#ifndef MAGMA_Z_SERVER_H
#define MAGMA_Z_SERVER_H

/*
 *   -- micMAGMA (version 0.1) --
 *      Univ. of Tennessee, Knoxville
 *      Univ. of California, Berkeley
 *      Univ. of Colorado, Denver
 *      April 2012
 *
 *   @author Azzam Haidar
 *   @author Khairul Kabir 
 *
 *   @precisions normal z -> s d c
 */

#include <mkl.h>

#include <mkl_trans.h>
#include <scif.h>
#include <fcntl.h>
#include <offload.h>

#if 0
#ifdef __MIC__
#define _M512_TYPED
#include <lmmintrin.h>
#endif
#endif
//#include <immintrin.h>

#include "magma.h"
#include "magma_z_bindings.h"

// Flops formula
#define MICFMULS_GEMM(m, n, k) ((m) * (n) * (k))
#define MICFADDS_GEMM(m, n, k) ((m) * (n) * (k))
#define MICFMULS_SYMM(side, m, n) (((side) == MagmaLeft) ? MICFMULS_GEMM(m, m, n) : MICFMULS_GEMM(m, n, n))
#define MICFADDS_SYMM(side, m, n) (((side) == MagmaLeft) ? MICFADDS_GEMM(m, m, n) : MICFADDS_GEMM(m, n, n))
#define MICFMULS_GEMV(m, n)   ((m) * (n))
#define MICFADDS_GEMV(m, n)   ((m) * (n))
#define MICFMULS_TRMM_L(m, n) (0.5 * (n) * (m) * ((m)+1))
#define MICFADDS_TRMM_L(m, n) (0.5 * (n) * (m) * ((m)-1))
#define MICFMULS_TRMM_R(m, n) (0.5 * (m) * (n) * ((n)+1))
#define MICFADDS_TRMM_R(m, n) (0.5 * (m) * (n) * ((n)-1))
#define MICFMULS_TRSM_L(m, n) (0.5 * (n) * (m) * ((m)+1))
#define MICFADDS_TRSM_L(m, n) (0.5 * (n) * (m) * ((m)-1))
#define MICFMULS_TRSM_R(m, n) (0.5 * (m) * (n) * ((n)+1))
#define MICFADDS_TRSM_R(m, n) (0.5 * (m) * (n) * ((n)-1))
#define MICFMULS_SYRK(k, n) (0.5 * (k) * (n) * ((n)+1))
#define MICFADDS_SYRK(k, n) (0.5 * (k) * (n) * ((n)+1))
#define MICFMULS_SYR2K(k, n) ((k) * (n) * (n)        )
#define MICFADDS_SYR2K(k, n) ((k) * (n) * (n) + (n)  )

#define MICFLOPS_GEMM(m, n, k) (MICFMULS_GEMM(m, n, k) + MICFADDS_GEMM(m, n, k))
#define MICFLOPS_SYMM(side, m, n) (MICFMULS_SYMM(side, m, n) + MICFADDS_SYMM(side, m, n))
#define MICFLOPS_GEMV(m, n)    (MICFMULS_GEMV(m, n) + MICFADDS_GEMV(m, n))
#define MICFLOPS_TRSM_L(m, n)  (MICFMULS_TRSM_L(m, n) + MICFADDS_TRSM_L(m, n))
#define MICFLOPS_TRSM_R(m, n)  (MICFMULS_TRSM_R(m, n) + MICFADDS_TRSM_R(m, n))

#define MICFLOPS_SYRK(k, n)    (MICFMULS_SYRK(k, n) + MICFADDS_SYRK(k, n))
#define MICFLOPS_SYR2K(k, n)   (MICFMULS_SYR2K(k, n) + MICFADDS_SYR2K(k, n))

void call_zcopy(magma_mic_zcopy_param zcopy_param);

void call_zgemm(magma_mic_zgemm_param zgemm_param);

void call_zhemm(magma_mic_zhemm_param zhemm_param);

void call_zgemv(magma_mic_zgemv_param zgemv_param);

void call_zhemv(magma_mic_zhemv_param hemv_param);

void call_zsymv2(magma_mic_zsymv2_param symv_param);

void call_ztrsm(magma_mic_ztrsm_param ztrsm_param);

void call_ztrsv(magma_mic_ztrsv_param ztrsv_param);

void call_ztrmv(magma_mic_ztrmv_param trmv_param);

void call_ztrmm(magma_mic_ztrmm_param ztrmm_param);

void call_zherk(magma_mic_zherk_param zherk_param);

void call_zherk_mmic(magma_mic_zherk_mmic_param zherk_mmic_param);

void call_zher2k(magma_mic_zher2k_param zher2k_param);

void call_zher2k_mmic(magma_mic_zher2k_mmic_param zher2k_mmic_param);

void call_zlarft(magma_mic_zlarft_param zlarft_param);

void call_zlarfb(magma_mic_zlarfb_param zlarfb_param);

void call_zlarfb_gemm(magma_mic_zlarfb_gemm_param zlarfb_gemm_param);

void call_zlaset(magma_mic_zlaset_param zlaset_param);

void call_ztranspose(magma_mic_ztranspose_param ztranspose_param);

void call_ztranspose_mkl(magma_mic_ztranspose_param ztranspose_param);

void call_zlaswp(magma_mic_zlaswp_param zlaswp_param);

void call_zswap(magma_mic_zswap_param zswap_param);

void call_ztrsmgemm(magma_mic_ztrsmgemm_param trsmgemm_param);

#define SREG_WIDTH 16
#define DREG_WIDTH 8

#define _MM512_LOAD_PPS _mm512_load_ps
#define _MM512_LOAD_PPD _mm512_load_pd

#define _MM512_STORE_PPS _mm512_store_ps
#define _MM512_STORE_PPD _mm512_store_pd

#define _MM512_I32LOEXTSCATTER_PPS _mm512_i32extscatter_ps
#define _MM512_I32LOEXTSCATTER_PPD _mm512_i32loextscatter_pd

#define __M512S __m512
#define __M512D __m512d
#endif // MAGMA_Z_SERVER_H
