12#pragma GCC diagnostic push
13#pragma GCC diagnostic ignored "-Wold-style-cast"
18 return (((
char*)&x)[0]) ?
'<' :
'>';
23 if (t ==
typeid(
float) )
28 if (t ==
typeid(
double) )
33 if (t ==
typeid(
long double) )
38 if (t ==
typeid(
int) )
43 if (t ==
typeid(
char) )
48 if (t ==
typeid(
short) )
53 if (t ==
typeid(
long) )
58 if (t ==
typeid(
long long) )
63 if (t ==
typeid(
unsigned char) )
68 if (t ==
typeid(
unsigned short) )
73 if (t ==
typeid(
unsigned long) )
78 if (t ==
typeid(
unsigned long long) )
83 if (t ==
typeid(
unsigned int) )
88 if (t ==
typeid(
bool) )
93 if (t ==
typeid(std::complex<float>) )
98 if (t ==
typeid(std::complex<double>) )
103 if (t ==
typeid(std::complex<long double>) )
114 const std::string rhs)
116 lhs.insert(lhs.end(), rhs.begin(), rhs.end());
124 size_t len = strlen(rhs);
127 for (
size_t byte = 0;
byte < len;
byte++)
129 lhs.push_back(rhs[
byte]);
136 std::vector<size_t>& shape,
bool& fortran_order, std::string& number_type)
139 uint8_t major_version = *
reinterpret_cast<uint8_t*
>(buffer + 6);
140 uint8_t minor_version = *
reinterpret_cast<uint8_t*
>(buffer + 7);
141 uint16_t header_len = *
reinterpret_cast<uint16_t*
>(buffer + 8);
142 std::string header(
reinterpret_cast<char*
>(buffer + 9), header_len);
145 loc1 = header.find(
"fortran_order") + 16;
146 fortran_order = (header.substr(loc1, 4) ==
"True" ? true :
false);
148 loc1 = header.find(
"(");
149 loc2 = header.find(
")");
150 std::regex num_regex(
"[0-9][0-9]*");
153 std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1);
155 while (std::regex_search(str_shape, sm, num_regex))
157 shape.push_back(std::stoi(sm[0].str()));
158 str_shape = sm.suffix().str();
164 loc1 = header.find(
"descr") + 9;
165 bool littleEndian = (header[loc1] ==
'<' || header[loc1] ==
'|' ? true :
false);
166 assert(littleEndian);
169 number_type = header.substr(loc1 + 1, 2);
170 std::string str_ws = header.substr(loc1 + 2);
171 loc2 = str_ws.find(
"'");
172 word_size = atoi(str_ws.substr(0, loc2).c_str());
176 std::vector<size_t>& shape,
bool& fortran_order, std::string& number_type)
179 size_t res = fread(buffer,
sizeof(
char), 11, fp);
183 throw std::runtime_error(
"parse_npy_header: failed fread");
186 std::string header = fgets(buffer, 256, fp);
187 assert(header[header.size() - 1] ==
'\n');
190 loc1 = header.find(
"fortran_order");
192 if (loc1 == std::string::npos)
194 throw std::runtime_error(
"parse_npy_header: failed to find header keyword: 'fortran_order'");
198 fortran_order = (header.substr(loc1, 4) ==
"True" ? true :
false);
200 loc1 = header.find(
"(");
201 loc2 = header.find(
")");
203 if (loc1 == std::string::npos || loc2 == std::string::npos)
205 throw std::runtime_error(
"parse_npy_header: failed to find header keyword: '(' or ')'");
208 std::regex num_regex(
"[0-9][0-9]*");
211 std::string str_shape = header.substr(loc1 + 1, loc2 - loc1 - 1);
213 while (std::regex_search(str_shape, sm, num_regex))
215 shape.push_back(std::stoi(sm[0].str()));
216 str_shape = sm.suffix().str();
222 loc1 = header.find(
"descr");
224 if (loc1 == std::string::npos)
226 throw std::runtime_error(
"parse_npy_header: failed to find header keyword: 'descr'");
230 bool littleEndian = (header[loc1] ==
'<' || header[loc1] ==
'|' ? true :
false);
231 assert(littleEndian);
234 std::string str_ws = header.substr(loc1 + 2);
235 number_type = header.substr(loc1 + 1, 2);
236 loc2 = str_ws.find(
"'");
237 word_size = atoi(str_ws.substr(0, loc2).c_str());
241 size_t& global_header_size,
size_t& global_header_offset)
243 std::vector<char> footer(22);
244 fseek(fp, -22, SEEK_END);
245 size_t res = fread(&footer[0],
sizeof(
char), 22, fp);
249 throw std::runtime_error(
"parse_zip_footer: failed fread");
252 uint16_t disk_no, disk_start, nrecs_on_disk, comment_len;
253 disk_no = *(uint16_t*) &footer[4];
254 disk_start = *(uint16_t*) &footer[6];
255 nrecs_on_disk = *(uint16_t*) &footer[8];
256 nrecs = *(uint16_t*) &footer[10];
257 global_header_size = *(uint32_t*) &footer[12];
258 global_header_offset = *(uint32_t*) &footer[16];
259 comment_len = *(uint16_t*) &footer[20];
260 assert(disk_no == 0);
261 assert(disk_start == 0);
262 assert(nrecs_on_disk == nrecs);
263 assert(comment_len == 0);
268 std::vector<size_t> shape;
271 std::string number_type;
274 size_t nread = fread(arr.
data<
char>(), 1, arr.
num_bytes(), fp);
278 throw std::runtime_error(
"load_the_npy_file: failed fread");
286 FILE* fp = fopen(fname.c_str(),
"rb");
291 uint32_t uncompr_bytes)
293 std::vector<unsigned char> buffer_compr(compr_bytes);
294 std::vector<unsigned char> buffer_uncompr(uncompr_bytes);
295 size_t nread = fread(&buffer_compr[0], 1, compr_bytes, fp);
297 if (nread != compr_bytes)
299 throw std::runtime_error(
"load_the_npy_file: failed fread");
304 d_stream.zalloc = Z_NULL;
305 d_stream.zfree = Z_NULL;
306 d_stream.opaque = Z_NULL;
307 d_stream.avail_in = 0;
308 d_stream.next_in = Z_NULL;
309 err = inflateInit2(&d_stream, -MAX_WBITS);
310 d_stream.avail_in = compr_bytes;
311 d_stream.next_in = &buffer_compr[0];
312 d_stream.avail_out = uncompr_bytes;
313 d_stream.next_out = &buffer_uncompr[0];
314 err = inflate(&d_stream, Z_FINISH);
315 err = inflateEnd(&d_stream);
316 std::vector<size_t> shape;
319 std::string number_type;
322 cnpy::NpyArray array(shape, word_size, fortran_order, number_type);
323 size_t offset = uncompr_bytes - array.
num_bytes();
324 memcpy(array.
data<
unsigned char>(), &buffer_uncompr[0] + offset,
331 FILE* fp = fopen(fname.c_str(),
"rb");
335 throw std::runtime_error(
"npz_load: Error! Unable to open file " + fname +
"!");
342 std::vector<char> local_header(30);
343 size_t headerres = fread(&local_header[0],
sizeof(
char), 30, fp);
347 throw std::runtime_error(
"npz_load: failed fread");
351 if (local_header[2] != 0x03 || local_header[3] != 0x04)
357 uint16_t name_len = *(uint16_t*) &local_header[26];
358 std::string varname(name_len,
' ');
359 size_t vname_res = fread(&varname[0],
sizeof(
char), name_len, fp);
361 if (vname_res != name_len)
363 throw std::runtime_error(
"npz_load: failed fread");
367 varname.erase(varname.end() - 4, varname.end());
369 uint16_t extra_field_len = *(uint16_t*) &local_header[28];
371 if (extra_field_len > 0)
373 std::vector<char> buff(extra_field_len);
374 size_t efield_res = fread(&buff[0],
sizeof(
char), extra_field_len, fp);
376 if (efield_res != extra_field_len)
378 throw std::runtime_error(
"npz_load: failed fread");
382 uint16_t compr_method = *
reinterpret_cast<uint16_t*
>(&local_header[0] + 8);
383 uint32_t compr_bytes = *
reinterpret_cast<uint32_t*
>(&local_header[0] + 18);
384 uint32_t uncompr_bytes = *
reinterpret_cast<uint32_t*
>(&local_header[0] + 22);
386 if (compr_method == 0)
402 FILE* fp = fopen(fname.c_str(),
"rb");
406 throw std::runtime_error(
"npz_load: Unable to open file " + fname);
411 std::vector<char> local_header(30);
412 size_t header_res = fread(&local_header[0],
sizeof(
char), 30, fp);
414 if (header_res != 30)
416 throw std::runtime_error(
"npz_load: failed fread");
420 if (local_header[2] != 0x03 || local_header[3] != 0x04)
426 uint16_t name_len = *(uint16_t*) &local_header[26];
427 std::string vname(name_len,
' ');
428 size_t vname_res = fread(&vname[0],
sizeof(
char), name_len, fp);
430 if (vname_res != name_len)
432 throw std::runtime_error(
"npz_load: failed fread");
435 vname.erase(vname.end() - 4, vname.end());
437 uint16_t extra_field_len = *(uint16_t*) &local_header[28];
438 fseek(fp, extra_field_len, SEEK_CUR);
439 uint16_t compr_method = *
reinterpret_cast<uint16_t*
>(&local_header[0] + 8);
440 uint32_t compr_bytes = *
reinterpret_cast<uint32_t*
>(&local_header[0] + 18);
441 uint32_t uncompr_bytes = *
reinterpret_cast<uint32_t*
>(&local_header[0] + 22);
443 if (vname == varname)
453 uint32_t size = *(uint32_t*) &local_header[22];
454 fseek(fp, size, SEEK_CUR);
460 throw std::runtime_error(
"npz_load: Variable name " + varname +
" not found in "
466 FILE* fp = fopen(fname.c_str(),
"rb");
470 throw std::runtime_error(
"npy_load: Unable to open file " + fname);
478template<
class typeNumber,
int dim>
479void cnpy::save(
const Eigen::Matrix<typeNumber, Eigen::Dynamic, dim>&
480 mat,
const std::string fname)
482 std::vector<typeNumber> matvec(mat.rows() * mat.cols());
483 std::vector<size_t> shape = {(
unsigned int) mat.rows(), (
unsigned int)mat.cols()};
485 for (
int i = 0;
i < mat.rows(); ++
i)
487 for (
int j = 0; j < mat.cols(); ++j)
489 matvec[
i * mat.cols() + j] = mat(
i, j);
493 npy_save(fname, matvec.data(), shape);
496template<
class typeNumber>
497void cnpy::save(
const Eigen::Tensor<typeNumber, 3>&
498 tens,
const std::string fname)
500 typename Eigen::Tensor<typeNumber, 3>::Dimensions dim = tens.dimensions();
503 for (
int k = 0; k < dim.size(); k++)
508 std::vector<typeNumber> matvec(tot);
509 std::vector<size_t> shape = {(
unsigned int) dim[0], (
unsigned int) dim[1], (
unsigned int) dim[2]};
511 for (
int i = 0;
i < dim[0]; ++
i)
513 for (
int j = 0; j < dim[1]; ++j)
515 for (
int k = 0; k < dim[2]; ++k)
517 matvec[
i * dim[2]*dim[1] + j * dim[2] + k] = tens(
i, j, k);
522 npy_save(fname, matvec.data(), shape);
525template<
class typeNumber,
int dim>
526Eigen::Matrix<typeNumber, Eigen::Dynamic, dim>
cnpy::load(
527 Eigen::Matrix<typeNumber, Eigen::Dynamic, dim>& mat,
528 const std::string fname, std::string order)
531 order ==
"colMajor",
"Order can be only rowMajor or colMajor");
533 assert(arr.shape.size() == 2);
534 mat.resize(arr.shape[0], arr.shape[1]);
535 std::vector<typeNumber> data = arr.as_vec<typeNumber>();
537 if (order ==
"rowMajor")
539 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
541 for (
size_t j = 0; j < arr.shape[1]; ++j)
543 mat(
i, j) = data[arr.shape[1] *
i + j];
547 else if (order ==
"colMajor")
549 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
551 for (
size_t j = 0; j < arr.shape[1]; ++j)
553 data[arr.shape[0] * j +
i];
562template<
typename typeNumber>
563Eigen::Tensor<typeNumber, 3>
cnpy::load(Eigen::Tensor<typeNumber, 3>& tens,
564 const std::string fname, std::string order)
567 order ==
"colMajor",
"Order can be only rowMajor or colMajor");
569 assert(arr.shape.size() == 3);
570 tens.resize(
static_cast<long>(arr.shape[0]),
static_cast<long>(arr.shape[1]),
571 static_cast<long>(arr.shape[2]));
572 std::vector<typeNumber> data = arr.as_vec<typeNumber>();
574 if (order ==
"rowMajor")
576 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
578 for (
size_t j = 0; j < arr.shape[1]; ++j)
580 for (
size_t k = 0; k < arr.shape[2]; ++k)
582 tens(
i, j, k) = data[arr.shape[1] * arr.shape[2] *
i + j *
588 else if (order ==
"colMajor")
590 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
592 for (
size_t j = 0; j < arr.shape[1]; ++j)
594 for (
size_t k = 0; k < arr.shape[2]; ++k)
596 tens(
i, j, k) = (typeNumber) data[arr.shape[0] * arr.shape[1] * k + j *
608Eigen::SparseMatrix<T>
cnpy::load(Eigen::SparseMatrix<T>& smatrix,
609 const std::string fname)
615 std::vector<T> data = d1.as_vec<
T>();
616 int32_t* indices =
reinterpret_cast<int32_t*
>(d2.data<int32_t>());
617 int32_t* indptr =
reinterpret_cast<int32_t*
>(d3.data<int32_t>());
618 int* shape =
reinterpret_cast<int*
>(d4.data<
int>());
620 M_Assert(d4.shape[0] == 2,
"Method works only with 2-D matrices");
621 rows = (int) shape[0];
622 cols = (int) d3.shape[0] - 1;
623 int nel = d1.shape[0];
624 smatrix.resize(rows, cols);
625 smatrix.reserve(nel);
626 typedef Eigen::Triplet<T> Trip;
627 std::vector<Trip> tripletList;
629 for (
int i = 0;
i < cols; ++
i)
631 for (
int j = indptr[
i]; j < indptr[
i + 1]; j++)
633 tripletList.push_back(Trip(indices[j],
i, (
T) data[j]));
637 smatrix.setFromTriplets(tripletList.begin(), tripletList.end());
642void cnpy::save(
const Eigen::SparseMatrix<T>& mat,
const std::string fname)
644 std::vector<size_t> shape1 = std::vector<size_t> {(
unsigned long) (mat.nonZeros())};
645 std::vector<size_t> shape2 = std::vector<size_t> {(
unsigned long) (mat.outerSize() + 1)};
646 std::vector<size_t> shape3 = std::vector<size_t> {2};
647 std::vector<size_t> shape4 = std::vector<size_t> {256};
649 cnpy::npz_save(fname,
"indices", mat.innerIndexPtr(), shape1,
"a");
650 cnpy::npz_save(fname,
"indptr", mat.outerIndexPtr(), shape2,
"a");
651 int64_t t1 = mat.rows();
652 int64_t t2 = mat.cols();
653 int64_t* shape =
new int64_t[2];
654 shape[0] = mat.rows();
655 shape[1] = mat.cols();
661template void cnpy::save(
const Eigen::MatrixXi& mat,
const std::string fname);
662template Eigen::MatrixXi
cnpy::load(Eigen::MatrixXi& mat,
663 const std::string fname, std::string order);
664template void cnpy::save(
const Eigen::MatrixXd& mat,
const std::string fname);
665template Eigen::MatrixXd
cnpy::load(Eigen::MatrixXd& mat,
666 const std::string fname, std::string order);
667template void cnpy::save(
const Eigen::MatrixXf& mat,
const std::string fname);
668template Eigen::MatrixXf
cnpy::load(Eigen::MatrixXf& mat,
669 const std::string fname, std::string order);
670template void cnpy::save(
const Eigen::MatrixXcd& mat,
const std::string fname);
671template Eigen::MatrixXcd
cnpy::load(Eigen::MatrixXcd& mat,
672 const std::string fname, std::string order);
673template void cnpy::save(
const Eigen::VectorXi& mat,
const std::string fname);
674template Eigen::VectorXi
cnpy::load(Eigen::VectorXi& mat,
675 const std::string fname, std::string order);
676template void cnpy::save(
const Eigen::VectorXd& mat,
const std::string fname);
677template Eigen::VectorXd
cnpy::load(Eigen::VectorXd& mat,
678 const std::string fname, std::string order);
679template void cnpy::save(
const Eigen::VectorXf& mat,
const std::string fname);
680template Eigen::VectorXf
cnpy::load(Eigen::VectorXf& mat,
681 const std::string fname, std::string order);
682template void cnpy::save(
const Eigen::VectorXcd& mat,
const std::string fname);
683template Eigen::VectorXcd
cnpy::load(Eigen::VectorXcd& mat,
684 const std::string fname, std::string order);
685template void cnpy::save(
const Eigen::SparseMatrix<double>& mat,
686 const std::string fname);
687template Eigen::SparseMatrix<double>
cnpy::load(Eigen::SparseMatrix<double>&
688 smatrix,
const std::string fname);
690template void cnpy::save(
const Eigen::Tensor<int, 3>& mat,
691 const std::string fname);
692template Eigen::Tensor<int, 3>
cnpy::load(Eigen::Tensor<int, 3>& tens,
693 const std::string fname, std::string order);
694template void cnpy::save(
const Eigen::Tensor<double, 3>& mat,
695 const std::string fname);
696template Eigen::Tensor<double, 3>
cnpy::load(Eigen::Tensor<double, 3>& tens,
697 const std::string fname, std::string order);
698template void cnpy::save(
const Eigen::Tensor<float, 3>& mat,
699 const std::string fname);
700template Eigen::Tensor<float, 3>
cnpy::load(Eigen::Tensor<float, 3>& tens,
701 const std::string fname, std::string order);
702template void cnpy::save(
const Eigen::Tensor<std::complex<double>, 3>& mat,
703 const std::string fname);
704template Eigen::Tensor<std::complex<double>, 3>
cnpy::load(
705 Eigen::Tensor<std::complex<double>, 3>& tens,
706 const std::string fname, std::string order);
707#pragma GCC diagnostic pop
#define M_Assert(Expr, Msg)
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
cnpy::NpyArray load_the_npz_array(FILE *fp, uint32_t compr_bytes, uint32_t uncompr_bytes)
void parse_zip_footer(FILE *fp, uint16_t &nrecs, size_t &global_header_size, size_t &global_header_offset)
void save(const Eigen::Matrix< T, -1, dim > &mat, const std::string fname)
std::map< std::string, NpyArray > npz_t
cnpy::NpyArray load_the_npy_file(FILE *fp)
char map_type(const std::type_info &t)
Eigen::Matrix< T, -1, dim > load(Eigen::Matrix< T, -1, dim > &mat, const std::string fname, std::string order="rowMajor")
npz_t npz_load(std::string fname)
void npy_save(std::string fname, const T *data, const std::vector< size_t > shape, std::string mode="w")
NpyArray npy_load(std::string fname)
void npz_save(std::string zipname, std::string fname, const T *data, const std::vector< size_t > &shape, std::string mode="w")
void parse_npy_header(FILE *fp, size_t &word_size, std::vector< size_t > &shape, bool &fortran_order, std::string &number_type)
std::vector< char > & operator+=(std::vector< char > &lhs, const T rhs)