FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
pack.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/util/string.hpp>
10
11// includes, system
12#include <cstdint>
13#include <ostream>
14#include <istream>
15
24namespace FEAT::Pack
25{
27 using i8 = std::int8_t;
29 using i16 = std::int16_t;
31 using i32 = std::int32_t;
33 using i64 = std::int64_t;
34
36 using u8 = std::uint8_t;
38 using u16 = std::uint16_t;
40 using u32 = std::uint32_t;
42 using u64 = std::uint64_t;
43
44#if defined(FEAT_HAVE_HALFMATH) || defined(DOXYGEN)
45#define FEAT_HAVE_PACK_TYPE_F16 1
47 using f16 = Half;
48 // make sure this really has only 16 bits; this may be violated by a stupid
49 // compiler
50 static_assert(sizeof(f16) == 2, "16-bit float is assumed to have exactly 16 bits");
51#endif
52
54 using f32 = float;
56 using f64 = double;
57
58#if defined(FEAT_HAVE_QUADMATH) || defined(DOYGEN)
59#define FEAT_HAVE_PACK_TYPE_F128 1
61 using f128 = __float128;
62 // make sure this really has only 16 bytes
63 static_assert(sizeof(f128) == 16, "128-bit float is assumed to have exactly 128 bits");
64#endif
65
69 enum class Type : u16
70 {
71 None = 0x0000, //< none (for comparison)
72 Mask_T = 0x0FFF, //< raw type mask
73 Mask_Z = 0x8000, //< zlib compression mask
74 Mask_P = 0x2000, //< zfp compression mask
75 // Mask_E = 0x4000, //< swap endianness mask
76
77 Type_I = 0x0010, //< signed integer type
78 Type_U = 0x0020, //< unsigend integer type
79 Type_F = 0x0030, //< floating point type
80
81 // raw signed integer types
82 I8 = 0x0011, //< 8-bit unsigned integer
83 I16 = 0x0012, //< 16-bit unsigned integer
84 I32 = 0x0013, //< 32-bit unsigned integer
85 I64 = 0x0014, //< 64-bit unsigned integer
86
87 // raw unsigned integer types
88 U8 = 0x0021, //< 8-bit unsigned integer
89 U16 = 0x0022, //< 16-bit unsigned integer
90 U32 = 0x0023, //< 32-bit unsigned integer
91 U64 = 0x0024, //< 64-bit unsigned integer
92
93 // raw floating point types
94 // F8 = 0x0031, //< 8-bit floating point (quarter precision)
95 F16 = 0x0032, //< 16-bit floating point (half precision)
96 F32 = 0x0033, //< 32-bit floating point (single precision)
97 F64 = 0x0034, //< 64-bit floating point (double precision)
98 F128 = 0x0035, //< 128-bit floating point (quadruple precision)
99
100 // zlib compressed signed integer types
101 ZI8 = 0x8011, //< 8-bit unsigned integer
102 ZI16 = 0x8012, //< 16-bit unsigned integer
103 ZI32 = 0x8013, //< 32-bit unsigned integer
104 ZI64 = 0x8014, //< 64-bit unsigned integer
105
106 // zlib compressed unsigned integer types
107 ZU8 = 0x8021, //< 8-bit unsigned integer
108 ZU16 = 0x8022, //< 16-bit unsigned integer
109 ZU32 = 0x8023, //< 32-bit unsigned integer
110 ZU64 = 0x8024, //< 64-bit unsigned integer
111
112 // zlib compressed floating point types
113 // ZF8 = 0x8031, //< 8-bit floating point (quarter precision)
114 ZF16 = 0x8032, //< 16-bit floating point (half precision)
115 ZF32 = 0x8033, //< 32-bit floating point (single precision)
116 ZF64 = 0x8034, //< 64-bit floating point (double precision)
117 ZF128 = 0x8035, //< 128-bit floating point (quadruple precision)
118
119 // zfp compressed floating point types
120 // PF8 = 0x2031, //< 8-bit floating point (quarter precision)
121 // PF16 = 0x2032, //< 16-bit floating point (half precision)
122 PF32 = 0x2033, //< 32-bit floating point (single precision)
123 PF64 = 0x2034 //< 64-bit floating point (double precision)
124 // PF128 = 0x2035 //< 128-bit floating point (quadruple precision)
125
126 }; // enum class Type
127
130 {
131 return (Pack::Type)(((Pack::u16)a) & ((Pack::u16)b));
132 }
133
136 {
137 return (Pack::Type)(((Pack::u16)a) | ((Pack::u16)b));
138 }
139
141 inline std::ostream& operator<<(std::ostream& os, Pack::Type t)
142 {
143 switch(t)
144 {
145 // case Pack::Type::F8: return os << "F8";
146 case Pack::Type::F16: return os << "F16";
147 case Pack::Type::F32: return os << "F32";
148 case Pack::Type::F64: return os << "F64";
149 case Pack::Type::F128: return os << "F128";
150 case Pack::Type::I8: return os << "I8";
151 case Pack::Type::I16: return os << "I16";
152 case Pack::Type::I32: return os << "I32";
153 case Pack::Type::I64: return os << "I64";
154 case Pack::Type::U8: return os << "U8";
155 case Pack::Type::U16: return os << "U16";
156 case Pack::Type::U32: return os << "U32";
157 case Pack::Type::U64: return os << "U64";
158 // case Pack::Type::ZF8: return os << "ZF8";
159 case Pack::Type::ZF16: return os << "ZF16";
160 case Pack::Type::ZF32: return os << "ZF32";
161 case Pack::Type::ZF64: return os << "ZF64";
162 case Pack::Type::ZF128: return os << "ZF128";
163 case Pack::Type::ZI8: return os << "ZI8";
164 case Pack::Type::ZI16: return os << "ZI16";
165 case Pack::Type::ZI32: return os << "ZI32";
166 case Pack::Type::ZI64: return os << "ZI64";
167 case Pack::Type::ZU8: return os << "ZU8";
168 case Pack::Type::ZU16: return os << "ZU16";
169 case Pack::Type::ZU32: return os << "ZU32";
170 case Pack::Type::ZU64: return os << "ZU64";
171 case Pack::Type::PF32: return os << "PF32";
172 case Pack::Type::PF64: return os << "PF64";
173 default: return os << "???";
174 }
175 }
176
178 inline std::istream& operator>>(std::istream& is, Pack::Type& t)
179 {
180 String s;
181 if((is >> s).fail())
182 {
183 return is;
184 }
185
186 // if(s.compare_no_case("F8") == 0) t = Pack::Type::F8; else
187 if(s.compare_no_case("F16") == 0)
188 t = Pack::Type::F16;
189 else if(s.compare_no_case("F32") == 0)
190 t = Pack::Type::F32;
191 else if(s.compare_no_case("F64") == 0)
192 t = Pack::Type::F64;
193 else if(s.compare_no_case("F128") == 0)
194 t = Pack::Type::F128;
195 else if(s.compare_no_case("I8") == 0)
196 t = Pack::Type::I8;
197 else if(s.compare_no_case("I16") == 0)
198 t = Pack::Type::I16;
199 else if(s.compare_no_case("I32") == 0)
200 t = Pack::Type::I32;
201 else if(s.compare_no_case("I64") == 0)
202 t = Pack::Type::I64;
203 else if(s.compare_no_case("U8") == 0)
204 t = Pack::Type::U8;
205 else if(s.compare_no_case("U16") == 0)
206 t = Pack::Type::U16;
207 else if(s.compare_no_case("U32") == 0)
208 t = Pack::Type::U32;
209 else if(s.compare_no_case("U64") == 0)
210 t = Pack::Type::U64;
211 else
212 // if(s.compare_no_case("ZF8") == 0) t = Pack::Type::ZF8; else
213 if(s.compare_no_case("ZF16") == 0)
214 t = Pack::Type::ZF16;
215 else if(s.compare_no_case("ZF32") == 0)
216 t = Pack::Type::ZF32;
217 else if(s.compare_no_case("ZF64") == 0)
218 t = Pack::Type::ZF64;
219 else if(s.compare_no_case("ZF128") == 0)
220 t = Pack::Type::ZF128;
221 else if(s.compare_no_case("ZI8") == 0)
222 t = Pack::Type::ZI8;
223 else if(s.compare_no_case("ZI16") == 0)
224 t = Pack::Type::ZI16;
225 else if(s.compare_no_case("ZI32") == 0)
226 t = Pack::Type::ZI32;
227 else if(s.compare_no_case("ZI64") == 0)
228 t = Pack::Type::ZI64;
229 else if(s.compare_no_case("ZU8") == 0)
230 t = Pack::Type::ZU8;
231 else if(s.compare_no_case("ZU16") == 0)
232 t = Pack::Type::ZU16;
233 else if(s.compare_no_case("ZU32") == 0)
234 t = Pack::Type::ZU32;
235 else if(s.compare_no_case("ZU64") == 0)
236 t = Pack::Type::ZU64;
237 else if(s.compare_no_case("PF32") == 0)
238 t = Pack::Type::PF32;
239 else if(s.compare_no_case("PF64") == 0)
240 t = Pack::Type::PF64;
241 else
242 is.setstate(std::ios_base::failbit);
243
244 return is;
245 }
246
256 inline std::size_t element_size(const Pack::Type type)
257 {
258 // Lower 4 bits contain the size of the data type.
259 // Upper bits contain the type of compression.
260 constexpr auto size_mask = 0xFULL;
261 return std::size_t(1) << ((static_cast<u16>(type) & size_mask) - 1);
262 }
263
276 template<typename T_>
278
291 std::size_t estimate_size(std::size_t count, Pack::Type type, double tolerance = 1e-16);
292
323 template<typename T_>
324 std::size_t encode(
325 void* buf,
326 const T_* src,
327 std::size_t buf_size,
328 std::size_t count,
329 Pack::Type pack_type,
330 bool swap_bytes,
331 double tolerance = 1e-16);
332
359 template<typename T_>
360 std::size_t decode(
361 T_* dst,
362 void* buf,
363 std::size_t count,
364 std::size_t buf_size,
365 Pack::Type pack_type,
366 bool swap_bytes);
367
369 // Base64 handling
371
379 bool is_valid_base64_string(const String& s);
380
391 String base64_encode(const Pack::u8* begin, const Pack::u8* end);
392
402 std::vector<Pack::u8> base64_decode(const String& s);
403} // namespace FEAT::Pack
String class implementation.
Definition: string.hpp:47
int compare_no_case(const String &other) const
Compares two strings without regard to case.
Definition: string.hpp:680
Data Array Pack namespace.
Definition: pack.cpp:30
Pack::Type operator|(Pack::Type a, Pack::Type b)
bit-wise OR operator for Pack::Type
Definition: pack.hpp:135
std::int32_t i32
32-bit signed integer type
Definition: pack.hpp:31
std::size_t encode(void *buf, const T_ *src, const std::size_t buf_size, const std::size_t count, const Pack::Type pack_type, bool swap_bytes, double tolerance)
Encodes an array into a packed buffer.
Definition: pack.cpp:580
std::uint64_t u64
64-bit unsigned integer type
Definition: pack.hpp:42
std::size_t element_size(const Pack::Type type)
Returns the size of a Pack::Type element in bytes.
Definition: pack.hpp:256
Pack::Type operator&(Pack::Type a, Pack::Type b)
bit-wise AND operator for Pack::Type
Definition: pack.hpp:129
std::size_t estimate_size(const std::size_t count, const Pack::Type type, const double tolerance)
Computes the estimated (upper bound) pack buffer size for an array.
Definition: pack.cpp:557
String base64_encode(const Pack::u8 *begin, const Pack::u8 *end)
Encodes bytes into a Base64 string.
Definition: pack.cpp:1115
std::istream & operator>>(std::istream &is, Pack::Type &t)
stream input operator for Pack::Type
Definition: pack.hpp:178
std::ostream & operator<<(std::ostream &os, Pack::Type t)
stream output operator for Pack::Type
Definition: pack.hpp:141
Half f16
16-bit floating point type
Definition: pack.hpp:47
float f32
32-bit floating point type
Definition: pack.hpp:54
Type
Type enumeration.
Definition: pack.hpp:70
std::int16_t i16
16-bit signed integer type
Definition: pack.hpp:29
std::uint32_t u32
32-bit unsigned integer type
Definition: pack.hpp:40
std::int64_t i64
64-bit signed integer type
Definition: pack.hpp:33
std::uint16_t u16
16-bit unsigned integer type
Definition: pack.hpp:38
std::int8_t i8
8-bit signed integer type
Definition: pack.hpp:27
double f64
64-bit floating point type
Definition: pack.hpp:56
std::size_t decode(T_ *dst, void *buf, const std::size_t count, const std::size_t buf_size, const Pack::Type pack_type, bool swap_bytes)
Decodes an array from a packed buffer.
Definition: pack.cpp:694
std::uint8_t u8
8-bit unsigned integer type
Definition: pack.hpp:36
Pack::Type deduct_type()
Deduct the (raw) Pack::Type from a given data type T_.
Definition: pack.cpp:376
bool is_valid_base64_string(const String &s)
Definition: pack.cpp:1098
std::vector< Pack::u8 > base64_decode(const String &s)
Decodes a Base64 string into bytes.
Definition: pack.cpp:1204
__half Half
Half data type.
Definition: half.hpp:25