Created
April 14, 2017 05:21
-
-
Save bshillingford/fff3298e93cbee07c71d674f210f89fe to your computer and use it in GitHub Desktop.
C++ numpy format deserializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _READNP_H_ | |
#define _READNP_H_ | |
// Simple header-only library for loading serialized numpy arrays. | |
// Only for testing. | |
#include <algorithm> | |
#include <cassert> | |
#include <fstream> | |
#include <regex> | |
#include <string> | |
#include <vector> | |
template<typename T> | |
inline void readnp(std::string fn, std::vector<T>& data, std::vector<uint64_t>& shape) { | |
static_assert(std::is_same<T, float>::value | |
|| std::is_same<T, int>::value, "unsupported type"); | |
static std::string signature = "\x93NUMPY"; | |
std::ifstream f(fn); | |
std::string line; | |
std::getline(f, line, '\n'); | |
//std::cout << "line: " << line << std::endl; | |
// many filetypes are handled by np.load, so check it's the right kind: | |
assert(std::equal(signature.begin(), signature.end(), line.begin())); | |
// double check types: | |
if (std::is_same<T, float>::value) { // float == <f4 | |
assert(std::regex_search(line, std::regex(R"('descr':\s*'<f4')"))); | |
} else if (std::is_same<T, int>::value) { // int == <i4 | |
assert(std::regex_search(line, std::regex(R"('descr':\s*'<i4')"))); | |
} | |
assert(std::regex_search(line, std::regex(R"('fortran_order':\s*False)"))); | |
// get shape: | |
std::smatch mat; | |
assert(std::regex_search(line, mat, std::regex(R"('shape':\s*\(([\d, ]+)\))"))); | |
std::string shape_str = mat.str(1); | |
//std::cout << "shape = " << shape_str << std::endl; | |
assert(shape.empty()); | |
std::smatch num_match; | |
std::regex num_re("\\d+"); | |
uint64_t nelem = 1; | |
while(std::regex_search(shape_str, num_match, num_re)) { | |
uint64_t dim = std::stol(num_match.str(0)); | |
//std::cout << "dim: " << dim << std::endl; | |
shape.push_back(dim); | |
nelem *= dim; | |
shape_str = num_match.suffix(); | |
} | |
// populate data: | |
data.resize(nelem); | |
f.read(reinterpret_cast<char*>(&data[0]), sizeof(T) * nelem); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment