/*
 *   -- clMAGMA (version 0.1) --
 *      Univ. of Tennessee, Knoxville
 *      Univ. of California, Berkeley
 *      Univ. of Colorado, Denver
 *      April 2012
 *
 * @author Mark Gates
 * @precisions normal z -> s d c
 */

#ifndef MAGMA_Z_H
#define MAGMA_Z_H

#include "magma_types.h"

#define PRECISION_z

#ifdef __cplusplus
extern "C" {
#endif

/* ////////////////////////////////////////////////////////////////////////////
   -- MAGMA function definitions / Data on CPU
*/
magma_err_t
magma_zgetrf(magma_int_t m, magma_int_t n,
             magmaDoubleComplex *a, magma_int_t lda,
             magma_int_t *ipiv, magma_int_t *info,
             magma_queue_t queue );
magma_err_t
magma_zgetrf3(magma_int_t m, magma_int_t n,
             magmaDoubleComplex *a, magma_int_t lda, magmaDoubleComplex *da, magma_int_t ldda,
             magma_int_t *ipiv, magma_int_t *d_ipiv, magma_int_t *info,
             magma_queue_t queue );


magma_err_t
magma_zpotrf(
        magma_int_t uplo,
        magma_int_t n, 
        magmaDoubleComplex_ptr hA, magma_int_t lda, 
        magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zpotrf3(
        magma_int_t uplo,
        magma_int_t n, 
        magmaDoubleComplex_ptr hA, magma_int_t lda, magmaDoubleComplex_ptr dA, magma_int_t ldda,
        magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgeqrf(magma_int_t m, magma_int_t n,
             magmaDoubleComplex *hA, magma_int_t lda, 
	     magmaDoubleComplex *tau, magmaDoubleComplex *hwork,
             magma_int_t lwork, magma_int_t *info,
             magma_queue_t queue );

magma_err_t
magma_zgeqrf3(magma_int_t m, magma_int_t n,
             magmaDoubleComplex *hA, magma_int_t lda, magmaDoubleComplex *dA, magma_int_t ldda, 
	     magmaDoubleComplex *tau, magmaDoubleComplex *hwork,
             magma_int_t lwork, magma_int_t *info,
             magma_queue_t queue );

magma_err_t
magma_zgetrf2(magma_int_t m, magma_int_t n,
              magmaDoubleComplex *a, magma_int_t lda,
              magma_int_t *ipiv, 
              magmaDoubleComplex_ptr dA, magma_int_t ldda, magma_int_t *d_ipiv,
              magma_int_t *info, magma_queue_t queue );

magma_err_t
magma_zunmtr( magma_side_t side, magma_uplo_t uplo, magma_trans_t trans,
              magma_int_t m, magma_int_t n,
              magmaDoubleComplex *a,    magma_int_t lda,
              magmaDoubleComplex *tau,
              magmaDoubleComplex *c,    magma_int_t ldc,
              magmaDoubleComplex *work, magma_int_t lwork,
              magma_int_t *info, magma_queue_t queue );

#if defined(PRECISION_z) || defined(PRECISION_c)
magma_err_t  
magma_zgeev(  magma_job_t jobvl, magma_job_t jobvr, magma_int_t n,
              magmaDoubleComplex *a, magma_int_t lda,
              magmaDoubleComplex *w,
              magmaDoubleComplex *vl, magma_int_t ldvl,
              magmaDoubleComplex *vr, magma_int_t ldvr,
              magmaDoubleComplex *work, magma_int_t lwork,
              double *rwork, magma_int_t *info, magma_queue_t queue);

magma_err_t 
magma_zgesvd( magma_job_t jobu, magma_job_t jobvt, magma_int_t m, magma_int_t n,
              magmaDoubleComplex *a,    magma_int_t lda, double *s,
              magmaDoubleComplex *u,    magma_int_t ldu,
              magmaDoubleComplex *vt,   magma_int_t ldvt,
              magmaDoubleComplex *work, magma_int_t lwork,
              double *rwork, magma_int_t *info, magma_queue_t queue );

magma_err_t 
magma_zheevd( magma_job_t jobz, magma_uplo_t uplo, magma_int_t n,
              magmaDoubleComplex *a, magma_int_t lda, double *w,
              magmaDoubleComplex *work, magma_int_t lwork,
              double *rwork, magma_int_t lrwork,
              magma_int_t *iwork, magma_int_t liwork, magma_int_t *info,
              magma_queue_t queue );

magma_err_t 
magma_zstedx( char range, magma_int_t n, double vl, double vu,
              magma_int_t il, magma_int_t iu, double *D, double *E,
              magmaDoubleComplex *Z, magma_int_t ldz,
              double *rwork, magma_int_t ldrwork, magma_int_t *iwork,
              magma_int_t liwork, double *dwork, magma_int_t *info,
              magma_queue_t queue );

#else /* not (defined(PRECISION_z) || defined(PRECISION_c)) */

magma_err_t  
magma_zgeev(  magma_job_t jobvl, magma_job_t jobvr, magma_int_t n,
              magmaDoubleComplex *a,    magma_int_t lda,
              magmaDoubleComplex *wr, magmaDoubleComplex *wi,
              magmaDoubleComplex *vl,   magma_int_t ldvl,
              magmaDoubleComplex *vr,   magma_int_t ldvr,
              magmaDoubleComplex *work, magma_int_t lwork,
              magma_int_t *info, magma_queue_t queue);

magma_err_t 
magma_zgesvd( magma_job_t jobu, magma_job_t jobvt, magma_int_t m, magma_int_t n,
              magmaDoubleComplex *a,    magma_int_t lda, double *s,
              magmaDoubleComplex *u,    magma_int_t ldu,
              magmaDoubleComplex *vt,   magma_int_t ldvt,
              magmaDoubleComplex *work, magma_int_t lwork,
              magma_int_t *info, magma_queue_t queue );

magma_err_t 
magma_zheevd( magma_job_t jobz, magma_uplo_t uplo, magma_int_t n,
              magmaDoubleComplex *a, magma_int_t lda, double *w,
              magmaDoubleComplex *work, magma_int_t lwork,
              magma_int_t *iwork, magma_int_t liwork, magma_int_t *info, 
              magma_queue_t queue);

magma_err_t 
magma_zstedx( char range, magma_int_t n, double vl, double vu,
              magma_int_t il, magma_int_t iu, double *d, double *e,
              double *z, magma_int_t ldz,
              double *work, magma_int_t lwork,
              magma_int_t *iwork, magma_int_t liwork,
              double *dwork, magma_int_t *info, magma_queue_t queue);

magma_err_t 
magma_zlaex0( magma_int_t n, double *d, double *e, double *q, magma_int_t ldq,
              double *work, magma_int_t *iwork, double *dwork,
              char range, double vl, double vu,
              magma_int_t il, magma_int_t iu, magma_int_t *info,
              magma_queue_t queue);

magma_err_t 
magma_zlaex1( magma_int_t n, double *d, double *q, magma_int_t ldq,
              magma_int_t *indxq, double rho, magma_int_t cutpnt,
              double *work, magma_int_t *iwork, double *dwork,
              char range, double vl, double vu,
              magma_int_t il, magma_int_t iu, magma_int_t *info,
              magma_queue_t queue);

magma_err_t 
magma_zlaex3( magma_int_t k, magma_int_t n, magma_int_t n1, double *d,
              double *q, magma_int_t ldq, double rho,
              double *dlamda, double *q2, magma_int_t *indx,
              magma_int_t *ctot, double *w, double *s, magma_int_t *indxq,
              double *dwork,
              char range, double vl, double vu, magma_int_t il, magma_int_t iu,
              magma_int_t *info, magma_queue_t queue );

#endif /* not (defined(PRECISION_z) || defined(PRECISION_c)) */

/* //////////////////////////////////////////////////////////////////////////// 
 -- MAGMA function definitions / Data on MIC
*/

magma_err_t
magma_zgebrd(magma_int_t m, magma_int_t n,
             magmaDoubleComplex *a, magma_int_t lda, double *d, double *e,
             magmaDoubleComplex *tauq, magmaDoubleComplex *taup,
             magmaDoubleComplex *work, magma_int_t lwork,
             magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgeqrf2_mic(
        magma_int_t m, magma_int_t n, 
        magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda, 
        magmaDoubleComplex *tau, magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgetrf_mic(
        magma_int_t m, magma_int_t n, 
        magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda, 
        magma_int_t *ipiv, magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgetrf_mmic(
        magma_int_t num_mics, magma_int_t m, magma_int_t n, 
        magmaDoubleComplex_ptr *dA, magma_int_t ldda, 
        magma_int_t *ipiv, magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgeqrf2_mmic(
        magma_int_t num_mics, magma_int_t m, magma_int_t n, 
        magmaDoubleComplex_ptr *dlA, magma_int_t ldda, 
        magmaDoubleComplex *tau, magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zlarfb_mic( 
        int side, int trans, int direct, int storev, 
        magma_int_t m, magma_int_t n, magma_int_t k,
        magmaDoubleComplex_ptr dV, size_t dV_offset, magma_int_t ldv,
        magmaDoubleComplex_ptr dT, size_t dT_offset, magma_int_t ldt, 
        magmaDoubleComplex_ptr dC, size_t dC_offset, magma_int_t ldc,
        magmaDoubleComplex_ptr dwork, size_t dwork_offset, magma_int_t ldwork,
        magma_queue_t queue);

magma_err_t
magma_zlarfb_mic_gemm( 
        int side, int trans, int direct, int storev, 
        magma_int_t m, magma_int_t n, magma_int_t k,
        magmaDoubleComplex_ptr dV, size_t dV_offset, magma_int_t ldv,
        magmaDoubleComplex_ptr dT, size_t dT_offset, magma_int_t ldt, 
        magmaDoubleComplex_ptr dC, size_t dC_offset, magma_int_t ldc,
        magmaDoubleComplex_ptr dwork, size_t dwork_offset, magma_int_t ldwork,
        magmaDoubleComplex_ptr dworkvt, size_t dworkvt_offset, magma_int_t ldworkvt,
        magma_queue_t queue);

magma_err_t
magma_zpotrf_mic(
        int uplo,
        magma_int_t n, 
        magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda, 
        magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zpotrf_mmic(
        magma_int_t num_mics,
        int uplo,
        magma_int_t n, 
        magmaDoubleComplex_ptr *dA, magma_int_t ldda, 
        magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zpotrs_mic(
         magma_uplo_t uplo, magma_int_t n, magma_int_t nrhs,
         magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
         magmaDoubleComplex_ptr dB, size_t dB_offset, magma_int_t lddb,
         magma_err_t *info, magma_queue_t queue );

magma_err_t
magma_zposv(
                magma_uplo_t uplo, magma_int_t n, magma_int_t nrhs,
                magmaDoubleComplex_ptr A, magma_int_t ldda,
                magmaDoubleComplex_ptr B, magma_int_t lddb,
                magma_err_t *info, magma_queue_t queue );

magma_err_t
magma_zposv_mic(
                magma_uplo_t uplo, magma_int_t n, magma_int_t nrhs,
                magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
                magmaDoubleComplex_ptr dB, size_t dB_offset, magma_int_t lddb,
                magma_err_t *info, magma_queue_t queue );

magma_int_t magma_zgetri_mic( magma_int_t n,
		magmaDoubleComplex *dA, magma_int_t ldda, magma_int_t *ipiv,
		magmaDoubleComplex *dwork, magma_int_t lwork, magma_int_t *info, magma_queue_t queue);

magma_int_t magma_ztrtri_mic( magma_uplo_t uplo,  magma_diag_t diag, magma_int_t n,
		magmaDoubleComplex *dA, magma_int_t ldda, magma_int_t *info, magma_queue_t queue);
magma_err_t
magma_zgetrs_mic(magma_trans_t trans, magma_int_t n, magma_int_t nrhs,
                 magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
                 magma_int_t *ipiv,
                 magmaDoubleComplex_ptr dB, size_t dB_offset, magma_int_t lddb,
                 magma_int_t *info, magma_queue_t queue);
magma_int_t magma_zgesv ( magma_int_t n, magma_int_t nrhs,
		magmaDoubleComplex *A, magma_int_t lda, magma_int_t *ipiv,
		magmaDoubleComplex *B, magma_int_t ldb, magma_int_t *info, magma_queue_t queue);
magma_err_t
magma_zgesv_mic( magma_int_t n, magma_int_t nrhs,
                 magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
                 magma_int_t *ipiv,
                 magmaDoubleComplex_ptr dB, size_t dB_offset, magma_int_t lddb,
                 magma_err_t *info, magma_queue_t queue );

magma_int_t
magma_zunmqr_mic(magma_side_t side, magma_trans_t trans,
                 magma_int_t m, magma_int_t n, magma_int_t k,
                 magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
                 magmaDoubleComplex *tau,
                 magmaDoubleComplex_ptr dC, size_t dC_offset, magma_int_t lddc,
                 magmaDoubleComplex *hwork, magma_int_t lwork,
                 magmaDoubleComplex_ptr dT, size_t dT_offset, magma_int_t nb,
                 magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgeqrs_mic(magma_int_t m, magma_int_t n, magma_int_t nrhs,
                 magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t ldda,
                 magmaDoubleComplex *tau,   magmaDoubleComplex_ptr dT, size_t dT_offset,
                 magmaDoubleComplex_ptr dB, size_t dB_offset, magma_int_t lddb,
                 magmaDoubleComplex *hwork, magma_int_t lwork,
                 magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zgeqrf_mic( magma_int_t m, magma_int_t n,
                  magmaDoubleComplex_ptr dA, size_t dA_offset,  magma_int_t ldda,
                  magmaDoubleComplex *tau, magmaDoubleComplex_ptr dT, size_t dT_offset,
                  magma_int_t *info, magma_queue_t queue);

magma_int_t
magma_zgels_mic( magma_trans_t trans, magma_int_t m, magma_int_t n, magma_int_t nrhs,
                 magmaDoubleComplex_ptr dA, size_t dA_offset,  magma_int_t ldda,
                 magmaDoubleComplex_ptr dB, size_t dB_offset,  magma_int_t lddb,
                 magmaDoubleComplex *hwork, magma_int_t lwork,
                 magma_int_t *info, magma_queue_t queue );

magma_int_t
magma_zgehrd(   magma_int_t n, magma_int_t ilo, magma_int_t ihi,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex *tau,
                magmaDoubleComplex *work, magma_int_t lwork,
                magmaDoubleComplex_ptr dT, size_t dT_offset,
                magma_int_t *info, magma_queue_t queue );

magma_int_t
magma_zlabrd_mic( magma_int_t m, magma_int_t n, magma_int_t nb,
                  magmaDoubleComplex *a, magma_int_t lda,
                  magmaDoubleComplex_ptr da, size_t da_offset, magma_int_t ldda,
                  double *d, double *e, magmaDoubleComplex *tauq, magmaDoubleComplex *taup,
                  magmaDoubleComplex *x, magma_int_t ldx,
                  magmaDoubleComplex_ptr dx, size_t dx_offset, magma_int_t lddx,
                  magmaDoubleComplex *y, magma_int_t ldy,
                  magmaDoubleComplex_ptr dy, size_t dy_offset, magma_int_t lddy,
                  magma_queue_t queue );

magma_err_t
magma_zlahr2(   magma_int_t n, magma_int_t k, magma_int_t nb,
                magmaDoubleComplex_ptr da, size_t da_offset, magmaDoubleComplex_ptr dv, size_t dv_offset,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex *tau, magmaDoubleComplex *t, magma_int_t ldt,
                magmaDoubleComplex *y, magma_int_t ldy,
                magma_queue_t queue     );

magma_err_t
magma_zlahru(   magma_int_t n, magma_int_t ihi, magma_int_t k, magma_int_t nb,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex_ptr d_a, size_t d_a_offset, magmaDoubleComplex_ptr y, size_t y_offset,
                magmaDoubleComplex_ptr v, size_t v_offset, magmaDoubleComplex_ptr d_t, size_t dt_offset,
                magmaDoubleComplex_ptr d_work, size_t d_work_offset, magma_queue_t queue );

magma_err_t
magma_zunghr(   magma_int_t n, magma_int_t ilo, magma_int_t ihi,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex *tau,
                magmaDoubleComplex_ptr dT, size_t dT_offset, magma_int_t nb,
                magma_int_t *info, magma_queue_t queue );

magma_err_t
magma_zungqr(   magma_int_t m, magma_int_t n, magma_int_t k,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex *tau, magmaDoubleComplex_ptr dT, size_t dT_offset,
                magma_int_t nb, magma_int_t *info, magma_queue_t queue );

magma_err_t
magma_zungqr2(  magma_int_t m, magma_int_t n, magma_int_t k,
                magmaDoubleComplex *A, magma_int_t lda,
                magmaDoubleComplex *tau,
                magma_int_t *info, magma_queue_t queue);

magma_err_t 
magma_zunmql(   magma_side_t side, magma_trans_t trans,
                magma_int_t m, magma_int_t n, magma_int_t k,
                magmaDoubleComplex *a, magma_int_t lda,
                magmaDoubleComplex *tau,
                magmaDoubleComplex *c, magma_int_t ldc,
                magmaDoubleComplex *work, magma_int_t lwork,
                magma_int_t *info, magma_queue_t queue );

magma_err_t 
magma_zunmqr(   magma_side_t side, magma_trans_t trans,
                magma_int_t m, magma_int_t n, magma_int_t k,
                magmaDoubleComplex *a, magma_int_t lda, magmaDoubleComplex *tau,
                magmaDoubleComplex *c, magma_int_t ldc,
                magmaDoubleComplex *work, magma_int_t lwork, 
                magma_int_t *info, magma_queue_t queue);

magma_err_t 
magma_zunmtr(   magma_side_t side, magma_uplo_t uplo, magma_trans_t trans,
                magma_int_t m, magma_int_t n,
                magmaDoubleComplex *a,    magma_int_t lda,
                magmaDoubleComplex *tau,
                magmaDoubleComplex *c,    magma_int_t ldc,
                magmaDoubleComplex *work, magma_int_t lwork,
                magma_int_t *info, magma_queue_t queue);

magma_err_t
magma_zlatrd(   magma_uplo_t uplo, magma_int_t n, magma_int_t nb,
                magmaDoubleComplex *a,  magma_int_t lda,
                double *e, magmaDoubleComplex *tau,
                magmaDoubleComplex *w,  magma_int_t ldw,
                magmaDoubleComplex_ptr da, size_t da_offset, magma_int_t ldda,
                magmaDoubleComplex_ptr dw, size_t dw_offset, magma_int_t lddw, magma_queue_t queue);

magma_err_t
magma_zhetrd(  magma_uplo_t uplo, magma_int_t n,
               magmaDoubleComplex *a, magma_int_t lda,
               double *d, double *e, magmaDoubleComplex *tau,
               magmaDoubleComplex *work, magma_int_t lwork,
               magma_int_t *info, magma_queue_t queue);

/* //////////////////////////////////////////////////////////////////////////// 
 -- MAGMA utility function definitions
*/

void magma_zprint    ( magma_int_t m, magma_int_t n, magmaDoubleComplex     *A, magma_int_t lda  );
void magma_zprint_gpu( magma_int_t m, magma_int_t n, magmaDoubleComplex_ptr dA, magma_int_t ldda );

void zpanel_to_q(magma_uplo_t uplo, int ib, magmaDoubleComplex *A, int lda, magmaDoubleComplex *work);
void zq_to_panel(magma_uplo_t uplo, int ib, magmaDoubleComplex *A, int lda, magmaDoubleComplex *work);

#ifdef __cplusplus
}
#endif

#undef PRECISION_z
#endif /* MAGMA_Z_H */
