Files
TheRock/rocm-libraries/projects/rocsparse/clients/common/rocsparseio.hpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

2352 lines
79 KiB
C++

/* ************************************************************************
* Copyright (C) 2024 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* ************************************************************************ */
#pragma once
#include <cstdint>
#include <iostream>
#include <limits>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
//
//
//
#define ROCSPARSEIO_CHECK(ROCSPARSEIO_CHECK_todo) \
{ \
rocsparseio::status_t check_status = (ROCSPARSEIO_CHECK_todo); \
if(check_status != rocsparseio::status_t::success) \
{ \
fprintf(stderr, "ROCSPARSEIO_CHECK FAILED, LINE %d FILE %s\n", __LINE__, __FILE__); \
return check_status; \
} \
} \
(void)0
//
//
//
#define ROCSPARSEIO_CHECK_ARG(ROCSPARSEIO_CHECK_ARG_cond, ROCSPARSEIO_CHECK_ARG_status) \
if(ROCSPARSEIO_CHECK_ARG_cond) \
{ \
return ROCSPARSEIO_CHECK_ARG_status; \
} \
(void)0
//
//
//
#define ROCSPARSEIO_C_CHECK(ROCSPARSEIO_C_CHECK_todo) \
{ \
rocsparseio::status_t check_status = (ROCSPARSEIO_C_CHECK_todo); \
if(check_status != rocsparseio::status_t::success) \
{ \
fprintf(stderr, "ROCSPARSEIO_CHECK FAILED\n"); \
return (rocsparseio_status)check_status; \
} \
} \
(void)0
//
//
//
#define ROCSPARSEIO_C_CHECK_ARG(ROCSPARSEIO_C_CHECK_ARG_cond, ROCSPARSEIO_C_CHECK_ARG_status) \
if(ROCSPARSEIO_C_CHECK_ARG_cond) \
{ \
return (rocsparseio_status)ROCSPARSEIO_C_CHECK_ARG_status; \
}
#include "rocsparseio.h"
namespace rocsparseio
{
#define ROCSPARSEIO_ENUM_EACH_STATUS \
ROCSPARSEIO_ENUM_STATUS(success) \
ROCSPARSEIO_ENUM_STATUS(invalid_handle) \
ROCSPARSEIO_ENUM_STATUS(invalid_pointer) \
ROCSPARSEIO_ENUM_STATUS(invalid_value) \
ROCSPARSEIO_ENUM_STATUS(invalid_enum) \
ROCSPARSEIO_ENUM_STATUS(invalid_file) \
ROCSPARSEIO_ENUM_STATUS(invalid_file_operation) \
ROCSPARSEIO_ENUM_STATUS(invalid_format) \
ROCSPARSEIO_ENUM_STATUS(invalid_mode) \
ROCSPARSEIO_ENUM_STATUS(invalid_size) \
ROCSPARSEIO_ENUM_STATUS(invalid_memory)
//!
//! @brief c++11 struct for status enum.
//!
struct status_t
{
#define ROCSPARSEIO_ENUM_STATUS(ROCSPARSEIO_ENUM_STATUS_x) \
ROCSPARSEIO_ENUM_STATUS_x = rocsparseio_status_##ROCSPARSEIO_ENUM_STATUS_x,
typedef enum value_type_ : rocsparseio_status_t
{
ROCSPARSEIO_ENUM_EACH_STATUS
} value_type;
#undef ROCSPARSEIO_ENUM_STATUS
value_type value{};
inline constexpr operator value_type() const
{
return this->value;
}
inline explicit constexpr operator rocsparseio_status() const
{
return (rocsparseio_status)this->value;
}
inline constexpr status_t() {}
inline constexpr status_t(rocsparseio_status_t ival)
: value((value_type)ival)
{
}
inline constexpr status_t(rocsparseio_status ival)
: value((value_type)ival)
{
}
inline bool is_invalid() const
{
#define ROCSPARSEIO_ENUM_STATUS(x_) case x_:
switch(this->value)
{
ROCSPARSEIO_ENUM_EACH_STATUS
{
return false;
}
}
#undef ROCSPARSEIO_ENUM_STATUS
return true;
}
inline const char* to_string() const
{
#define ROCSPARSEIO_ENUM_STATUS(x_) \
case x_: \
{ \
return #x_; \
}
switch(this->value)
{
ROCSPARSEIO_ENUM_EACH_STATUS;
}
#undef ROCSPARSEIO_ENUM_STATUS
return "rocsparseio-unknown";
}
#undef ROCSPARSEIO_ENUM_EACH_STATUS
};
//!
//! @brief c++11 struct for format enum.
//!
struct format_t
{
typedef enum value_type_ : rocsparseio_format_t
{
dense_vector = rocsparseio_format_dense_vector,
dense_matrix = rocsparseio_format_dense_matrix,
sparse_csx = rocsparseio_format_sparse_csx,
sparse_gebsx = rocsparseio_format_sparse_gebsx,
sparse_coo = rocsparseio_format_sparse_coo,
sparse_ell = rocsparseio_format_sparse_ell,
sparse_hyb = rocsparseio_format_sparse_hyb,
sparse_dia = rocsparseio_format_sparse_dia,
sparse_mcsx = rocsparseio_format_sparse_mcsx,
} value_type;
value_type value{};
inline constexpr operator value_type() const
{
return this->value;
}
inline constexpr format_t(){};
inline constexpr format_t(rocsparseio_format_t ival_)
: value((value_type)ival_)
{
}
inline constexpr format_t(rocsparseio_format ival_)
: value((value_type)ival_)
{
}
inline explicit constexpr operator rocsparseio_format() const
{
return (rocsparseio_format)this->value;
}
inline bool is_invalid() const
{
switch(this->value)
{
case dense_vector:
case dense_matrix:
case sparse_csx:
case sparse_gebsx:
case sparse_coo:
case sparse_ell:
case sparse_dia:
case sparse_hyb:
case sparse_mcsx:
{
return false;
}
}
return true;
}
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(dense_matrix);
CASE(dense_vector);
CASE(sparse_csx);
CASE(sparse_mcsx);
CASE(sparse_gebsx);
CASE(sparse_coo);
CASE(sparse_ell);
CASE(sparse_dia);
CASE(sparse_hyb);
#undef CASE
}
return "unknown";
}
};
//!
//! @brief c++11 struct for order enum.
//!
struct order_t
{
typedef enum value_type_ : rocsparseio_order_t
{
row = rocsparseio_order_row,
column = rocsparseio_order_column,
} value_type;
value_type value{};
inline constexpr operator value_type() const
{
return this->value;
}
inline explicit constexpr operator rocsparseio_order() const
{
return (rocsparseio_order)this->value;
}
// order_t(){};
inline constexpr order_t() {}
inline constexpr order_t(rocsparseio_order_t ival_)
: value((value_type)ival_)
{
}
inline bool is_invalid() const
{
switch(this->value)
{
case row:
case column:
{
return false;
}
}
return true;
}
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(row);
CASE(column);
#undef CASE
}
return "unknown";
}
};
//!
//! @brief c++11 struct for direction enum.
//!
struct direction_t
{
typedef enum value_type_ : rocsparseio_direction_t
{
row = rocsparseio_direction_row,
column = rocsparseio_direction_column,
} value_type;
value_type value{};
inline constexpr operator value_type() const
{
return this->value;
}
inline explicit constexpr operator rocsparseio_direction() const
{
return (rocsparseio_direction)this->value;
}
inline constexpr direction_t(){};
inline constexpr direction_t(rocsparseio_direction_t ival_)
: value((value_type)ival_)
{
}
inline bool is_invalid() const
{
switch(this->value)
{
case row:
case column:
{
return false;
}
}
return true;
}
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(row);
CASE(column);
#undef CASE
}
return "unknown";
}
};
//!
//! @brief c++11 struct for type enum.
//!
struct type_t
{
typedef enum value_type_ : rocsparseio_type_t
{
int32 = rocsparseio_type_int32,
int64 = rocsparseio_type_int64,
float32 = rocsparseio_type_float32,
float64 = rocsparseio_type_float64,
complex32 = rocsparseio_type_complex32,
complex64 = rocsparseio_type_complex64,
} value_type;
value_type value{};
inline constexpr operator value_type() const
{
return this->value;
};
inline explicit constexpr operator rocsparseio_type() const
{
return (rocsparseio_type)this->value;
};
constexpr type_t(){};
constexpr type_t(rocsparseio_type_t ival_)
: value((value_type)ival_){};
template <typename T>
static constexpr type_t convert();
inline uint64_t size() const
{
switch(this->value)
{
case int32:
{
return sizeof(int32_t);
}
case int64:
{
return sizeof(int64_t);
}
case float32:
{
return sizeof(float);
}
case float64:
{
return sizeof(double);
}
case complex32:
{
return sizeof(float) * 2;
}
case complex64:
{
return sizeof(double) * 2;
}
}
return 0;
};
inline bool is_invalid() const
{
switch(this->value)
{
case int32:
case int64:
case float32:
case float64:
case complex32:
case complex64:
{
return false;
}
}
return true;
};
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(int32);
CASE(int64);
CASE(float32);
CASE(float64);
CASE(complex32);
CASE(complex64);
#undef CASE
}
return "unknown";
}
};
struct index_base_t
{
typedef enum value_index_base_ : rocsparseio_index_base_t
{
zero = rocsparseio_index_base_zero,
one = rocsparseio_index_base_one
} value_index_base;
value_index_base value{};
inline constexpr operator value_index_base() const
{
return this->value;
};
inline explicit constexpr operator rocsparseio_index_base() const
{
return (rocsparseio_index_base)this->value;
};
constexpr index_base_t(){};
constexpr index_base_t(rocsparseio_index_base_t ival_)
: value((value_index_base)ival_){};
template <typename T>
static constexpr index_base_t convert();
inline bool is_invalid() const
{
switch(this->value)
{
case one:
case zero:
{
return false;
}
}
return true;
};
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(one);
CASE(zero);
#undef CASE
}
return "unknown";
}
};
//!
//! @brief c++11 struct for rwmode enum.
//!
struct rwmode_t
{
typedef enum value_type_ : rocsparseio_rwmode_t
{
read = rocsparseio_rwmode_read,
write = rocsparseio_rwmode_write
} value_type;
value_type value;
inline constexpr operator value_type() const
{
return this->value;
};
inline constexpr rwmode_t(rocsparseio_rwmode_t ival_)
: value((value_type)ival_)
{
}
inline bool is_invalid() const
{
switch(this->value)
{
case read:
case write:
{
return false;
}
}
return true;
};
inline const char* to_string() const
{
switch(this->value)
{
#define CASE(case_name) \
case case_name: \
{ \
return #case_name; \
}
CASE(read);
CASE(write);
#undef CASE
}
return "unknown";
}
};
inline std::ostream& operator<<(std::ostream& os_, const status_t& that_)
{
os_ << that_.to_string();
return os_;
}
inline std::ostream& operator<<(std::ostream& os_, const direction_t& that_)
{
os_ << that_.to_string();
return os_;
}
inline std::ostream& operator<<(std::ostream& os_, const order_t& that_)
{
os_ << that_.to_string();
return os_;
}
inline std::ostream& operator<<(std::ostream& os_, const type_t& that_)
{
os_ << that_.to_string();
return os_;
}
inline std::ostream& operator<<(std::ostream& os_, const rwmode_t& that_)
{
os_ << that_.to_string();
return os_;
}
inline std::ostream& operator<<(std::ostream& os_, const format_t& that_)
{
os_ << that_.to_string();
return os_;
}
} // namespace rocsparseio
struct _rocsparseio_handle
{
rocsparseio::rwmode_t mode;
std::string filename{};
FILE* f{};
_rocsparseio_handle(rocsparseio::rwmode_t mode_, const char* filename_)
: mode(mode_)
, filename(filename_)
{
}
};
namespace rocsparseio
{
using handle_t = rocsparseio_handle;
inline status_t fread_data(FILE* in_, uint64_t size_, uint64_t nmemb_, void* data_)
{
if(nmemb_ != fread(data_, size_, nmemb_, in_))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
template <typename source, typename target>
inline status_t convert_scalar(const source& s_, target& t_)
{
if(!std::is_same<source, target>())
{
if(std::is_unsigned<source>())
{
if(sizeof(target) < sizeof(source))
{
if(static_cast<source>(std::numeric_limits<target>::max()) < s_)
{
std::cerr << "convert out of bounds " << s_ << ", max is "
<< std::numeric_limits<target>::max() << "" << std::endl;
return status_t::invalid_value;
}
}
}
else
{
if(sizeof(target) < sizeof(source))
{
if((s_ > static_cast<source>(std::numeric_limits<target>::max()))
|| (s_ < static_cast<source>(std::numeric_limits<target>::lowest())))
{
std::cerr << "convert out of bounds " << s_ << ", ["
<< std::numeric_limits<target>::lowest() << ", "
<< std::numeric_limits<target>::max() << "]" << std::endl;
return status_t::invalid_value;
}
}
}
}
t_ = static_cast<target>(s_);
return status_t::success;
}
template <typename source>
inline status_t convert_scalar(const source& s_, format_t& t_)
{
t_ = static_cast<format_t>(s_);
if(t_.is_invalid())
{
return status_t::invalid_value;
}
return status_t::success;
}
template <typename source>
inline status_t convert_scalar(const source& s_, direction_t& t_)
{
t_ = static_cast<direction_t>(s_);
if(t_.is_invalid())
{
return status_t::invalid_value;
}
return status_t::success;
}
template <typename source>
inline status_t convert_scalar(const source& s_, order_t& t_)
{
t_ = static_cast<order_t>(s_);
if(t_.is_invalid())
{
return status_t::invalid_value;
}
return status_t::success;
}
template <typename source>
inline status_t convert_scalar(const source& s_, type_t& t_)
{
t_ = static_cast<type_t>(s_);
if(t_.is_invalid())
{
return status_t::invalid_value;
}
return status_t::success;
}
template <typename T, typename J>
inline status_t fwrite_scalar(J scalar_, FILE* out_)
{
{
T value = static_cast<T>(scalar_);
if(1 != fwrite(&value, sizeof(T), 1, out_))
{
return status_t::invalid_file_operation;
}
}
return status_t::success;
};
template <typename T, typename J>
inline status_t fread_scalar(J& scalar_, FILE* in_)
{
{
T value;
if(1 != fread(&value, sizeof(T), 1, in_))
{
return status_t::invalid_file_operation;
}
return convert_scalar(value, scalar_);
}
return status_t::success;
};
template <typename T, typename J>
inline status_t fread_scalar(J* scalar_, FILE* in_)
{
{
T value;
if(1 != fread(&value, sizeof(T), 1, in_))
{
return status_t::invalid_file_operation;
}
J scalar;
status_t status = convert_scalar(value, scalar);
if(status != status_t::success)
{
return status;
}
scalar_[0] = scalar;
}
return status_t::success;
};
inline status_t fwrite_array(FILE* out_, uint64_t size_, uint64_t nmemb_, const void* data_)
{
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(size_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nmemb_, out_));
if(nmemb_ != fwrite(data_, size_, nmemb_, out_))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_array(FILE* in_, void* data_)
{
uint64_t size;
uint64_t nmemb;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(size, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nmemb, in_));
if(nmemb != fread(data_, size, nmemb, in_))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_array_metadata(FILE* in_, uint64_t* size_, uint64_t* nmemb_)
{
const long pos = ftell(in_);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(size_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nmemb_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
//
// ////////////////////////////////////////////////
//
inline status_t fwrite_dense_vector(FILE* out_,
type_t data_type_,
uint64_t data_nmemb_,
const void* data_,
uint64_t data_inc_,
const char* name_,
...)
{
ROCSPARSEIO_CHECK_ARG(out_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(data_type_.is_invalid(), status_t::invalid_value);
ROCSPARSEIO_CHECK_ARG(((data_nmemb_ > 0) && (data_ == nullptr)), status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(((data_inc_ > 0) && (data_ == nullptr)), status_t::invalid_size);
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::dense_vector, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_nmemb_, out_));
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
uint64_t data_size = data_type_.size();
if(data_inc_ == 1)
{
if(data_nmemb_ != fwrite(data_, data_size, data_nmemb_, out_))
{
return status_t::invalid_file_operation;
}
}
else
{
for(uint64_t i = 0; i < data_nmemb_; ++i)
{
if(1
!= fwrite(((const char*)data_) + i * data_inc_ * data_size, data_size, 1, out_))
{
return status_t::invalid_file_operation;
}
}
}
return status_t::success;
}
inline status_t fread_format(FILE* in_, format_t* format_)
{
ROCSPARSEIO_CHECK_ARG(in_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(format_ == nullptr, status_t::invalid_pointer);
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
};
inline status_t fread_name(FILE* in_, rocsparseio_string name_)
{
ROCSPARSEIO_CHECK_ARG(in_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(name_ == nullptr, status_t::invalid_pointer);
const long pos = ftell(in_);
if(size_t(1) != fread(name_, sizeof(rocsparseio_string), 1, in_))
{
return status_t::invalid_file_operation;
}
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
};
inline status_t fread_metadata_dense_vector(FILE* in_, type_t* type_, uint64_t* nmemb_)
{
ROCSPARSEIO_CHECK_ARG(in_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(type_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(nmemb_ == nullptr, status_t::invalid_pointer);
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
if(format != format_t::dense_vector)
{
std::cerr << " wrong format, not flagged as a dense_vector. " << std::endl;
return status_t::invalid_format;
}
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nmemb_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
};
inline status_t fread_dense_vector(FILE* in_, void* data_, uint64_t inc_)
{
if(0 != fseek(in_, sizeof(uint64_t) + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
type_t type;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(type, in_));
uint64_t size = type.size();
uint64_t nmemb;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nmemb, in_));
if(inc_ == 1)
{
return fread_data(in_, size, nmemb, data_);
}
else
{
void* buff = malloc(size * nmemb);
ROCSPARSEIO_CHECK(fread_data(in_, size, nmemb, buff));
uint64_t j = 0;
for(uint64_t i = 0; i < nmemb; ++i)
{
memcpy(((char*)data_) + j * size, ((char*)buff) + i * size, size);
j += inc_;
}
free(buff);
return status_t::invalid_value;
}
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_dense_matrix(FILE* out_,
order_t order_,
uint64_t m_,
uint64_t n_,
type_t data_type_,
const void* data_,
uint64_t data_ld_,
const char* name_,
...)
{
ROCSPARSEIO_CHECK_ARG(out_ == nullptr, status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(order_.is_invalid(), status_t::invalid_value);
ROCSPARSEIO_CHECK_ARG(data_type_.is_invalid(), status_t::invalid_value);
ROCSPARSEIO_CHECK_ARG((((m_ > 0) && (n_ > 0)) && (data_ == nullptr)),
status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG((((m_ > 0) && (n_ > 0)) && (data_ == nullptr)),
status_t::invalid_pointer);
ROCSPARSEIO_CHECK_ARG(((order_ == order_t::row) && (data_ld_ < n_)),
status_t::invalid_size);
ROCSPARSEIO_CHECK_ARG(((order_ == order_t::column) && (data_ld_ < m_)),
status_t::invalid_size);
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::dense_matrix, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(order_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
uint64_t data_size = data_type_.size();
switch(order_)
{
case order_t::row:
{
if(data_ld_ == n_)
{
const uint64_t data_nmemb = m_ * n_;
if(data_nmemb != fwrite(data_, data_size, data_nmemb, out_))
{
return status_t::invalid_file_operation;
}
}
else
{
for(uint64_t i = 0; i < m_; ++i)
{
if(n_
!= fwrite(
((const char*)data_) + i * data_ld_ * data_size, data_size, n_, out_))
{
return status_t::invalid_file_operation;
}
}
}
break;
}
case order_t::column:
{
if(data_ld_ == m_)
{
const uint64_t data_nmemb = m_ * n_;
if(data_nmemb != fwrite(data_, data_size, data_nmemb, out_))
{
return status_t::invalid_file_operation;
}
}
else
{
for(uint64_t j = 0; j < n_; ++j)
{
if(m_
!= fwrite(
((const char*)data_) + j * data_ld_ * data_size, data_size, m_, out_))
{
return status_t::invalid_file_operation;
}
}
}
break;
}
}
return status_t::success;
};
inline status_t fread_dense_matrix(FILE* in_, void* data_, uint64_t ld_)
{
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
{
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
if(format != format_t::dense_matrix)
{
std::cerr << " wrong format, not flagged as a dense matrix. " << std::endl;
return status_t::invalid_format;
}
}
order_t order;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(&order, in_));
uint64_t m;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(&m, in_));
uint64_t n;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(&n, in_));
type_t type;
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(&type, in_));
const uint64_t s = type.size();
ROCSPARSEIO_CHECK_ARG(((order == order_t::row) && (ld_ < n)), status_t::invalid_size);
ROCSPARSEIO_CHECK_ARG(((order == order_t::column) && (ld_ < m)), status_t::invalid_size);
switch(order)
{
case order_t::row:
{
if(ld_ == n)
{
ROCSPARSEIO_CHECK(fread_data(in_, s, m * n, data_));
}
else
{
char* p = static_cast<char*>(data_);
for(uint64_t i = 0; i < m; ++i)
{
ROCSPARSEIO_CHECK(fread_data(in_, s, n, p));
p += s * ld_;
}
}
break;
}
case order_t::column:
{
if(ld_ == m)
{
ROCSPARSEIO_CHECK(fread_data(in_, s, m * n, data_));
}
else
{
char* p = static_cast<char*>(data_);
const uint64_t s = type.size();
for(uint64_t j = 0; j < n; ++j)
{
ROCSPARSEIO_CHECK(fread_data(in_, s, m, p));
p += s * ld_;
}
}
break;
}
}
return status_t::success;
}
inline status_t fread_metadata_dense_matrix(
FILE* in_, order_t* order_, uint64_t* m_, uint64_t* n_, type_t* type_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
if(format != format_t::dense_matrix)
{
std::cerr << " wrong format, not flagged as a dense matrix. " << std::endl;
return status_t::invalid_format;
}
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(order_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(type_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
} // namespace rocsparseio
//
//
//
namespace rocsparseio
{
inline status_t fwrite_sparse_csx(FILE* out_,
direction_t dir_,
uint64_t m_,
uint64_t n_,
uint64_t nnz_,
type_t ptr_type_,
const void* __restrict__ ptr_,
type_t ind_type_,
const void* __restrict__ ind_,
type_t data_type_,
const void* __restrict__ data_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_csx, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(dir_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nnz_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ptr_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
switch(dir_)
{
case direction_t::row:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), m_ + 1, ptr_));
break;
}
case direction_t::column:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), n_ + 1, ptr_));
break;
}
}
ROCSPARSEIO_CHECK(fwrite_array(out_, ind_type_.size(), nnz_, ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, data_type_.size(), nnz_, data_));
return status_t::success;
};
inline status_t fread_metadata_sparse_csx(FILE* in_,
direction_t* dir_,
uint64_t* m_,
uint64_t* n_,
uint64_t* nnz_,
type_t* ptr_type_,
type_t* ind_type_,
type_t* data_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(dir_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nnz_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ptr_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(data_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_csx(FILE* in_,
void* __restrict__ ptr_,
void* __restrict__ ind_,
void* __restrict__ data_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 9 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, ptr_));
ROCSPARSEIO_CHECK(fread_array(in_, ind_));
ROCSPARSEIO_CHECK(fread_array(in_, data_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_sparse_coo(FILE* out_,
uint64_t m_,
uint64_t n_,
uint64_t nnz_,
type_t row_ind_type_,
const void* __restrict__ row_ind_,
type_t col_ind_type_,
const void* __restrict__ col_ind_,
type_t data_type_,
const void* __restrict__ data_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_coo, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nnz_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(row_ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(col_ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
ROCSPARSEIO_CHECK(fwrite_array(out_, row_ind_type_.size(), nnz_, row_ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, col_ind_type_.size(), nnz_, col_ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, data_type_.size(), nnz_, data_));
return status_t::success;
};
inline status_t fread_metadata_sparse_coo(FILE* in_,
uint64_t* m_,
uint64_t* n_,
uint64_t* nnz_,
type_t* row_ind_type_,
type_t* col_ind_type_,
type_t* data_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nnz_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(row_ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(col_ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(data_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_coo(FILE* in_,
void* __restrict__ row_ind_,
void* __restrict__ col_ind_,
void* __restrict__ data_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 8 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, row_ind_));
ROCSPARSEIO_CHECK(fread_array(in_, col_ind_));
ROCSPARSEIO_CHECK(fread_array(in_, data_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_sparse_ell(FILE* out_,
uint64_t m_,
uint64_t n_,
uint64_t width_,
type_t ind_type_,
const void* __restrict__ ind_,
type_t val_type_,
const void* __restrict__ val_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_ell, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(width_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(val_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
ROCSPARSEIO_CHECK(fwrite_array(out_, ind_type_.size(), m_ * width_, ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, val_type_.size(), m_ * width_, val_));
return status_t::success;
};
inline status_t fread_metadata_sparse_ell(FILE* in_,
uint64_t* m_,
uint64_t* n_,
uint64_t* width_,
type_t* ind_type_,
type_t* val_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(width_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(val_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_ell(FILE* in_, void* __restrict__ ind_, void* __restrict__ val_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 7 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, ind_));
ROCSPARSEIO_CHECK(fread_array(in_, val_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_sparse_dia(FILE* out_,
uint64_t m_,
uint64_t n_,
uint64_t ndiag_,
type_t ind_type_,
const void* __restrict__ ind_,
type_t val_type_,
const void* __restrict__ val_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_dia, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ndiag_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(val_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
ROCSPARSEIO_CHECK(fwrite_array(out_, ind_type_.size(), ndiag_, ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, val_type_.size(), std::min(m_, n_) * ndiag_, val_));
return status_t::success;
};
inline status_t fread_metadata_sparse_dia(FILE* in_,
uint64_t* m_,
uint64_t* n_,
uint64_t* ndiag_,
type_t* ind_type_,
type_t* val_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ndiag_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(val_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_dia(FILE* in_, void* __restrict__ ind_, void* __restrict__ val_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 7 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, ind_));
ROCSPARSEIO_CHECK(fread_array(in_, val_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_sparse_hyb(FILE* out_,
uint64_t m_,
uint64_t n_,
uint64_t coo_nnz_,
type_t coo_row_ind_type_,
const void* __restrict__ coo_row_ind_,
type_t coo_col_ind_type_,
const void* __restrict__ coo_col_ind_,
type_t coo_data_type_,
const void* __restrict__ coo_data_,
index_base_t coo_base_,
uint64_t ell_width_,
type_t ell_ind_type_,
const void* __restrict__ ell_ind_,
type_t ell_val_type_,
const void* __restrict__ ell_val_,
index_base_t ell_base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_hyb, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(coo_nnz_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(coo_row_ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(coo_col_ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(coo_data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(coo_base_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ell_width_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ell_ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ell_val_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ell_base_, out_));
ROCSPARSEIO_CHECK(fwrite_array(out_, coo_row_ind_type_.size(), coo_nnz_, coo_row_ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, coo_col_ind_type_.size(), coo_nnz_, coo_col_ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, coo_data_type_.size(), coo_nnz_, coo_data_));
ROCSPARSEIO_CHECK(fwrite_array(out_, ell_ind_type_.size(), m_ * ell_width_, ell_ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, ell_val_type_.size(), m_ * ell_width_, ell_val_));
return status_t::success;
};
inline status_t fread_metadata_sparse_hyb(FILE* in_,
uint64_t* m_,
uint64_t* n_,
uint64_t* coo_nnz_,
type_t* coo_row_ind_type_,
type_t* coo_col_ind_type_,
type_t* coo_data_type_,
index_base_t* coo_base_,
uint64_t* ell_width_,
type_t* ell_ind_type_,
type_t* ell_val_type_,
index_base_t* ell_base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(coo_nnz_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(coo_row_ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(coo_col_ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(coo_data_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(coo_base_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ell_width_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ell_ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ell_val_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ell_base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_hyb(FILE* in_,
void* __restrict__ coo_row_ind_,
void* __restrict__ coo_col_ind_,
void* __restrict__ coo_data_,
void* __restrict__ ell_ind_,
void* __restrict__ ell_val_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 12 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, coo_row_ind_));
ROCSPARSEIO_CHECK(fread_array(in_, coo_col_ind_));
ROCSPARSEIO_CHECK(fread_array(in_, coo_data_));
ROCSPARSEIO_CHECK(fread_array(in_, ell_ind_));
ROCSPARSEIO_CHECK(fread_array(in_, ell_val_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
inline status_t fwrite_sparse_gebsx(FILE* out_,
direction_t dir_,
direction_t dirb_,
uint64_t mb_,
uint64_t nb_,
uint64_t nnzb_,
uint64_t row_block_dim_,
uint64_t col_block_dim_,
type_t ptr_type_,
const void* __restrict__ ptr_,
type_t ind_type_,
const void* __restrict__ ind_,
type_t data_type_,
const void* __restrict__ data_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_gebsx, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(dir_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(dirb_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(mb_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nb_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nnzb_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(row_block_dim_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(col_block_dim_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ptr_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
switch(dir_)
{
case direction_t::row:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), mb_ + 1, ptr_));
break;
}
case direction_t::column:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), nb_ + 1, ptr_));
break;
}
}
ROCSPARSEIO_CHECK(fwrite_array(out_, ind_type_.size(), nnzb_, ind_));
ROCSPARSEIO_CHECK(
fwrite_array(out_, data_type_.size(), nnzb_ * row_block_dim_ * col_block_dim_, data_));
return status_t::success;
};
inline status_t fread_metadata_sparse_gebsx(FILE* in_,
direction_t* dir_,
direction_t* dirb_,
uint64_t* mb_,
uint64_t* nb_,
uint64_t* nnzb_,
uint64_t* row_block_dim_,
uint64_t* col_block_dim_,
type_t* ptr_type_,
type_t* ind_type_,
type_t* data_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(dir_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(dirb_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(mb_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nb_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nnzb_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(row_block_dim_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(col_block_dim_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ptr_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(data_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_gebsx(FILE* in_,
void* __restrict__ ptr_,
void* __restrict__ ind_,
void* __restrict__ data_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 12 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, ptr_));
ROCSPARSEIO_CHECK(fread_array(in_, ind_));
ROCSPARSEIO_CHECK(fread_array(in_, data_));
return status_t::success;
}
} // namespace rocsparseio
//
//
//
namespace rocsparseio
{
inline status_t fwrite_sparse_mcsx(FILE* out_,
direction_t dir_,
uint64_t m_,
uint64_t n_,
uint64_t nnz_,
type_t ptr_type_,
const void* __restrict__ ptr_,
type_t ind_type_,
const void* __restrict__ ind_,
type_t data_type_,
const void* __restrict__ data_,
index_base_t base_,
const char* name_,
...)
{
rocsparseio_string name;
if(name_)
{
va_list args;
va_start(args, name_);
if(vsnprintf(name, sizeof(rocsparseio_string), name_, args)
>= sizeof(rocsparseio_string))
{
std::cerr << "the name of the object to save is too long and would be truncated. "
<< std::endl;
return status_t::invalid_value;
}
va_end(args);
}
else
{
sprintf(name, "unknown");
}
if(size_t(1) != fwrite(name, sizeof(rocsparseio_string), 1, out_))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(format_t::sparse_mcsx, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(dir_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(m_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(n_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(nnz_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ptr_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(ind_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(data_type_, out_));
ROCSPARSEIO_CHECK(fwrite_scalar<uint64_t>(base_, out_));
switch(dir_)
{
case direction_t::row:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), m_ + 1, ptr_));
break;
}
case direction_t::column:
{
ROCSPARSEIO_CHECK(fwrite_array(out_, ptr_type_.size(), n_ + 1, ptr_));
break;
}
}
ROCSPARSEIO_CHECK(fwrite_array(out_, ind_type_.size(), nnz_, ind_));
ROCSPARSEIO_CHECK(fwrite_array(out_, data_type_.size(), nnz_, data_));
return status_t::success;
};
inline status_t fread_metadata_sparse_mcsx(FILE* in_,
direction_t* dir_,
uint64_t* m_,
uint64_t* n_,
uint64_t* nnz_,
type_t* ptr_type_,
type_t* ind_type_,
type_t* data_type_,
index_base_t* base_)
{
const long pos = ftell(in_);
if(0 != fseek(in_, sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
format_t format(0);
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(format, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(dir_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(m_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(n_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(nnz_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ptr_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(ind_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(data_type_, in_));
ROCSPARSEIO_CHECK(fread_scalar<uint64_t>(base_, in_));
if(0 != fseek(in_, pos, SEEK_SET))
{
return status_t::invalid_file_operation;
}
return status_t::success;
}
inline status_t fread_sparse_mcsx(FILE* in_,
void* __restrict__ ptr_,
void* __restrict__ ind_,
void* __restrict__ data_)
{
if(0 != fseek(in_, sizeof(uint64_t) * 9 + sizeof(rocsparseio_string), SEEK_CUR))
{
return status_t::invalid_file_operation;
}
ROCSPARSEIO_CHECK(fread_array(in_, ptr_));
ROCSPARSEIO_CHECK(fread_array(in_, ind_));
ROCSPARSEIO_CHECK(fread_array(in_, data_));
return status_t::success;
}
} // namespace rocsparseio
namespace rocsparseio
{
template <>
inline type_t type_t::convert<int32_t>()
{
return type_t::int32;
};
template <>
inline type_t type_t::convert<int64_t>()
{
return type_t::int64;
};
template <>
inline type_t type_t::convert<float>()
{
return type_t::float32;
};
template <>
inline type_t type_t::convert<double>()
{
return type_t::float64;
};
template <typename... Ts>
inline status_t read_format(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_format(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_name(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_name(handle_->f, ts_...);
}
inline status_t open(rocsparseio_handle* p_handle_, rwmode_t mode, const char* filename, ...)
{
char filename_[512];
{
va_list args;
va_start(args, filename);
if(vsnprintf(filename_, 512, filename, args) >= 512)
{
std::cerr << "string is too long and is truncated. " << std::endl;
return status_t::invalid_value;
}
va_end(args);
}
rocsparseio_handle h = new _rocsparseio_handle(mode, filename_);
p_handle_[0] = h;
h->f = nullptr;
switch(mode)
{
case rwmode_t::read:
{
h->f = fopen(filename_, "rb");
if(h->f == nullptr)
{
return status_t::invalid_file;
}
{
uint64_t ref_value[2]{};
char* p = (char*)&ref_value[0];
sprintf(p, "ROCSPARSEIO.%d", ROCSPARSEIO_VERSION_MAJOR);
uint64_t value[2]{};
if(2 != fread(&value[0], sizeof(uint64_t), 2, h->f))
{
return status_t::invalid_file_operation;
}
// std::cout << "read " << value[0] << " " << value[1] <<
//std::endl;
if(ref_value[0] != value[0] || ref_value[1] != value[1])
{
std::cerr << "incompatible rocsparseio version: " << std::endl;
std::cerr << " expected : " << ref_value[0] << "." << ref_value[1]
<< std::endl;
std::cerr << " from file : " << value[0] << "." << value[1] << std::endl;
return status_t::invalid_file;
}
}
break;
}
case rwmode_t::write:
{
h->f = fopen(filename_, "wb");
if(h->f == nullptr)
{
return status_t::invalid_file;
}
//
// WRITE HEADER
//
{
uint64_t value[2]{};
char* p = (char*)&value;
sprintf(p, "ROCSPARSEIO.%d", ROCSPARSEIO_VERSION_MAJOR);
if(2 != fwrite(&value[0], sizeof(uint64_t), 2, h->f))
{
return status_t::invalid_file_operation;
}
}
break;
}
}
return status_t::success;
}
//!
//! @brief Close.
//!
inline status_t close(rocsparseio_handle handle_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
if(handle_->f != nullptr)
{
fclose(handle_->f);
}
delete handle_;
return status_t::success;
}
template <typename... Ts>
inline status_t write_dense_vector(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_dense_vector(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_dense_vector(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_dense_vector(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_dense_vector(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_dense_vector(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_dense_matrix(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_dense_matrix(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_dense_matrix(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_dense_matrix(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_dense_matrix(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_dense_matrix(handle_->f, ts_...);
}
template <typename T, typename J>
inline status_t write_dense_matrix_template(
rocsparseio_handle handle_, order_t order_, J m_, J n_, const T* data_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
ROCSPARSEIO_CHECK_ARG(handle_->mode != rwmode_t::write, status_t::invalid_mode);
return fwrite_dense_matrix(handle_->f,
order_,
static_cast<uint64_t>(m_),
static_cast<uint64_t>(n_),
type_t::convert<T>(),
data_,
(order_ == ROCSPARSEIO_ORDER_ROW) ? static_cast<uint64_t>(n_)
: static_cast<uint64_t>(m_));
};
template <typename... Ts>
inline status_t write_sparse_csx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_csx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_csx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_csx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_csx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_csx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_coo(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_coo(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_coo(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_coo(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_coo(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_coo(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_hyb(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_hyb(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_hyb(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_hyb(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_hyb(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_hyb(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_gebsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_gebsx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_gebsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_gebsx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_gebsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_gebsx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_ell(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_ell(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_ell(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_ell(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_ell(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_ell(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_dia(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_dia(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_dia(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_dia(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_dia(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_dia(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t write_sparse_mcsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fwrite_sparse_mcsx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_metadata_sparse_mcsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_metadata_sparse_mcsx(handle_->f, ts_...);
}
template <typename... Ts>
inline status_t read_sparse_mcsx(rocsparseio_handle handle_, Ts&&... ts_)
{
ROCSPARSEIO_CHECK_ARG(!handle_, status_t::invalid_handle);
return fread_sparse_mcsx(handle_->f, ts_...);
}
} // namespace rocsparseio