text: /*
  //@HEADER
  // ************************************************************************
  //
  //               KokkosKernels 0.9: Linear Algebra and Graph Kernels
  //                 Copyright 2017 Sandia Corporation
  //
  // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  // the U.S. Government retains certain rights in this software.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  //
  // 1. Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  //
  // 2. Redistributions in binary form must reproduce the above copyright
  // notice, this list of conditions and the following disclaimer in the
  // documentation and/or other materials provided with the distribution.
  //
  // 3. Neither the name of the Corporation nor the names of the
  // contributors may be used to endorse or promote products derived from
  // this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
  // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
  // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  //
  // Questions? Contact Siva Rajamanickam (srajama@sandia.gov)
  //
  // ************************************************************************
  //@HEADER
  */
  
  #include <Kokkos_MemoryTraits.hpp>
  #include <Kokkos_Core.hpp>
  #include <iostream>
  #include <string>
  
  //#define KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
  
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
  #include "cusparse.h"
  #endif
  #ifndef _SPGEMMHANDLE_HPP
  #define _SPGEMMHANDLE_HPP
  //#define VERBOSE
  
  namespace KokkosSparse{
  
  //TODO:SPGEMM_KK_MEMORY2 option is for testing in openmp.
  //it wont work on cuda, not bind to a test program.
  //hidden parameter for StringToSPGEMMAlgorithm for now.
  enum SPGEMMAlgorithm{
  		/*DEFAULT*/SPGEMM_KK, SPGEMM_KK_DENSE, SPGEMM_KK_MEMORY, SPGEMM_KK_LP, //KKVARIANTS
  		SPGEMM_CUSPARSE,  SPGEMM_CUSP, SPGEMM_MKL, SPGEMM_MKL2PHASE, SPGEMM_VIENNA, //TPLS
  
  		//TRIANGLE COUNTING SPECIALIZED
  		SPGEMM_KK_TRIANGLE_AI, //SPGEMM_KK_TRIANGLE_DEFAULT, SPGEMM_KK_TRIANGLE_MEM, SPGEMM_KK_TRIANGLE_DENSE,
  		SPGEMM_KK_TRIANGLE_IA_UNION, //SPGEMM_KK_TRIANGLE_DEFAULT_IA_UNION, SPGEMM_KK_TRIANGLE_MEM_IA_UNION, SPGEMM_KK_TRIANGLE_DENSE_IA_UNION,
  		SPGEMM_KK_TRIANGLE_IA,//SPGEMM_KK_TRIANGLE_IA_DEFAULT, SPGEMM_KK_TRIANGLE_IA_MEM, SPGEMM_KK_TRIANGLE_IA_DENSE,
  		SPGEMM_KK_TRIANGLE_LL,
  		SPGEMM_KK_TRIANGLE_LU,
  
  		//below research code.
  		SPGEMM_KK_MULTIMEM, SPGEMM_KK_OUTERMULTIMEM,
  		SPGEMM_DEFAULT, SPGEMM_DEBUG, SPGEMM_SERIAL,
  		SPGEMM_KK_CUCKOO, //USE CUCKOO HASHING
  		SPGEMM_KK_TRACKED_CUCKOO, //USE SCALED CUCKOO HASHING
  		SPGEMM_KK_TRACKED_CUCKOO_F, //USE SCALED FANCY CUCKOO HASHING
  		SPGEMM_KK_SPEED,  // DENSE ACCUMULATOR SAME AS SPEED
  		SPGEMM_KK_MEMORY_SORTED,
  		SPGEMM_KK_MEMORY_TEAM,
  		SPGEMM_KK_MEMORY_BIGTEAM,
  		SPGEMM_KK_MEMORY_SPREADTEAM,
  		SPGEMM_KK_MEMORY_BIGSPREADTEAM,
  		SPGEMM_KK_MEMORY2,
  		SPGEMM_KK_COLOR,
  		SPGEMM_KK_MULTICOLOR,
  		SPGEMM_KK_MULTICOLOR2,
  		SPGEMM_KK_MEMSPEED};
  
  enum SPGEMMAccumulator{
    SPGEMM_ACC_DEFAULT, SPGEMM_ACC_DENSE, SPGEMM_ACC_SPARSE,
  };
  template <class size_type_, class lno_t_, class scalar_t_,
            class ExecutionSpace,
            class TemporaryMemorySpace,
            class PersistentMemorySpace>
  class SPGEMMHandle{
  public:
    typedef ExecutionSpace HandleExecSpace;
    typedef TemporaryMemorySpace HandleTempMemorySpace;
    typedef PersistentMemorySpace HandlePersistentMemorySpace;
  
  
    typedef typename std::remove_const<size_type_>::type  size_type;
    typedef const size_type const_size_type;
  
    typedef typename std::remove_const<lno_t_>::type  nnz_lno_t;
    typedef const nnz_lno_t const_nnz_lno_t;
  
    typedef typename std::remove_const<scalar_t_>::type  nnz_scalar_t;
    typedef const nnz_scalar_t const_nnz_scalar_t;
  
  
    typedef typename Kokkos::View<size_type *, HandleTempMemorySpace> row_lno_temp_work_view_t;
    typedef typename Kokkos::View<size_type *, HandlePersistentMemorySpace> row_lno_persistent_work_view_t;
    typedef typename row_lno_persistent_work_view_t::HostMirror row_lno_persistent_work_host_view_t; //Host view type
  
    typedef typename Kokkos::View<nnz_scalar_t *, HandleTempMemorySpace> scalar_temp_work_view_t;
    typedef typename Kokkos::View<nnz_scalar_t *, HandlePersistentMemorySpace> scalar_persistent_work_view_t;
  
  
    typedef typename Kokkos::View<nnz_lno_t *, HandleTempMemorySpace> nnz_lno_temp_work_view_t;
    typedef typename Kokkos::View<nnz_lno_t *, HandlePersistentMemorySpace> nnz_lno_persistent_work_view_t;
    typedef typename nnz_lno_persistent_work_view_t::HostMirror nnz_lno_persistent_work_host_view_t; //Host view type
  
  
  
  
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
    struct cuSparseHandleType{
      cusparseHandle_t handle;
      cusparseOperation_t transA;
      cusparseOperation_t transB;
      cusparseMatDescr_t a_descr;
      cusparseMatDescr_t b_descr;
      cusparseMatDescr_t c_descr;
      cuSparseHandleType(bool transposeA, bool transposeB){
        cusparseStatus_t status;
        status= cusparseCreate(&handle);
        if (status != CUSPARSE_STATUS_SUCCESS) {
          throw std::runtime_error ("cusparseCreate ERROR\n");
          //return;
        }
        cusparseSetPointerMode(handle, CUSPARSE_POINTER_MODE_HOST);
  
        if (transposeA){
          transA = CUSPARSE_OPERATION_TRANSPOSE;
        }
        else {
          transA  = CUSPARSE_OPERATION_NON_TRANSPOSE;
        }
        if (transposeB){
          transB = CUSPARSE_OPERATION_TRANSPOSE;
        }
        else {
          transB  = CUSPARSE_OPERATION_NON_TRANSPOSE;
        }
  
  
        status = cusparseCreateMatDescr(&a_descr);
        if (status != CUSPARSE_STATUS_SUCCESS) {
          throw std::runtime_error ("cusparseCreateMatDescr a_descr ERROR\n");
          //return;
        }
        cusparseSetMatType(a_descr,CUSPARSE_MATRIX_TYPE_GENERAL);
        cusparseSetMatIndexBase(a_descr,CUSPARSE_INDEX_BASE_ZERO);
  
        status = cusparseCreateMatDescr(&b_descr);
        if (status != CUSPARSE_STATUS_SUCCESS) {
          throw std::runtime_error ("cusparseCreateMatDescr b_descr ERROR\n");
          //return;
        }
        cusparseSetMatType(b_descr,CUSPARSE_MATRIX_TYPE_GENERAL);
        cusparseSetMatIndexBase(b_descr,CUSPARSE_INDEX_BASE_ZERO);
  
        status = cusparseCreateMatDescr(&c_descr);
        if (status != CUSPARSE_STATUS_SUCCESS) {
          throw std::runtime_error ("cusparseCreateMatDescr  c_descr ERROR\n");
          //return;
        }
        cusparseSetMatType(c_descr,CUSPARSE_MATRIX_TYPE_GENERAL);
        cusparseSetMatIndexBase(c_descr,CUSPARSE_INDEX_BASE_ZERO);
      }
      ~cuSparseHandleType(){
        cusparseDestroyMatDescr(a_descr);
        cusparseDestroyMatDescr(b_descr);
        cusparseDestroyMatDescr(c_descr);
        cusparseDestroy(handle);
      }
    };
  
    typedef cuSparseHandleType SPGEMMcuSparseHandleType;
  #endif
  private:
    SPGEMMAlgorithm algorithm_type;
    SPGEMMAccumulator accumulator_type;
    size_type result_nnz_size;
  
    bool called_symbolic;
    bool called_numeric;
  
    int suggested_vector_size;
    int suggested_team_size;
    nnz_lno_t max_nnz_inresult;
    nnz_lno_t max_nnz_compressed_result;
  
    size_type compressed_b_size;
    row_lno_temp_work_view_t compressed_b_rowmap;// compressed_b_set_begins, compressed_b_set_nexts;
    nnz_lno_temp_work_view_t compressed_b_set_indices, compressed_b_sets;
  
    row_lno_temp_work_view_t compressed_c_rowmap;
  
    nnz_lno_temp_work_view_t c_column_indices;
  
    row_lno_temp_work_view_t tranpose_a_xadj, tranpose_b_xadj, tranpose_c_xadj;
    nnz_lno_temp_work_view_t tranpose_a_adj, tranpose_b_adj, tranpose_c_adj;
  
    bool transpose_a,transpose_b, transpose_c_symbolic;
  
  
    nnz_lno_t num_colors;
    nnz_lno_persistent_work_host_view_t color_xadj;
    nnz_lno_persistent_work_view_t color_adj, vertex_colors;
    nnz_lno_t num_multi_colors, num_used_colors;
    nnz_lno_persistent_work_view_t min_result_row_for_each_row;
  
  
    bool create_lower_triangular;
    int sort_lower_triangular; //0 - do not sort // 1 - sort // 2 - Algorithm decides (default)
    int sort_option ;
    nnz_lno_persistent_work_view_t lower_triangular_permutation;
  
    row_lno_persistent_work_view_t lower_triangular_matrix_rowmap;
    nnz_lno_persistent_work_view_t lower_triangular_matrix_entries;
  
  
    row_lno_persistent_work_view_t incidence_matrix_row_map;
    nnz_lno_persistent_work_view_t incidence_matrix_entries;
    bool compress_second_matrix;
  
  
    double multi_color_scale;
    int mkl_sort_option;
    bool calculate_read_write_cost;
  
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
    SPGEMMcuSparseHandleType *cuSPARSEHandle;
  #endif
    public:
  
    std::string coloring_input_file;
    std::string coloring_output_file;
  
    int min_hash_size_scale;
    double compression_cut_off;
    double first_level_hash_cut_off;
    size_t original_max_row_flops, original_overall_flops;
    row_lno_persistent_work_view_t row_flops;
  
    size_t compressed_max_row_flops, compressed_overall_flops;
  
    void set_first_level_hash_cut_off(double first_level_hash_cut_off_){
      this->first_level_hash_cut_off = first_level_hash_cut_off_;
    }
  
    double get_first_level_hash_cut_off(){
      return this->first_level_hash_cut_off;
    }
  
    void set_compression_cut_off(double compression_cut_off_){
      this->compression_cut_off = compression_cut_off_;
    }
  
    double get_compression_cut_off(){
      return this->compression_cut_off;
    }
    void set_min_hash_size_scale(int scale){
      min_hash_size_scale = scale;
    }
    int get_min_hash_size_scale(){
      return min_hash_size_scale;
    }
    void set_read_write_cost_calc(bool read_write_cost_cal){
      this->calculate_read_write_cost = read_write_cost_cal;
    }
    int get_read_write_cost_calc(){
      return this->calculate_read_write_cost;
    }
  
    typename Kokkos::View<int *, HandlePersistentMemorySpace> persistent_c_xadj, persistent_a_xadj, persistent_b_xadj, persistent_a_adj, persistent_b_adj;
    size_t MaxColDenseAcc;
    bool mkl_keep_output;
    bool mkl_convert_to_1base;
    bool is_compression_single_step;
  
    void set_mkl_sort_option(int mkl_sort_option_){
      this->mkl_sort_option = mkl_sort_option_;
    }
    int get_mkl_sort_option(){
      return this->mkl_sort_option;
    }
    void set_c_column_indices(nnz_lno_temp_work_view_t c_col_indices_){
      this->c_column_indices = c_col_indices_;
    }
  
    nnz_lno_temp_work_view_t get_c_column_indices(){
      return this->c_column_indices;
    }
  
    void set_color_xadj(
        nnz_lno_t num_colors_,
        nnz_lno_persistent_work_host_view_t color_xadj_,
        nnz_lno_persistent_work_view_t color_adj_,
        nnz_lno_persistent_work_view_t vertex_colors_,
        nnz_lno_t num_multi_colors_, nnz_lno_t num_used_colors_){
  
      num_colors = num_colors_;
      color_xadj = color_xadj_;
      color_adj = color_adj_;
      vertex_colors = vertex_colors_;
  
      num_multi_colors = num_multi_colors_;
      num_used_colors = num_used_colors_;
    }
  
    /**
     * \brief sets the result nnz size.
     * \param result_nnz_size: size of the output matrix.
     */
    void set_c_nnz(size_type result_nnz_size_){
      this->result_nnz_size = result_nnz_size_;
    }
    /**
     * \brief returns the result nnz size.
     */
    size_type get_c_nnz(){
      return this->result_nnz_size;
    }
  
    void set_multi_color_scale(double multi_color_scale_){
      this->multi_color_scale = multi_color_scale_;
    }
  
    double get_multi_color_scale(){
      return this->multi_color_scale;
    }
  
    void get_color_xadj(
        nnz_lno_t &num_colors_,
        nnz_lno_persistent_work_host_view_t &color_xadj_,
        nnz_lno_persistent_work_view_t &color_adj_,
        nnz_lno_persistent_work_view_t &vertex_colors_,
        nnz_lno_t &num_multi_colors_, nnz_lno_t &num_used_colors_){
      num_colors_ = num_colors;
      color_xadj_ = color_xadj;
      color_adj_ = color_adj ;
      num_multi_colors_ = num_multi_colors;
      num_used_colors_ = num_used_colors ;
      vertex_colors_ = vertex_colors;
    }
  
    void set_compressed_c(
        row_lno_temp_work_view_t compressed_c_rowmap_){
      compressed_c_rowmap = compressed_c_rowmap_;
    }
  
    void get_compressed_c(
        row_lno_temp_work_view_t &compressed_c_rowmap_){
      compressed_c_rowmap_ = compressed_c_rowmap;
    }
  
    //TODO: store transpose here.
    void get_c_transpose_symbolic(){}
  
    
    void set_sort_lower_triangular(int option){
      this->sort_lower_triangular = option;
    }
    int get_sort_lower_triangular(){
      return this->sort_lower_triangular;
    }
  
    void set_sort_option(int option){
      this->sort_option = option;
    }
    int get_sort_option(){
      return this->sort_option;
    }
  
    void set_create_lower_triangular(bool option){
      this->create_lower_triangular = option;
    }
    bool get_create_lower_triangular(){
      return this->create_lower_triangular;
    }
  
    void set_lower_triangular_permutation(nnz_lno_persistent_work_view_t ltp_){
      this->lower_triangular_permutation = ltp_;
    }
  
    nnz_lno_persistent_work_view_t get_lower_triangular_permutation(){
      return this->lower_triangular_permutation;
    }
  
    void set_lower_triangular_matrix(
        row_lno_persistent_work_view_t lower_triangular_matrix_rowmap_,
        nnz_lno_persistent_work_view_t lower_triangular_matrix_entries_){
      this->lower_triangular_matrix_rowmap = lower_triangular_matrix_rowmap_;
      this->lower_triangular_matrix_entries = lower_triangular_matrix_entries_;
    }
    void get_lower_triangular_matrix(
        row_lno_persistent_work_view_t &lower_triangular_matrix_rowmap_,
        nnz_lno_persistent_work_view_t &lower_triangular_matrix_entries_){
      lower_triangular_matrix_rowmap_ = this->lower_triangular_matrix_rowmap;
      lower_triangular_matrix_entries_ = this->lower_triangular_matrix_entries;
    }
  
  
    void set_compressed_b(
        size_type b_nnz_size,
        row_lno_temp_work_view_t compressed_b_rowmap_,
        nnz_lno_temp_work_view_t compressed_b_set_indices_,
        nnz_lno_temp_work_view_t compressed_b_sets_){
      compressed_b_size = b_nnz_size;
      compressed_b_rowmap = compressed_b_rowmap_;
      compressed_b_set_indices = compressed_b_set_indices_;
      compressed_b_sets = compressed_b_sets_;
    }
  
  
    void get_compressed_b(
        size_type &b_nnz_size,
        row_lno_temp_work_view_t &compressed_b_rowmap_,
        nnz_lno_temp_work_view_t &compressed_b_set_indices_,
        nnz_lno_temp_work_view_t &compressed_b_sets_){
      b_nnz_size = compressed_b_size;
      compressed_b_rowmap_ = compressed_b_rowmap;
      compressed_b_set_indices_ = compressed_b_set_indices;
      compressed_b_sets_ = compressed_b_sets;
    }
  
    /**
     * \brief Default constructor.
     */
    SPGEMMHandle(SPGEMMAlgorithm gs = SPGEMM_DEFAULT):
      algorithm_type(gs), accumulator_type(SPGEMM_ACC_DEFAULT), result_nnz_size(0),
      called_symbolic(false), called_numeric(false),
      suggested_vector_size(0), suggested_team_size(0), max_nnz_inresult(0),
      c_column_indices(),
      tranpose_a_xadj(), tranpose_b_xadj(), tranpose_c_xadj(),
      tranpose_a_adj(), tranpose_b_adj(), tranpose_c_adj(),
      transpose_a(false),transpose_b(false), transpose_c_symbolic(false),
      num_colors(0),
      color_xadj(), color_adj(), vertex_colors(), num_multi_colors(0),num_used_colors(0),
      min_result_row_for_each_row(),
  
      create_lower_triangular(false),
      sort_lower_triangular(2),
      sort_option (-1),
      lower_triangular_permutation(),
      lower_triangular_matrix_rowmap(),
      lower_triangular_matrix_entries(),
      incidence_matrix_row_map(),
      incidence_matrix_entries(),compress_second_matrix(true),
  
      multi_color_scale(1), mkl_sort_option(7), calculate_read_write_cost(false),
      coloring_input_file(""),
      coloring_output_file(""), min_hash_size_scale(1), compression_cut_off(0.85), first_level_hash_cut_off(0.50),
      original_max_row_flops(std::numeric_limits<size_t>::max()), original_overall_flops(std::numeric_limits<size_t>::max()),
      persistent_a_xadj(), persistent_b_xadj(), persistent_a_adj(), persistent_b_adj(), MaxColDenseAcc(250001),
      mkl_keep_output(true),
      mkl_convert_to_1base(true), is_compression_single_step(false)
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
    ,cuSPARSEHandle(NULL)
  #endif
    {
      if (gs == SPGEMM_DEFAULT){
        this->choose_default_algorithm();
      }
    }
  
  
    virtual ~SPGEMMHandle(){
  
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
      this->destroy_cuSPARSE_Handle();
  #endif
    };
  
  #ifdef KOKKOSKERNELS_ENABLE_TPL_CUSPARSE
    void create_cuSPARSE_Handle(bool transA, bool transB){
      this->destroy_cuSPARSE_Handle();
      this->cuSPARSEHandle = new cuSparseHandleType(transA, transB);
    }
    void destroy_cuSPARSE_Handle(){
      if (this->cuSPARSEHandle != NULL){
        delete this->cuSPARSEHandle;
        this->cuSPARSEHandle = NULL;
      }
    }
  
    SPGEMMcuSparseHandleType *get_cuSparseHandle(){
      return this->cuSPARSEHandle;
    }
  #endif
      /** \brief Chooses best algorithm based on the execution space. COLORING_EB if cuda, COLORING_VB otherwise.
     */
    void choose_default_algorithm(){
  #if defined( KOKKOS_ENABLE_SERIAL )
      if (Kokkos::Impl::is_same< Kokkos::Serial , ExecutionSpace >::value){
        this->algorithm_type = SPGEMM_SERIAL;
  #ifdef VERBOSE
        std::cout << "Serial Execution Space, Default Algorithm: SPGEMM_SERIAL" << std::endl;
  #endif
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_THREADS )
      if (Kokkos::Impl::is_same< Kokkos::Threads , ExecutionSpace >::value){
        this->algorithm_type = SPGEMM_SERIAL;
  #ifdef VERBOSE
        std::cout << "THREADS Execution Space, Default Algorithm: SPGEMM_SERIAL" << std::endl;
  #endif
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_OPENMP )
      if (Kokkos::Impl::is_same< Kokkos::OpenMP, ExecutionSpace >::value){
        this->algorithm_type = SPGEMM_SERIAL;
  #ifdef VERBOSE
        std::cout << "OpenMP Execution Space, Default Algorithm: SPGEMM_SERIAL" << std::endl;
  #endif
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_CUDA )
      if (Kokkos::Impl::is_same<Kokkos::Cuda, ExecutionSpace >::value){
        this->algorithm_type = SPGEMM_CUSPARSE;
  #ifdef VERBOSE
        std::cout << "Cuda Execution Space, Default Algorithm: SPGEMM_CUSPARSE" << std::endl;
  #endif
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_QTHREAD)
      if (Kokkos::Impl::is_same< Kokkos::Qthread, ExecutionSpace >::value){
        this->algorithm_type = SPGEMM_SERIAL;
  #ifdef VERBOSE
        std::cout << "Qthread Execution Space, Default Algorithm: SPGEMM_SERIAL" << std::endl;
  #endif
      }
  #endif
    }
  
  
    void set_compression(bool compress_second_matrix_){
      this->compress_second_matrix = compress_second_matrix_;
    }
  
    bool get_compression (){
      return this->compress_second_matrix;
    }
  
    SPGEMMAccumulator get_accumulator_type() const {return this->accumulator_type;}
    void set_accumulator_type(const SPGEMMAccumulator &acc_type){this->accumulator_type = acc_type;}
  
  
    //getters
    SPGEMMAlgorithm get_algorithm_type() const {return this->algorithm_type;}
  
    bool is_symbolic_called(){return this->called_symbolic;}
    bool is_numeric_called(){return this->called_numeric;}
  
  
    nnz_lno_t get_max_result_nnz() const{
      return this->max_nnz_inresult ;
    }
  
    nnz_lno_t get_max_compresed_result_nnz() const{
      return this->max_nnz_compressed_result ;
    }
  
  
    //setters
    void set_algorithm_type(const SPGEMMAlgorithm &sgs_algo){this->algorithm_type = sgs_algo;}
    void set_call_symbolic(bool call = true){this->called_symbolic = call;}
    void set_call_numeric(bool call = true){this->called_numeric = call;}
  
    void set_max_result_nnz(nnz_lno_t num_result_nnz_){
      this->max_nnz_inresult = num_result_nnz_;
    }
  
    void set_max_compresed_result_nnz(nnz_lno_t num_result_nnz_){
      this->max_nnz_compressed_result = num_result_nnz_;
    }
  
    void vector_team_size(
        int max_allowed_team_size,
        int &suggested_vector_size_,
        int &suggested_team_size_,
        size_type nr, size_type nnz){
      //suggested_team_size_ =  this->suggested_team_size = 1;
      //suggested_vector_size_=this->suggested_vector_size = 1;
      //return;
      if (this->suggested_team_size && this->suggested_vector_size) {
        suggested_vector_size_ = this->suggested_vector_size;
        suggested_team_size_ = this->suggested_team_size;
        return;
      }
  
  #if defined( KOKKOS_ENABLE_SERIAL )
      if (Kokkos::Impl::is_same< Kokkos::Serial , ExecutionSpace >::value){
        suggested_vector_size_ = this->suggested_vector_size = 1;
        suggested_team_size_ = this->suggested_team_size = max_allowed_team_size;
        return;
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_THREADS )
      if (Kokkos::Impl::is_same< Kokkos::Threads , ExecutionSpace >::value){
        suggested_vector_size_ = this->suggested_vector_size = 1;
        suggested_team_size_ = this->suggested_team_size = max_allowed_team_size;
        return;
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_OPENMP )
      if (Kokkos::Impl::is_same< Kokkos::OpenMP, ExecutionSpace >::value){
        suggested_vector_size_ = this->suggested_vector_size = 1;
        suggested_team_size_ = this->suggested_team_size = max_allowed_team_size;
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_CUDA )
      if (Kokkos::Impl::is_same<Kokkos::Cuda, ExecutionSpace >::value){
  
        this->suggested_vector_size = nnz / double (nr) + 0.5;
  
        if (this->suggested_vector_size <= 3){
          this->suggested_vector_size = 2;
        }
        else if (this->suggested_vector_size <= 6){
          this->suggested_vector_size = 4;
        }
        else if (this->suggested_vector_size <= 12){
          this->suggested_vector_size = 8;
        }
        else if (this->suggested_vector_size <= 24){
          this->suggested_vector_size = 16;
        }
        else {
          this->suggested_vector_size = 32;
        }
  
        suggested_vector_size_ = this->suggested_vector_size;
        this->suggested_team_size= suggested_team_size_ = max_allowed_team_size / this->suggested_vector_size;
      }
  #endif
  
  #if defined( KOKKOS_ENABLE_QTHREAD)
      if (Kokkos::Impl::is_same< Kokkos::Qthread, ExecutionSpace >::value){
        suggested_vector_size_ = this->suggested_vector_size = 1;
        suggested_team_size_ = this->suggested_team_size = max_allowed_team_size;
      }
  #endif
  
    }
  
    void set_compression_steps(bool isCompressionSingleStep){
      this->is_compression_single_step = isCompressionSingleStep;
    }
  
    void set_min_col_of_row(nnz_lno_persistent_work_view_t min_result_row_for_each_row_){
      this->min_result_row_for_each_row = min_result_row_for_each_row_;
    }
  
    nnz_lno_persistent_work_view_t get_min_col_of_row(){
      return this->min_result_row_for_each_row;
    }
  
    bool get_compression_step(){
      return is_compression_single_step;
    }
  };
  
  
    inline SPGEMMAlgorithm StringToSPGEMMAlgorithm(std::string & name) {
      if(name=="SPGEMM_DEFAULT")             return SPGEMM_KK;
      else if(name=="SPGEMM_KK")       	   return SPGEMM_KK;
      else if(name=="SPGEMM_KK_MEMORY")      return SPGEMM_KK_MEMORY;
      else if(name=="SPGEMM_KK_DENSE")       return SPGEMM_KK_DENSE;
      else if(name=="SPGEMM_KK_LP")  		   return SPGEMM_KK_LP;
      else if(name=="SPGEMM_KK_MEMSPEED")    return SPGEMM_KK;
  
      else if(name=="SPGEMM_DEBUG")          return SPGEMM_SERIAL;
      else if(name=="SPGEMM_SERIAL")         return SPGEMM_SERIAL;
      else if(name=="SPGEMM_CUSPARSE")       return SPGEMM_CUSPARSE;
      else if(name=="SPGEMM_CUSP")           return SPGEMM_CUSP;
      else if(name=="SPGEMM_MKL")            return SPGEMM_MKL;
      else if(name=="SPGEMM_VIENNA")         return SPGEMM_VIENNA;
      else
        throw std::runtime_error("Invalid SPGEMMAlgorithm name");
    }
  
  
  
  }
  
  #endif
  