libnpy 2.0.0
Lightweight C++ library for reading and writing NPY and NPZ files
Loading...
Searching...
No Matches
npy.h
Go to the documentation of this file.
1
17
18#ifndef _NPY_H_
19#define _NPY_H_
20
21#include <algorithm>
22#include <cassert>
23#include <cstdint>
24#include <filesystem>
25#include <fstream>
26#include <map>
27#include <sstream>
28#include <stdexcept>
29#include <string>
30#include <vector>
31
32#define NPY_VERSION_MAJOR 2
33#define NPY_VERSION_MINOR 0
34#define NPY_VERSION_PATCH 0
35#define NPY_VERSION_STRING "2.0.0"
36
37const int STATIC_HEADER_LENGTH = 10;
38
39namespace npy {
41enum class endian_t : char {
44 NATIVE,
46 BIG,
48 LITTLE
49};
50
53 union {
54 std::uint32_t i;
55 char c[4];
56 } endian_test = {0x01020304};
57
58 return endian_test.c[0] == 1 ? endian_t::BIG : endian_t::LITTLE;
59};
60
63enum class data_type_t : char {
65 INT8,
67 UINT8,
69 INT16,
71 UINT16,
73 INT32,
75 UINT32,
77 INT64,
79 UINT64,
81 FLOAT32,
83 FLOAT64,
90};
91
97const std::string &to_dtype(data_type_t dtype,
98 endian_t endian = endian_t::NATIVE);
99
103const std::pair<data_type_t, endian_t> &from_dtype(const std::string &dtype);
104
105std::ostream &operator<<(std::ostream &os, const endian_t &obj);
106std::ostream &operator<<(std::ostream &os, const data_type_t &obj);
107
113 explicit header_info(const std::string &dictionary);
114
117 const std::vector<size_t> &shape);
118
121
124
128
130 std::vector<size_t> shape;
131
135};
136
146template <typename CHAR>
147void write_npy_header(std::basic_ostream<CHAR> &output,
148 const std::string &dtype, bool fortran_order,
149 const std::vector<size_t> &shape) {
150 std::ostringstream buff;
151 buff << "{'descr': '" << dtype;
152 buff << "', 'fortran_order': " << (fortran_order ? "True" : "False");
153 buff << ", 'shape': (";
154 for (auto dim = shape.begin(); dim < shape.end(); ++dim) {
155 buff << *dim;
156 if (dim < shape.end() - 1) {
157 buff << ", ";
158 }
159 }
160
161 if (shape.size() == 1) {
162 buff << ",";
163 }
164
165 buff << "), }";
166 std::string dictionary = buff.str();
167 auto dict_length = dictionary.size() + 1;
168 std::string end = "\n";
169 auto header_length = dict_length + STATIC_HEADER_LENGTH;
170 if (header_length % 64 != 0) {
171 header_length = ((header_length / 64) + 1) * 64;
172 dict_length = header_length - STATIC_HEADER_LENGTH;
173 end = std::string(dict_length - dictionary.length(), ' ');
174 end.back() = '\n';
175 }
176
177 const char header[STATIC_HEADER_LENGTH] = {
178 static_cast<char>(0x93), 'N', 'U', 'M', 'P', 'Y', 0x01, 0x00,
179 static_cast<char>(dict_length), 0x00};
180 output.write(header, STATIC_HEADER_LENGTH);
181 output.write(reinterpret_cast<const CHAR *>(dictionary.data()),
182 dictionary.length());
183 output.write(reinterpret_cast<const CHAR *>(end.data()), end.length());
184}
185
193template <typename T, typename CHAR>
194void write_values(std::basic_ostream<CHAR> &output, const T *data_ptr,
195 size_t num_elements, endian_t endianness);
196
203template <typename T, typename CHAR>
204void save(std::basic_ostream<CHAR> &output, const T &tensor,
205 endian_t endianness = npy::endian_t::NATIVE) {
206 std::vector<size_t> shape;
207 for (size_t d = 0; d < tensor.ndim(); ++d) {
208 shape.push_back(tensor.shape(d));
209 }
210
211 write_npy_header(output, tensor.dtype(endianness), tensor.fortran_order(),
212 shape);
213 tensor.save(output, endianness);
214};
215
223template <typename T, template <typename> class TENSOR, typename CHAR>
224void save(std::basic_ostream<CHAR> &output, const TENSOR<T> &tensor,
225 endian_t endianness = npy::endian_t::NATIVE) {
226 save<TENSOR<T>, CHAR>(output, tensor, endianness);
227}
228
234template <typename T>
235void save(const std::string &path, T &tensor,
236 endian_t endianness = npy::endian_t::NATIVE) {
237 std::ofstream output(path, std::ios::out | std::ios::binary);
238 if (!output.is_open()) {
239 throw std::invalid_argument("path");
240 }
241
242 save<T>(output, tensor, endianness);
243};
244
251template <typename T, template <typename> class TENSOR>
252void save(const std::string &path, T &tensor,
253 endian_t endianness = npy::endian_t::NATIVE) {
254 save<TENSOR<T>>(path, tensor, endianness);
255};
256
260template <typename CHAR>
261header_info read_npy_header(std::basic_istream<CHAR> &input) {
262 std::uint8_t header[STATIC_HEADER_LENGTH];
263 input.read(reinterpret_cast<CHAR *>(header), STATIC_HEADER_LENGTH);
264 assert(header[0] == 0x93);
265 assert(header[1] == 'N');
266 assert(header[2] == 'U');
267 assert(header[3] == 'M');
268 assert(header[4] == 'P');
269 assert(header[5] == 'Y');
270 size_t dict_length = 0;
271 if (header[6] == 0x01 && header[7] == 0x00) {
272 dict_length = header[8] | (header[9] << 8);
273 } else if (header[6] == 0x02 && header[7] == 0x00) {
274 std::uint8_t extra[2];
275 input.read(reinterpret_cast<CHAR *>(extra), 2);
276 dict_length =
277 header[8] | (header[9] << 8) | (extra[0] << 16) | (extra[1] << 24);
278 }
279
280 std::vector<CHAR> buffer(dict_length);
281 input.read(buffer.data(), dict_length);
282 std::string dictionary(buffer.begin(), buffer.end());
283 return header_info(dictionary);
284}
285
293template <typename T, typename CHAR>
294void read_values(std::basic_istream<CHAR> &input, T *data_ptr,
295 size_t num_elements, const header_info &info);
296
297template <typename T, typename CHAR> T load(std::basic_istream<CHAR> &input) {
298 header_info info = read_npy_header(input);
299 return T::load(input, info);
300}
301
308template <typename T> T load(const std::string &path) {
309 std::ifstream input(path, std::ios::in | std::ios::binary);
310 if (!input.is_open()) {
311 throw std::invalid_argument("path");
312 }
313
314 return load<T>(input);
315}
316
323template <typename T, template <typename> class TENSOR>
324TENSOR<T> load(const std::string &path) {
325 return load<TENSOR<T>>(path);
326}
327
331template <typename CHAR> header_info peek(std::basic_istream<CHAR> &input) {
332 return read_npy_header(input);
333}
334
338header_info peek(const std::string &path);
339
342enum class compression_method_t : std::uint16_t {
344 STORED = 0,
346 DEFLATED = 8
347};
348
352 std::string filename;
354 std::uint32_t crc32;
356 std::uint64_t compressed_size;
358 std::uint64_t uncompressed_size;
360 std::uint16_t compression_method;
362 std::uint64_t offset;
363
367 bool check(const file_entry &other) const;
368};
369
372public:
378 endian_t endianness = npy::endian_t::NATIVE);
379
383
386 std::string str() const;
387
390 void close();
391
396 template <typename T>
397 void write(const std::string &filename, const T &tensor) {
398 if (m_closed) {
399 throw std::runtime_error("Stream is closed");
400 }
401
402 std::ostringstream output;
403 save<T>(output, tensor, m_endianness);
404
405 std::string suffix = ".npy";
406 std::string name = filename;
407 if (name.size() < 4 ||
408 !std::equal(suffix.rbegin(), suffix.rend(), name.rbegin())) {
409 name += ".npy";
410 }
411
412 write_file(name, output.str());
413 }
414
415private:
419 void write_file(const std::string &filename, std::string &&bytes);
420
421 bool m_closed;
422 std::ostringstream m_output;
423 compression_method_t m_compression_method;
424 endian_t m_endianness;
425 std::vector<file_entry> m_entries;
426};
427
430public:
435 npzfilewriter(const std::string &path,
437 endian_t endianness = npy::endian_t::NATIVE);
438
443 npzfilewriter(const char *path,
445 endian_t endianness = npy::endian_t::NATIVE);
446
451 npzfilewriter(const std::filesystem::path &path,
453 endian_t endianness = npy::endian_t::NATIVE);
454
458
460 bool is_open() const;
461
464 void close();
465
470 template <typename T>
471 void write(const std::string &filename, const T &tensor) {
472 if (m_closed) {
473 throw std::runtime_error("Stream is closed");
474 }
475
476 std::ostringstream output;
477 save<T>(output, tensor, m_endianness);
478
479 std::string suffix = ".npy";
480 std::string name = filename;
481 if (name.size() < 4 ||
482 !std::equal(suffix.rbegin(), suffix.rend(), name.rbegin())) {
483 name += ".npy";
484 }
485
486 write_file(name, output.str());
487 }
488
489private:
493 void write_file(const std::string &filename, std::string &&bytes);
494
495 bool m_closed;
496 std::ofstream m_output;
497 compression_method_t m_compression_method;
498 endian_t m_endianness;
499 std::vector<file_entry> m_entries;
500};
501
504public:
507 npzstringreader(const std::string &bytes);
508
511 npzstringreader(std::string &&bytes);
512
514 const std::vector<std::string> &keys() const;
515
519 bool contains(const std::string &filename);
520
524 header_info peek(const std::string &filename);
525
534 template <typename T> T read(const std::string &filename) {
535 std::istringstream stream(read_file(filename));
536 return load<T>(stream);
537 }
538
539 template <typename T, template <typename> class TENSOR>
540 TENSOR<T> read(const std::string &filename) {
541 return read<TENSOR<T>>(filename);
542 }
543
544private:
548 std::string read_file(const std::string &filename);
549
551 void read_entries();
552
553 std::istringstream m_input;
554 std::map<std::string, file_entry> m_entries;
555 std::vector<std::string> m_keys;
556};
557
560public:
563 npzfilereader(const std::string &path);
564
567 npzfilereader(const char *path);
568
571 npzfilereader(const std::filesystem::path &path);
572
574 bool is_open() const;
575
577 void close();
578
580 const std::vector<std::string> &keys() const;
581
585 bool contains(const std::string &filename);
586
590 header_info peek(const std::string &filename);
591
599 template <typename T> T read(const std::string &filename) {
600 std::istringstream stream(read_file(filename));
601 return load<T>(stream);
602 }
603
612 template <typename T, template <typename> class TENSOR>
613 TENSOR<T> read(const std::string &filename) {
614 read<TENSOR<T>>(filename);
615 }
616
617private:
621 std::string read_file(const std::string &filename);
622
624 void read_entries();
625
626 std::ifstream m_input;
627 std::map<std::string, file_entry> m_entries;
628 std::vector<std::string> m_keys;
629};
630
650template <typename T> class tensor {
651public:
653 typedef T value_type;
661 typedef const value_type *const_pointer;
662
667 tensor(const std::vector<size_t> &shape) : tensor(shape, false) {}
668
674 tensor(const std::vector<size_t> &shape, bool fortran_order)
675 : m_shape(shape),
676 m_ravel_strides(tensor<T>::get_ravel_strides(shape, fortran_order)),
677 m_fortran_order(fortran_order), m_dtype(tensor<T>::get_dtype()),
678 m_values(tensor<T>::get_size(shape)) {}
679
681 tensor(const tensor<T> &other)
682 : m_shape(other.m_shape), m_ravel_strides(other.m_ravel_strides),
683 m_fortran_order(other.m_fortran_order), m_dtype(other.m_dtype),
684 m_values(other.m_values) {}
685
688 : m_shape(std::move(other.m_shape)),
689 m_ravel_strides(std::move(other.m_ravel_strides)),
690 m_fortran_order(other.m_fortran_order), m_dtype(other.m_dtype),
691 m_values(std::move(other.m_values)) {}
692
694 static tensor<T> from_file(const std::string &path) {
695 return npy::load<tensor<T>>(path);
696 }
697
708 static tensor<T> load(std::basic_istream<char> &input,
709 const header_info &info) {
710 tensor<T> result(info.shape, info.fortran_order);
711 if (info.dtype != result.dtype()) {
712 throw std::runtime_error("requested dtype does not match stream's dtype");
713 }
714
715 read_values(input, result.m_values.data(), result.m_values.size(), info);
716
717 return result;
718 }
719
728 void save(std::basic_ostream<char> &output, endian_t endianness) const {
729 write_values(output, m_values.data(), m_values.size(), endianness);
730 }
731
736 template <typename... Indices> const T &operator()(Indices... index) const {
737 return m_values[ravel(std::vector<std::int32_t>({index...}))];
738 }
739
743 const T &operator()(const std::vector<std::size_t> &multi_index) const {
744 return m_values[ravel(multi_index)];
745 }
746
751 template <typename... Indices> T &operator()(Indices... index) {
752 return m_values[ravel(std::vector<std::int32_t>({index...}))];
753 }
754
758 T &operator()(const std::vector<std::size_t> &multi_index) {
759 return m_values[ravel(multi_index)];
760 }
761
763 typename std::vector<T>::iterator begin() { return m_values.begin(); }
764
766 typename std::vector<T>::const_iterator begin() const {
767 return m_values.begin();
768 }
769
771 typename std::vector<T>::iterator end() { return m_values.end(); }
772
774 typename std::vector<T>::const_iterator end() const { return m_values.end(); }
775
779 void set(const std::vector<std::int32_t> &multi_index, const T &value) {
780 m_values[ravel(multi_index)] = value;
781 }
782
786 const T &get(const std::vector<std::int32_t> &multi_index) const {
787 return m_values[ravel(multi_index)];
788 }
789
791 std::string dtype(endian_t endianness) const {
792 return to_dtype(m_dtype, endianness);
793 }
794
799 data_type_t dtype() const { return m_dtype; };
800
802 const std::vector<T> &values() const { return m_values; }
803
807 void copy_from(const T *source, size_t nitems) {
808 if (nitems != size()) {
809 throw std::invalid_argument("nitems");
810 }
811
812 std::copy(source, source + nitems, m_values.begin());
813 }
814
817 void copy_from(const std::vector<T> &source) {
818 if (source.size() != size()) {
819 throw std::invalid_argument("source.size");
820 }
821
822 std::copy(source.begin(), source.end(), m_values.begin());
823 }
824
827 void move_from(std::vector<T> &&source) {
828 if (source.size() != size()) {
829 throw std::invalid_argument("source.size");
830 }
831
832 m_values = std::move(source);
833 }
834
836 T *data() { return m_values.data(); }
837
839 const T *data() const { return m_values.data(); }
840
842 size_t size() const { return m_values.size(); }
843
846 const std::vector<size_t> &shape() const { return m_shape; }
847
853 size_t shape(int index) const { return m_shape[index]; }
854
859 size_t ndim() const { return m_shape.size(); }
860
866 bool fortran_order() const { return m_fortran_order; }
867
870 m_shape = other.m_shape;
871 m_ravel_strides = other.m_ravel_strides;
872 m_fortran_order = other.m_fortran_order;
873 m_dtype = other.m_dtype;
874 m_values = other.m_values;
875 return *this;
876 }
877
880 m_shape = std::move(other.m_shape);
881 m_ravel_strides = std::move(other.m_ravel_strides);
882 m_fortran_order = other.m_fortran_order;
883 m_dtype = other.m_dtype;
884 m_values = std::move(other.m_values);
885 return *this;
886 }
887
891 void save(const std::string &path,
892 endian_t endianness = npy::endian_t::NATIVE) {
893 npy::save(path, *this, endianness);
894 }
895
902 template <class INDEX_IT, class SHAPE_IT>
903 size_t ravel(INDEX_IT index, SHAPE_IT shape) const {
904 std::size_t ravel = 0;
905 for (auto stride = m_ravel_strides.begin(); stride < m_ravel_strides.end();
906 ++index, ++shape, ++stride) {
907 if (*index >= *shape) {
908 throw std::invalid_argument("multi_index");
909 }
910
911 ravel += *index * *stride;
912 }
913
914 return ravel;
915 }
916
920 size_t ravel(const std::vector<std::int32_t> &multi_index) const {
921 if (multi_index.size() != m_shape.size()) {
922 throw std::invalid_argument("multi_index");
923 }
924
925 std::vector<std::size_t> abs_multi_index(multi_index.size());
926 std::transform(multi_index.begin(), multi_index.end(), m_shape.begin(),
927 abs_multi_index.begin(),
928 [](std::int32_t index, std::size_t shape) -> std::size_t {
929 if (index < 0) {
930 return static_cast<std::size_t>(shape + index);
931 }
932
933 return static_cast<std::size_t>(index);
934 });
935
936 return ravel(abs_multi_index);
937 }
938
942 size_t ravel(const std::vector<std::size_t> &abs_multi_index) const {
943 if (m_fortran_order) {
944 return ravel(abs_multi_index.rbegin(), m_shape.rbegin());
945 }
946
947 return ravel(abs_multi_index.begin(), m_shape.begin());
948 }
949
950private:
951 std::vector<size_t> m_shape;
952 std::vector<size_t> m_ravel_strides;
953 bool m_fortran_order;
954 data_type_t m_dtype;
955 std::vector<T> m_values;
956
958 static data_type_t get_dtype();
959
961 static size_t get_size(const std::vector<size_t> &shape) {
962 size_t size = 1;
963 for (auto &dim : shape) {
964 size *= dim;
965 }
966
967 return size;
968 }
969
971 static std::vector<size_t> get_ravel_strides(const std::vector<size_t> &shape,
972 bool fortran_order) {
973 std::vector<size_t> ravel_strides(shape.size());
974 size_t stride = 1;
975 auto ravel = ravel_strides.rbegin();
976 if (fortran_order) {
977 for (auto max_index = shape.begin(); max_index < shape.end();
978 ++max_index, ++ravel) {
979 *ravel = stride;
980 stride *= *max_index;
981 }
982 } else {
983 for (auto max_index = shape.rbegin(); max_index < shape.rend();
984 ++max_index, ++ravel) {
985 *ravel = stride;
986 stride *= *max_index;
987 }
988 }
989
990 return ravel_strides;
991 }
992};
993
995template <>
996inline std::string tensor<std::wstring>::dtype(endian_t endianness) const {
997 std::size_t max_length = 0;
998 for (const auto &element : m_values) {
999 if (element.size() > max_length) {
1000 max_length = element.size();
1001 }
1002 }
1003
1004 if (endianness == npy::endian_t::NATIVE) {
1005 endianness = native_endian();
1006 }
1007
1008 if (endianness == npy::endian_t::LITTLE) {
1009 return "<U" + std::to_string(max_length);
1010 }
1011
1012 return ">U" + std::to_string(max_length);
1013}
1014
1015} // namespace npy
1016
1017#endif
Class handling reading of an NPZ from a file on disk.
Definition npy.h:559
const std::vector< std::string > & keys() const
The keys of the tensors in the NPZ.
TENSOR< T > read(const std::string &filename)
Read a tensor from the archive.
Definition npy.h:613
bool contains(const std::string &filename)
Returns whether this NPZ contains the specified tensor.
npzfilereader(const std::filesystem::path &path)
Constructor.
void close()
Closes the NPZ file.
T read(const std::string &filename)
Read a tensor from the archive.
Definition npy.h:599
npzfilereader(const char *path)
Constructor.
header_info peek(const std::string &filename)
Returns the header for a specified tensor.
npzfilereader(const std::string &path)
Constructor.
bool is_open() const
Whether the NPZ file is open.
Class which handles writing of an NPZ archive to disk.
Definition npy.h:429
bool is_open() const
Returns whether the NPZ file is open.
npzfilewriter(const std::string &path, compression_method_t compression=compression_method_t::STORED, endian_t endianness=npy::endian_t::NATIVE)
Constructor.
~npzfilewriter()
Destructor. This will call npy::npzfilewriter::close, if it has not been called already.
npzfilewriter(const char *path, compression_method_t compression=compression_method_t::STORED, endian_t endianness=npy::endian_t::NATIVE)
Constructor.
void write(const std::string &filename, const T &tensor)
Write a tensor to the NPZ archive.
Definition npy.h:471
npzfilewriter(const std::filesystem::path &path, compression_method_t compression=compression_method_t::STORED, endian_t endianness=npy::endian_t::NATIVE)
Constructor.
void close()
Writes the directory and end-matter of the NPZ file, and closes the file. Further writes will fail.
Class handling reading of an NPZ from an in-memory string stream.
Definition npy.h:503
TENSOR< T > read(const std::string &filename)
Definition npy.h:540
const std::vector< std::string > & keys() const
The keys of the tensors in the NPZ.
T read(const std::string &filename)
Read a tensor from the archive.
Definition npy.h:534
npzstringreader(const std::string &bytes)
Constructor.
npzstringreader(std::string &&bytes)
Constructor.
header_info peek(const std::string &filename)
Returns the header for a specified tensor.
bool contains(const std::string &filename)
Returns whether this NPZ contains the specified tensor.
Class which handles writing of an NPZ to an in-memory string stream.
Definition npy.h:371
void close()
Writes the directory and end-matter of the NPZ file. Further writes will fail.
void write(const std::string &filename, const T &tensor)
Write a tensor to the NPZ archive.
Definition npy.h:397
~npzstringwriter()
Destructor. This will call npy::npzstringwriter::close, if it has not been called already.
std::string str() const
Returns the contents of the string stream as a string.
npzstringwriter(compression_method_t compression=compression_method_t::STORED, endian_t endianness=npy::endian_t::NATIVE)
Constructor.
The default tensor class.
Definition npy.h:650
T * data()
A pointer to the start of the underlying values buffer.
Definition npy.h:836
void copy_from(const T *source, size_t nitems)
Copy values from the source to this tensor.
Definition npy.h:807
const T & get(const std::vector< std::int32_t > &multi_index) const
Gets the value at the provided index.
Definition npy.h:786
void save(std::basic_ostream< char > &output, endian_t endianness) const
Save the tensor to the provided stream.
Definition npy.h:728
const value_type & const_reference
The const reference type of the tensor.
Definition npy.h:657
std::vector< T >::iterator end()
Iterator pointing at the end of the tensor in memory.
Definition npy.h:771
data_type_t dtype() const
The data type of the tensor.
Definition npy.h:799
const T & operator()(Indices... index) const
Variable parameter index function.
Definition npy.h:736
const value_type * const_pointer
The const pointer type of the tensor.
Definition npy.h:661
size_t ravel(const std::vector< std::size_t > &abs_multi_index) const
Ravels a multi-index into a single value indexing the buffer.
Definition npy.h:942
T & operator()(const std::vector< std::size_t > &multi_index)
Index function.
Definition npy.h:758
std::vector< T >::const_iterator begin() const
Iterator pointing at the beginning of the tensor in memory.
Definition npy.h:766
value_type * pointer
The pointer type of the tensor.
Definition npy.h:659
void copy_from(const std::vector< T > &source)
Copy values from the provided vector.
Definition npy.h:817
bool fortran_order() const
Whether the tensor data is stored in FORTRAN, or column-major, order.
Definition npy.h:866
static tensor< T > from_file(const std::string &path)
Load a tensor from the specified location on disk.
Definition npy.h:694
void set(const std::vector< std::int32_t > &multi_index, const T &value)
Sets the value at the provided index.
Definition npy.h:779
tensor< T > & operator=(const tensor< T > &other)
Copy assignment operator.
Definition npy.h:869
size_t ravel(const std::vector< std::int32_t > &multi_index) const
Ravels a multi-index into a single value indexing the buffer.
Definition npy.h:920
tensor(const std::vector< size_t > &shape, bool fortran_order)
Constructor.
Definition npy.h:674
T & operator()(Indices... index)
Variable parameter index function.
Definition npy.h:751
void move_from(std::vector< T > &&source)
Move values from the provided vector.
Definition npy.h:827
tensor(const std::vector< size_t > &shape)
Constructor.
Definition npy.h:667
std::string dtype(endian_t endianness) const
The data type of the tensor.
Definition npy.h:791
tensor< T > & operator=(tensor< T > &&other)
Move assignment operator.
Definition npy.h:879
const T & operator()(const std::vector< std::size_t > &multi_index) const
Index function.
Definition npy.h:743
tensor(tensor< T > &&other)
Move constructor.
Definition npy.h:687
const T * data() const
A pointer to the start of the underlying values buffer.
Definition npy.h:839
T value_type
The value type of the tensor.
Definition npy.h:653
const std::vector< size_t > & shape() const
The shape of the vector. Each element is the size of the corresponding dimension.
Definition npy.h:846
std::vector< T >::iterator begin()
Iterator pointing at the beginning of the tensor in memory.
Definition npy.h:763
size_t ndim() const
The number of dimensions of the tensor.
Definition npy.h:859
size_t ravel(INDEX_IT index, SHAPE_IT shape) const
Ravels a multi-index into a single value indexing the buffer.
Definition npy.h:903
void save(const std::string &path, endian_t endianness=npy::endian_t::NATIVE)
Save this tensor to the provided location on disk.
Definition npy.h:891
size_t shape(int index) const
Returns the dimensionality of the tensor at the specified index.
Definition npy.h:853
std::vector< T >::const_iterator end() const
Iterator pointing at the end of the tensor in memory.
Definition npy.h:774
value_type & reference
The reference type of the tensor.
Definition npy.h:655
static tensor< T > load(std::basic_istream< char > &input, const header_info &info)
Load a tensor from the provided stream.
Definition npy.h:708
const std::vector< T > & values() const
The underlying values buffer.
Definition npy.h:802
size_t size() const
The number of elements in the tensor.
Definition npy.h:842
tensor(const tensor< T > &other)
Copy constructor.
Definition npy.h:681
Definition npy.h:39
void write_npy_header(std::basic_ostream< CHAR > &output, const std::string &dtype, bool fortran_order, const std::vector< size_t > &shape)
Writes an NPY header to the provided stream.
Definition npy.h:147
endian_t native_endian()
This function will return the endianness of the current hardware.
Definition npy.h:52
void write_values(std::basic_ostream< CHAR > &output, const T *data_ptr, size_t num_elements, endian_t endianness)
Write values to the provided stream.
header_info peek(std::basic_istream< CHAR > &input)
Return the header information for an NPY file.
Definition npy.h:331
const std::pair< data_type_t, endian_t > & from_dtype(const std::string &dtype)
endian_t
Enumeration which represents a type of endianness.
Definition npy.h:41
@ LITTLE
Indicates the use of little-endian encoding.
@ BIG
Indicates the use of big-endian encoding.
compression_method_t
Enumeration indicating the compression method to use for data in the NPZ archive.
Definition npy.h:342
@ STORED
Store the data with no compression.
@ DEFLATED
Use the DEFLATE algorithm to compress the data.
void read_values(std::basic_istream< CHAR > &input, T *data_ptr, size_t num_elements, const header_info &info)
Read values from the provided stream.
void save(std::basic_ostream< CHAR > &output, const T &tensor, endian_t endianness=npy::endian_t::NATIVE)
Saves a tensor to the provided stream.
Definition npy.h:204
header_info read_npy_header(std::basic_istream< CHAR > &input)
Read an NPY header from the provided stream.
Definition npy.h:261
const std::string & to_dtype(data_type_t dtype, endian_t endian=endian_t::NATIVE)
Convert a data type and endianness to a NPY dtype string.
data_type_t
This enum represents the different types of tensor data that can be stored.
Definition npy.h:63
@ UNICODE_STRING
Unicode string (std::wstring)
@ FLOAT64
64-bit floating-point value (double)
@ UINT32
32-bit unsigned integer (uint)
@ COMPLEX128
128-bit complex number (std::complex<double>)
@ UINT16
16-bit unsigned integer (ushort)
@ INT64
64-bit integer (long)
@ COMPLEX64
64-bit complex number (std::complex<float>)
@ INT16
16-bit signed integer (short)
@ INT32
32-bit signed integer (int)
@ UINT64
64-bit unsigned integer (long)
@ FLOAT32
32-bit floating-point value (float)
@ UINT8
8 bit unsigned integer
@ INT8
8 bit signed integer
std::ostream & operator<<(std::ostream &os, const endian_t &obj)
T load(std::basic_istream< CHAR > &input)
Definition npy.h:297
const int STATIC_HEADER_LENGTH
Definition npy.h:37
Struct representing a file in the NPZ archive.
Definition npy.h:350
std::string filename
The name of the file.
Definition npy.h:352
std::uint32_t crc32
The CRC32 checksum of the uncompressed data.
Definition npy.h:354
bool check(const file_entry &other) const
std::uint64_t offset
The offset of the file in the archive.
Definition npy.h:362
std::uint16_t compression_method
The method used to compress the data.
Definition npy.h:360
std::uint64_t compressed_size
The size of the compressed data.
Definition npy.h:356
std::uint64_t uncompressed_size
The size of the uncompressed data.
Definition npy.h:358
Class representing the header info for an NPY file.
Definition npy.h:109
std::size_t max_element_length
Definition npy.h:134
header_info(const std::string &dictionary)
std::vector< size_t > shape
A vector of values indicating the shape of each dimension of the tensor.
Definition npy.h:130
data_type_t dtype
The data type of the NPY file.
Definition npy.h:120
header_info(data_type_t dtype, npy::endian_t endianness, bool fortran_order, const std::vector< size_t > &shape)
Constructor.
bool fortran_order
Definition npy.h:127
npy::endian_t endianness
The endianness of the data in the NPY file.
Definition npy.h:123