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)
531 assert(arr.shape.size() == 2);
532 mat.resize(arr.shape[0], arr.shape[1]);
533 std::vector<typeNumber> data = arr.as_vec<typeNumber>();
535 if (!arr.fortran_order)
537 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
539 for (
size_t j = 0; j < arr.shape[1]; ++j)
541 mat(
i, j) = data[arr.shape[1] *
i + j];
547 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
549 for (
size_t j = 0; j < arr.shape[1]; ++j)
551 mat(
i, j) = data[arr.shape[0] * j +
i];
560template<
typename typeNumber>
561Eigen::Tensor<typeNumber, 3>
cnpy::load(Eigen::Tensor<typeNumber, 3>& tens,
562 const std::string fname)
565 assert(arr.shape.size() == 3);
566 tens.resize(
static_cast<long>(arr.shape[0]),
static_cast<long>(arr.shape[1]),
567 static_cast<long>(arr.shape[2]));
568 std::vector<typeNumber> data = arr.as_vec<typeNumber>();
570 if (!arr.fortran_order)
572 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
574 for (
size_t j = 0; j < arr.shape[1]; ++j)
576 for (
size_t k = 0; k < arr.shape[2]; ++k)
578 tens(
i, j, k) = data[arr.shape[1] * arr.shape[2] *
i + j *
586 for (
size_t i = 0;
i < arr.shape[0]; ++
i)
588 for (
size_t j = 0; j < arr.shape[1]; ++j)
590 for (
size_t k = 0; k < arr.shape[2]; ++k)
592 tens(
i, j, k) = (typeNumber) data[arr.shape[0] * arr.shape[1] * k + j *
604Eigen::SparseMatrix<T>
cnpy::load(Eigen::SparseMatrix<T>& smatrix,
605 const std::string fname)
611 std::vector<T> data = d1.as_vec<
T>();
612 int32_t* indices =
reinterpret_cast<int32_t*
>(d2.data<int32_t>());
613 int32_t* indptr =
reinterpret_cast<int32_t*
>(d3.data<int32_t>());
614 int* shape =
reinterpret_cast<int*
>(d4.data<
int>());
616 M_Assert(d4.shape[0] == 2,
"Method works only with 2-D matrices");
617 rows = (int) shape[0];
618 cols = (int) d3.shape[0] - 1;
619 int nel = d1.shape[0];
620 smatrix.resize(rows, cols);
621 smatrix.reserve(nel);
622 typedef Eigen::Triplet<T> Trip;
623 std::vector<Trip> tripletList;
625 for (
int i = 0;
i < cols; ++
i)
627 for (
int j = indptr[
i]; j < indptr[
i + 1]; j++)
629 tripletList.push_back(Trip(indices[j],
i, (
T) data[j]));
633 smatrix.setFromTriplets(tripletList.begin(), tripletList.end());
638void cnpy::save(
const Eigen::SparseMatrix<T>& mat,
const std::string fname)
640 std::vector<size_t> shape1 = std::vector<size_t> {(
unsigned long) (mat.nonZeros())};
641 std::vector<size_t> shape2 = std::vector<size_t> {(
unsigned long) (mat.outerSize() + 1)};
642 std::vector<size_t> shape3 = std::vector<size_t> {2};
643 std::vector<size_t> shape4 = std::vector<size_t> {256};
645 cnpy::npz_save(fname,
"indices", mat.innerIndexPtr(), shape1,
"a");
646 cnpy::npz_save(fname,
"indptr", mat.outerIndexPtr(), shape2,
"a");
647 int64_t t1 = mat.rows();
648 int64_t t2 = mat.cols();
649 int64_t* shape =
new int64_t[2];
650 shape[0] = mat.rows();
651 shape[1] = mat.cols();
657template void cnpy::save(
const Eigen::MatrixXi& mat,
const std::string fname);
658template Eigen::MatrixXi
cnpy::load(Eigen::MatrixXi& mat,
659 const std::string fname);
660template void cnpy::save(
const Eigen::MatrixXd& mat,
const std::string fname);
661template Eigen::MatrixXd
cnpy::load(Eigen::MatrixXd& mat,
662 const std::string fname);
663template void cnpy::save(
const Eigen::MatrixXf& mat,
const std::string fname);
664template Eigen::MatrixXf
cnpy::load(Eigen::MatrixXf& mat,
665 const std::string fname);
666template void cnpy::save(
const Eigen::MatrixXcd& mat,
const std::string fname);
667template Eigen::MatrixXcd
cnpy::load(Eigen::MatrixXcd& mat,
668 const std::string fname);
669template void cnpy::save(
const Eigen::VectorXi& mat,
const std::string fname);
670template Eigen::VectorXi
cnpy::load(Eigen::VectorXi& mat,
671 const std::string fname);
672template void cnpy::save(
const Eigen::VectorXd& mat,
const std::string fname);
673template Eigen::VectorXd
cnpy::load(Eigen::VectorXd& mat,
674 const std::string fname);
675template void cnpy::save(
const Eigen::VectorXf& mat,
const std::string fname);
676template Eigen::VectorXf
cnpy::load(Eigen::VectorXf& mat,
677 const std::string fname);
678template void cnpy::save(
const Eigen::VectorXcd& mat,
const std::string fname);
679template Eigen::VectorXcd
cnpy::load(Eigen::VectorXcd& mat,
680 const std::string fname);
681template void cnpy::save(
const Eigen::SparseMatrix<double>& mat,
682 const std::string fname);
683template Eigen::SparseMatrix<double>
cnpy::load(Eigen::SparseMatrix<double>&
684 smatrix,
const std::string fname);
686template void cnpy::save(
const Eigen::Tensor<int, 3>& mat,
687 const std::string fname);
688template Eigen::Tensor<int, 3>
cnpy::load(Eigen::Tensor<int, 3>& tens,
689 const std::string fname);
690template void cnpy::save(
const Eigen::Tensor<double, 3>& mat,
691 const std::string fname);
692template Eigen::Tensor<double, 3>
cnpy::load(Eigen::Tensor<double, 3>& tens,
693 const std::string fname);
694template void cnpy::save(
const Eigen::Tensor<float, 3>& mat,
695 const std::string fname);
696template Eigen::Tensor<float, 3>
cnpy::load(Eigen::Tensor<float, 3>& tens,
697 const std::string fname);
698template void cnpy::save(
const Eigen::Tensor<std::complex<double>, 3>& mat,
699 const std::string fname);
700template Eigen::Tensor<std::complex<double>, 3>
cnpy::load(
701 Eigen::Tensor<std::complex<double>, 3>& tens,
702 const std::string fname);
703#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)
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)
Eigen::Matrix< T, -1, dim > load(Eigen::Matrix< T, -1, dim > &mat, const 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)