/*
 *   -- 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_BLAS_Z_H
#define MAGMA_BLAS_Z_H

#include "magma_types.h"

#ifdef __cplusplus
extern "C" {
#endif

// ========================================
// copying sub-matrices (contiguous columns)
magma_err_t
magma_zsetmatrix(
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex const* hA_src, size_t hA_offset, magma_int_t ldha,
    magmaDoubleComplex_ptr    dA_dst, size_t dA_offset, magma_int_t ldda,
    magma_queue_t queue );

magma_err_t
magma_zgetmatrix(
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex_const_ptr dA_src, size_t dA_offset, magma_int_t ldda,
    magmaDoubleComplex*          hA_dst, size_t hA_offset, magma_int_t ldha,
    magma_queue_t queue );

magma_err_t
magma_zsetmatrix_async(
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex const* hA_src, size_t hA_offset, magma_int_t ldha,
    magmaDoubleComplex_ptr    dA_dst, size_t dA_offset, magma_int_t ldda,
    magma_queue_t queue, magma_event_t *event );

magma_err_t
magma_zgetmatrix_async(
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex_const_ptr dA_src, size_t dA_offset, magma_int_t ldda,
    magmaDoubleComplex*          hA_dst, size_t hA_offset, magma_int_t ldha,
    magma_queue_t queue, magma_event_t *event );

magma_err_t
magma_zsetintarray_async(
    magma_int_t lda, magma_int_t const* hA_src, size_t hA_offset, magma_int_t *dA_dst, size_t dA_offset, magma_queue_t queue, magma_event_t *event );


// ========================================
// matrix transpose and swapping functions
//magma_err_t
//magma_zinplace_transpose(
//    magmaDoubleComplex_ptr dA, size_t dA_offset, int lda, int n,
//    magma_queue_t queue );

#define magma_zinplace_transpose( dAT, dAT_offset, ldda, lddat, queue ) ; 

//magma_err_t
//magma_ztranspose2(
//    magmaDoubleComplex_ptr odata, size_t odata_offset, int ldo,
//    magmaDoubleComplex_ptr idata, size_t idata_offset, int ldi,
//    int m, int n,
//    magma_queue_t queue );

#define magma_ztranspose2( dAT, dAT_offset, lddat, dA, dA_offset,  ldda, m, n, queue ) \
    magma_ztranspose(dAT, 0, lddat, dA, 0, ldda, m, n, queue)

magma_err_t
magma_ztranspose(
    magmaDoubleComplex_ptr odata, int offo, int ldo,
    magmaDoubleComplex_ptr idata, int offi, int ldi,
    int m, int n,
    magma_queue_t queue );

magma_err_t
magma_zswap(magma_int_t n, magmaDoubleComplex *dA1T, magma_int_t lda1, magmaDoubleComplex *dA2T, magma_int_t lda2, magma_queue_t queue);

magma_err_t
magma_zlaswp(magma_int_t n, magmaDoubleComplex_ptr d_A, magma_int_t ldda, magma_int_t k1, magma_int_t k2, magma_int_t *d_ipiv, magma_int_t incx, magma_queue_t queue);

// ========================================
// BLAS functions
magma_err_t
magma_zcopy(
    magma_int_t n,
    magmaDoubleComplex_ptr dx, size_t dx_offset, magma_int_t incx,
    magmaDoubleComplex_ptr dy, size_t dy_offset, magma_int_t incy,
    magma_queue_t queue );

magma_err_t
magma_zgemm(
    magma_trans_t transA, magma_trans_t transB,
    magma_int_t m, magma_int_t n, magma_int_t k,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dB, size_t dB_offset, magma_int_t ldb,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_queue_t queue );

magma_err_t
magma_zgemv(
    magma_trans_t transA,
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dx, size_t dx_offset, magma_int_t incx,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dy, size_t dy_offset, magma_int_t incy,
    magma_queue_t queue );

magma_err_t
magma_zhemm(
    magma_side_t side, magma_uplo_t uplo,
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dB, size_t dB_offset, magma_int_t ldb,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_queue_t queue );

magma_err_t
magma_zhemm_ours(
    magma_side_t side, magma_uplo_t uplo,
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dB, size_t dB_offset, magma_int_t ldb,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_int_t globaldAoffset,
    magma_queue_t queue );

magma_err_t
magma_zhemv(
    magma_uplo_t uplo,
    magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dx, size_t dx_offset, magma_int_t incx,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dy, size_t dy_offset, magma_int_t incy,
    magma_queue_t queue );

magma_err_t
magma_zsymv2(
    magma_uplo_t uplo,
    magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dx, size_t dx_offset, magma_int_t incx,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dy, size_t dy_offset, magma_int_t incy,
    magma_queue_t queue );


magma_err_t
magma_zherk(
    magma_uplo_t uplo, magma_trans_t trans,
    magma_int_t n, magma_int_t k,
    double alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
    double beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_queue_t queue );

void magmablas_zherk_mmic2(                                                                                                                    
    char uplo, char trans, magma_int_t n, magma_int_t k,                                                                                
    double alpha, magmaDoubleComplex *dA[], magma_int_t lda, magma_int_t aoff,                                                                             
    double beta,           magmaDoubleComplex *dC[], magma_int_t ldc,  magma_int_t offset, 
    magma_int_t nmic, magma_int_t nb, magma_queue_t queue);  
 
magma_err_t
magma_zherk_mmic(                                                                                                                    
    magma_uplo_t uplo, magma_trans_t trans, magma_int_t n, magma_int_t k,                                                                                
    double alpha, magmaDoubleComplex_const_ptr dA, magma_int_t lda, magma_int_t dAoff,                                                                             
    double beta, magmaDoubleComplex_const_ptr dC, magma_int_t ldc,  magma_int_t offset, 
    magma_int_t nmic, magma_int_t nb, magma_int_t my_id);  

magma_err_t
magma_zher2k(
    magma_uplo_t uplo, magma_trans_t trans,
    magma_int_t n, magma_int_t k,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
    magmaDoubleComplex_const_ptr dB, size_t dB_offset, magma_int_t ldb,
    double beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_queue_t queue );

void magmablas_zher2k_mmic2(                                                                                                                    
    char uplo, char trans, magma_int_t n, magma_int_t k,                                                                                
    magmaDoubleComplex alpha, magmaDoubleComplex *dA[], magma_int_t lda, magma_int_t aoff,                                                                             
    magmaDoubleComplex *dB[], magma_int_t ldb, magma_int_t boff,                                               
    double beta,           magmaDoubleComplex *dC[], magma_int_t ldc,  magma_int_t offset, 
    magma_int_t nmic, magma_int_t nb, magma_queue_t queue);  

magma_err_t
magma_zher2k_mmic(
    magma_uplo_t uplo, magma_trans_t trans, magma_int_t n, magma_int_t k,                                                                                
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, magma_int_t lda, magma_int_t dAoff,                                                                             
    magmaDoubleComplex_const_ptr dB, magma_int_t ldb, magma_int_t dBoff,                                               
    double beta,           magmaDoubleComplex_const_ptr dC, magma_int_t ldc,  magma_int_t offset, 
    magma_int_t nmic, magma_int_t nb, magma_int_t my_id);  

magma_err_t
magma_ztrsm(
    magma_side_t side, magma_uplo_t uplo, magma_trans_t trans, magma_diag_t diag,
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_ptr       dB, size_t dB_offset, magma_int_t ldb,
    magma_queue_t queue );

magma_err_t
magma_ztrsv(
    magma_uplo_t uplo, magma_trans_t trans, magma_diag_t diag,
    magma_int_t n,
    magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
    magmaDoubleComplex_ptr dx, size_t dx_offset, magma_int_t incx,
    magma_queue_t queue );

magma_err_t
magma_ztrmm(
    magma_side_t side, magma_uplo_t uplo, magma_trans_t trans, magma_diag_t diag,
    magma_int_t m, magma_int_t n,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_ptr       dB, size_t dB_offset, magma_int_t ldb,
    magma_queue_t queue );

magma_err_t
magma_ztrmv(
    magma_uplo_t uplo, magma_trans_t trans, magma_diag_t diag,
    magma_int_t n,
    magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
    magmaDoubleComplex_ptr dx, size_t dx_offset, magma_int_t incx,
    magma_queue_t queue );



magma_err_t
magma_zlarfb( magma_int_t side, magma_int_t trans, magma_int_t direct, magma_int_t 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_gemm(magma_int_t side, magma_int_t trans, magma_int_t direct, magma_int_t 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_zlaset(magma_uplo_t uplo,
             magma_int_t m, magma_int_t n,
             magmaDoubleComplex alpha, magmaDoubleComplex beta,
             magmaDoubleComplex_ptr dA, size_t dA_offset, magma_int_t lda,
             magma_queue_t queue);

// ========================================
// BLAS functions -- combined for MIC
magma_err_t
magma_ztrsmgemm(
    magma_side_t side, magma_uplo_t uplo, magma_trans_t trans, magma_diag_t diag,
    magma_int_t tm, magma_int_t tn,
    magmaDoubleComplex talpha, magmaDoubleComplex_const_ptr tdA, size_t tdA_offset, magma_int_t tlda,
                              magmaDoubleComplex_ptr       tdB, size_t tdB_offset, magma_int_t tldb,
    magma_trans_t transA, magma_trans_t transB,
    magma_int_t m, magma_int_t n, magma_int_t k,
    magmaDoubleComplex alpha, magmaDoubleComplex_const_ptr dA, size_t dA_offset, magma_int_t lda,
                              magmaDoubleComplex_const_ptr dB, size_t dB_offset, magma_int_t ldb,
    magmaDoubleComplex beta,  magmaDoubleComplex_ptr       dC, size_t dC_offset, magma_int_t ldc,
    magma_queue_t queue );

#ifdef __cplusplus
}
#endif

#endif        //  #ifndef MAGMA_BLAS_H
