File indexing completed on 2026-04-09 07:49:24
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <cassert>
0012 #include <string>
0013 #include <sstream>
0014 #include <fstream>
0015 #include <vector>
0016 #include <cstdint>
0017
0018 struct np
0019 {
0020 static constexpr char* MAGIC = (char*)"\x93NUMPY" ;
0021 static constexpr bool FORTRAN_ORDER = false ;
0022 static char constexpr ENDIAN_LITTLE = '<' ;
0023 static char constexpr ENDIAN_BIG = '>' ;
0024
0025 static std::string _make_header(const std::vector<int>& shape, const char* descr="<f8" );
0026 static std::string _make_header(const std::string& dict);
0027 static std::string _make_preamble( int major=1, int minor=0 );
0028 static std::string _little_endian_short_string( uint16_t dlen ) ;
0029 static std::string _make_tuple(const std::vector<int>& shape, bool json );
0030 static std::string _make_dict(const std::vector<int>& shape, const char* descr );
0031
0032 template<typename T>
0033 static void Write(const char* path, const std::vector<int>& shape, const T* data, const char* descr="<f8" );
0034
0035 template<typename T>
0036 static void Write(const char* dir, const char* name, const std::vector<int>& shape, const T* data, const char* descr="<f8" );
0037
0038 static std::string FormPath( const char* dir, const char* name );
0039 static void WriteString( const char* dir, const char* name, const char* txt );
0040
0041
0042 };
0043
0044
0045 inline std::string np::_make_header(const std::vector<int>& shape, const char* descr )
0046 {
0047 std::string dict = _make_dict( shape, descr );
0048 std::string header = _make_header( dict );
0049 return header ;
0050 }
0051
0052
0053 inline std::string np::_make_header(const std::string& dict)
0054 {
0055 uint16_t dlen = dict.size() ;
0056 uint16_t padding = 16 - ((10 + dlen ) % 16 ) - 1 ;
0057 padding += 3*16 ;
0058 uint16_t hlen = dlen + padding + 1 ;
0059
0060 assert( (hlen + 10) % 16 == 0 );
0061 std::stringstream ss ;
0062 ss << _make_preamble() ;
0063 ss << _little_endian_short_string( hlen ) ;
0064 ss << dict ;
0065
0066 for(int i=0 ; i < padding ; i++ ) ss << " " ;
0067 ss << "\n" ;
0068
0069 return ss.str();
0070 }
0071
0072
0073 inline std::string np::_make_preamble( int major, int minor )
0074 {
0075 std::string preamble(MAGIC) ;
0076 preamble.push_back((char)major);
0077 preamble.push_back((char)minor);
0078 return preamble ;
0079 }
0080
0081
0082 inline std::string np::_little_endian_short_string( uint16_t dlen )
0083 {
0084 union u16c2_t {
0085 uint16_t u16 ;
0086 char c[2] ;
0087 };
0088
0089 u16c2_t len ;
0090 len.u16 = dlen ;
0091
0092 unsigned one = 1u ;
0093 char e = *(char *)&one == 1 ? ENDIAN_LITTLE : ENDIAN_BIG ;
0094 std::string hlen(2, ' ') ;
0095 hlen[0] = e == ENDIAN_LITTLE ? len.c[0] : len.c[1] ;
0096 hlen[1] = e == ENDIAN_LITTLE ? len.c[1] : len.c[0] ;
0097 return hlen ;
0098 }
0099
0100
0101 inline std::string np::_make_tuple( const std::vector<int>& shape, bool json )
0102 {
0103 int ndim = shape.size() ;
0104 std::stringstream ss ;
0105 ss << ( json ? "[" : "(" ) ;
0106
0107 if( ndim == 1)
0108 {
0109 ss << shape[0] << "," ;
0110 }
0111 else
0112 {
0113 for(int i=0 ; i < ndim ; i++ ) ss << shape[i] << ( i == ndim - 1 ? "" : ", " ) ;
0114 }
0115 ss << ( json ? "] " : "), " ) ;
0116 return ss.str();
0117 }
0118
0119
0120 inline std::string np::_make_dict(const std::vector<int>& shape, const char* descr )
0121 {
0122 std::stringstream ss ;
0123 ss << "{" ;
0124 ss << "'descr': '" << descr << "', " ;
0125 ss << "'fortran_order': " << ( FORTRAN_ORDER ? "True" : "False" ) << ", " ;
0126 ss << "'shape': " ;
0127 bool json = false ;
0128 ss << _make_tuple( shape, json ) ;
0129 ss << "}" ;
0130 return ss.str();
0131 }
0132
0133
0134
0135
0136 template<typename T>
0137 inline void np::Write(const char* path, const std::vector<int>& shape, const T* data, const char* descr )
0138 {
0139 size_t nv = 1 ;
0140 for(int i=0 ; i < int(shape.size()) ; i++) nv *= shape[i] ;
0141 size_t arr_bytes = sizeof(T)*nv ;
0142
0143 std::string hdr = _make_header(shape, descr);
0144 std::ofstream fpa(path, std::ios::out|std::ios::binary);
0145 fpa << hdr ;
0146 fpa.write( (char*)data, arr_bytes );
0147 }
0148
0149 template<typename T>
0150 inline void np::Write(const char* dir, const char* name, const std::vector<int>& shape, const T* data, const char* descr )
0151 {
0152 std::string path = FormPath(dir, name);
0153 Write<T>( path.c_str(), shape, data, descr );
0154 }
0155
0156 inline std::string np::FormPath( const char* dir, const char* name )
0157 {
0158 std::stringstream ss ;
0159 if(dir) ss << dir << "/" ;
0160 if(name) ss << name ;
0161 std::string path = ss.str();
0162 return path ;
0163 }
0164
0165 inline void np::WriteString( const char* dir, const char* name, const char* txt )
0166 {
0167 std::string path = FormPath(dir, name);
0168 if(txt == nullptr) return ;
0169 std::ofstream fp(path.c_str(), std::ios::out);
0170 fp << txt ;
0171 fp.close();
0172 }
0173
0174