#ifndef DASP_SPMV3_H
#define DASP_SPMV3_H

#include "common.h"
#include "utils.h"

struct DASPSparseMatrix {
    // === 1. Long Part ===
    MAT_VAL_TYPE *dlongA_val;
    int          *dlongA_cid;
    MAT_VAL_TYPE *dwarp_val;
    MAT_PTR_TYPE *dlongA_rpt;
    int           row_long;

    // === 2. Regular Block Part ===
    MAT_VAL_TYPE *dregA_val;
    int          *dregA_cid;
    MAT_PTR_TYPE *dblockA_ptr;
    int           row_block;
    int           blocknum;

    // === 3. Irregular Part ===
    MAT_VAL_TYPE *dirregA_val;
    int          *dirregA_cid;
    MAT_PTR_TYPE *dirregA_rpt;

    // === 4. Short Part ===
    MAT_VAL_TYPE *dshort_val;
    int          *dshort_cid;
    int           short_row_1;
    int           common_13;
    int           short_row_34;
    int           short_row_2;
    MAT_PTR_TYPE  fill0_nnz_short13;
    MAT_PTR_TYPE  fill0_nnz_short34;

    // === 5. Scheduling Offsets ===
    int offset_reg;
    int offset_short1;
    int offset_short13;
    int offset_short34;
    int offset_short22;
};

template <int rowloop>
__global__ void dasp_spmv3(MAT_VAL_TYPE *dX_val, MAT_VAL_TYPE *dY_val, DASPSparseMatrix *A);

__host__ void spmv_all3(char *filename, MAT_VAL_TYPE *csrValA, MAT_PTR_TYPE *csrRowPtrA, int *csrColIdxA, 
    MAT_VAL_TYPE *X_val, MAT_VAL_TYPE *Y_val, int *order_rid, int rowA, int colA, MAT_PTR_TYPE nnzA, int NUM, double threshold, int block_longest);

#endif