FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
pack.cpp
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#include <kernel/util/pack.hpp>
7
8// includes, FEAT
11#include <kernel/util/math.hpp>
12#include <kernel/util/type_traits.hpp>
13
14// includes, system
15#include <cstring>
16
17// includes, thirdparty
18#ifdef FEAT_HAVE_ZLIB
19#include <zlib.h>
20#endif // FEAT_HAVE_ZLIB
21#ifdef FEAT_HAVE_ZFP
22FEAT_DISABLE_WARNINGS
23#include "zfp.h"
24FEAT_RESTORE_WARNINGS
25#endif // FEAT_HAVE_ZFP
26
27namespace FEAT::Pack
28{
30 template<int bytes_>
31 struct SwapHelper;
32
33 template<>
34 struct SwapHelper<1>
35 {
36 static void swap(void* /*unused*/)
37 {
38 // nothing to do here
39 }
40 };
41
42 template<>
43 struct SwapHelper<2>
44 {
45 static void swap(void* x)
46 {
47 u16& v = *reinterpret_cast<u16*>(x);
48 v = u16(((v & 0x00FFULL) << 8) | ((v & 0xFF00ULL) >> 8));
49 }
50 };
51
52 template<>
53 struct SwapHelper<4>
54 {
55 static void swap(void* x)
56 {
57 u32& v = *reinterpret_cast<u32*>(x);
58 v = u32(((v & 0x000000FFULL) << 24) | ((v & 0x0000FF00ULL) << 8) |
59 ((v & 0x00FF0000ULL) >> 8) | ((v & 0xFF000000ULL) >> 24));
60 }
61 };
62
63 template<>
64 struct SwapHelper<8>
65 {
66 static void swap(void* x)
67 {
68 u64& v = *reinterpret_cast<u64*>(x);
69 v = ((v & 0x00000000000000FFULL) << 56) | ((v & 0x000000000000FF00ULL) << 40) |
70 ((v & 0x0000000000FF0000ULL) << 24) | ((v & 0x00000000FF000000ULL) << 8) |
71 ((v & 0x000000FF00000000ULL) >> 8) | ((v & 0x0000FF0000000000ULL) >> 24) |
72 ((v & 0x00FF000000000000ULL) >> 40) | ((v & 0xFF00000000000000ULL) >> 56);
73 }
74 };
75
76 template<>
77 struct SwapHelper<16>
78 {
79 static void swap(void* x)
80 {
81 // swap two 64-bit ints
82 u64* vv = reinterpret_cast<u64*>(x);
83 u64 t = vv[0];
84 vv[0] = vv[1];
85 vv[1] = t;
86 // the the bytes within
87 SwapHelper<8>::swap(&vv[0]);
88 SwapHelper<8>::swap(&vv[1]);
89 }
90 };
91
95 template<typename X_>
96 inline X_ xswap(X_ x)
97 {
98 SwapHelper<int(sizeof(X_))>::swap(&x);
99 return x;
100 }
101
132 template<typename X_, typename T_>
133 static std::size_t xencode(void* buf, const T_* src, const std::size_t count, bool swap_bytes)
134 {
135 X_* x = reinterpret_cast<X_*>(buf);
136 if(swap_bytes)
137 {
138 for(std::size_t i(0); i < count; ++i)
139 {
140 x[i] = xswap(static_cast<X_>(src[i]));
141 }
142 }
143 else
144 {
145 for(std::size_t i(0); i < count; ++i)
146 {
147 x[i] = static_cast<X_>(src[i]);
148 }
149 }
150 return count * sizeof(X_);
151 }
152
183 template<typename X_, typename T_>
184 static std::size_t xdecode(T_* dest, const void* buf, const std::size_t count, bool swap_bytes)
185 {
186 const X_* x = reinterpret_cast<const X_*>(buf);
187 if(swap_bytes)
188 {
189 for(std::size_t i(0); i < count; ++i)
190 {
191 dest[i] = static_cast<T_>(xswap(x[i]));
192 }
193 }
194 else
195 {
196 for(std::size_t i(0); i < count; ++i)
197 {
198 dest[i] = static_cast<T_>(x[i]);
199 }
200 }
201 return count * sizeof(X_);
202 }
203
204 template<typename Tclass_, bool signed_>
206 {
207 template<typename T_>
208 static Pack::Type deduct()
209 {
210 return Pack::Type::None;
211 }
212 };
213
214 // specialization for floating point types
215 template<>
217 {
218 template<typename T_>
219 static Pack::Type deduct()
220 {
221 switch(sizeof(T_))
222 {
223 // case 1: return Pack::Type::F8;
224 case 2: return Pack::Type::F16;
225 case 4: return Pack::Type::F32;
226 case 8: return Pack::Type::F64;
227 case 16: return Pack::Type::F128;
228 default: return Pack::Type::None;
229 }
230 }
231
232 template<typename T_>
233 static std::size_t
234 encode(void* buf, const T_* t, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
235 {
236 switch(pack_type)
237 {
238#ifdef FEAT_HAVE_PACK_TYPE_F16
239 case Pack::Type::F16: return xencode<Pack::f16>(buf, t, count, swap_bytes);
240#endif
241 case Pack::Type::F32: return xencode<Pack::f32>(buf, t, count, swap_bytes);
242 case Pack::Type::F64: return xencode<Pack::f64>(buf, t, count, swap_bytes);
243#ifdef FEAT_HAVE_PACK_TYPE_F128
244 case Pack::Type::F128: return xencode<Pack::f128>(buf, t, count, swap_bytes);
245#endif
246 default: XABORTM("invalid data type conversion");
247 }
248 }
249
250 template<typename T_>
251 static std::size_t
252 decode(T_* t, const void* buf, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
253 {
254 switch(pack_type)
255 {
256#ifdef FEAT_HAVE_PACK_TYPE_F16
257 case Pack::Type::F16: return xdecode<Pack::f16>(t, buf, count, swap_bytes);
258#endif
259 case Pack::Type::F32: return xdecode<Pack::f32>(t, buf, count, swap_bytes);
260 case Pack::Type::F64: return xdecode<Pack::f64>(t, buf, count, swap_bytes);
261#ifdef FEAT_HAVE_PACK_TYPE_F128
262 case Pack::Type::F128: return xdecode<Pack::f128>(t, buf, count, swap_bytes);
263#endif
264 default: XABORTM("invalid data type conversion");
265 }
266 }
267 };
268
269 // specialization for signed integer types
270 template<>
272 {
273 template<typename T_>
274 static Pack::Type deduct()
275 {
276 switch(sizeof(T_))
277 {
278 case 1: return Pack::Type::I8;
279 case 2: return Pack::Type::I16;
280 case 4: return Pack::Type::I32;
281 case 8: return Pack::Type::I64;
282 default: return Pack::Type::None;
283 }
284 }
285
286 template<typename T_>
287 static std::size_t
288 encode(void* buf, const T_* t, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
289 {
290 switch(pack_type)
291 {
292 case Pack::Type::I8: return xencode<Pack::i8>(buf, t, count, swap_bytes);
293 case Pack::Type::I16: return xencode<Pack::i16>(buf, t, count, swap_bytes);
294 case Pack::Type::I32: return xencode<Pack::i32>(buf, t, count, swap_bytes);
295 case Pack::Type::I64: return xencode<Pack::i64>(buf, t, count, swap_bytes);
296 default: XABORTM("invalid data type conversion");
297 }
298 }
299
300 template<typename T_>
301 static std::size_t
302 decode(T_* t, const void* buf, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
303 {
304 switch(pack_type)
305 {
306 case Pack::Type::I8: return xdecode<Pack::i8>(t, buf, count, swap_bytes);
307 case Pack::Type::I16: return xdecode<Pack::i16>(t, buf, count, swap_bytes);
308 case Pack::Type::I32: return xdecode<Pack::i32>(t, buf, count, swap_bytes);
309 case Pack::Type::I64: return xdecode<Pack::i64>(t, buf, count, swap_bytes);
310 default: XABORTM("invalid data type conversion");
311 }
312 }
313 };
314
315 // specialization for unsigned integer types
316 template<>
318 {
319 template<typename T_>
320 static Pack::Type deduct()
321 {
322 switch(sizeof(T_))
323 {
324 case 1: return Pack::Type::U8;
325 case 2: return Pack::Type::U16;
326 case 4: return Pack::Type::U32;
327 case 8: return Pack::Type::U64;
328 default: return Pack::Type::None;
329 }
330 }
331
332 template<typename T_>
333 static std::size_t
334 encode(void* buf, const T_* t, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
335 {
336 switch(pack_type)
337 {
338 case Pack::Type::U8: return xencode<Pack::u8>(buf, t, count, swap_bytes);
339 case Pack::Type::U16: return xencode<Pack::u16>(buf, t, count, swap_bytes);
340 case Pack::Type::U32: return xencode<Pack::u32>(buf, t, count, swap_bytes);
341 case Pack::Type::U64: return xencode<Pack::u64>(buf, t, count, swap_bytes);
342 default: XABORTM("invalid data type conversion");
343 }
344 }
345
346 template<typename T_>
347 static std::size_t
348 decode(T_* t, const void* buf, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
349 {
350 switch(pack_type)
351 {
352 case Pack::Type::U8: return xdecode<Pack::u8>(t, buf, count, swap_bytes);
353 case Pack::Type::U16: return xdecode<Pack::u16>(t, buf, count, swap_bytes);
354 case Pack::Type::U32: return xdecode<Pack::u32>(t, buf, count, swap_bytes);
355 case Pack::Type::U64: return xdecode<Pack::u64>(t, buf, count, swap_bytes);
356 default: XABORTM("invalid data type conversion");
357 }
358 }
359 };
360
361 template<typename T_>
363 {
364 using TypeTraits = typename FEAT::Type::Traits<T_>;
366 }
367
392 template<typename T_>
393 static std::size_t
394 encode_raw(void* buf, const T_* src, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
395 {
396 if(count <= std::size_t(0))
397 {
398 return std::size_t(0);
399 }
400
401 XASSERT(buf != nullptr);
402 XASSERT(src != nullptr);
403
404 XASSERTM((pack_type & Pack::Type::Mask_T) != Pack::Type::None, "invalid pack type");
405 XASSERTM((pack_type & Pack::Type::Mask_Z) != Pack::Type::Mask_Z, "cannot encode compressed type");
406
407 using TypeTraits = typename FEAT::Type::Traits<T_>;
408
410 buf,
411 src,
412 count,
413 pack_type,
414 swap_bytes);
415 }
416
441 template<typename T_>
442 static std::size_t
443 decode_raw(T_* dst, const void* buf, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
444 {
445 if(count <= std::size_t(0))
446 {
447 return std::size_t(0);
448 }
449
450 XASSERT(dst != nullptr);
451 XASSERT(buf != nullptr);
452
453 XASSERTM((pack_type & Pack::Type::Mask_T) != Pack::Type::None, "invalid pack type");
454 XASSERTM((pack_type & Pack::Type::Mask_Z) != Pack::Type::Mask_Z, "cannot decode compressed type");
455
456 using TypeTraits = typename FEAT::Type::Traits<T_>;
457
459 dst,
460 buf,
461 count,
462 pack_type,
463 swap_bytes);
464 }
465
486 static std::size_t lossy_estimate_size(const std::size_t count, const Pack::Type type, const double tolerance)
487 {
488 if(count <= std::size_t(0))
489 {
490 return std::size_t(0);
491 }
492#ifdef FEAT_HAVE_ZFP
493 // get type T_, int would be handleable... but why lossy save an int array?:
494 zfp_type t = zfp_type::zfp_type_none;
495 switch(type)
496 {
497 case Pack::Type::PF32: t = zfp_type::zfp_type_float; break;
498 case Pack::Type::PF64: t = zfp_type::zfp_type_double; break;
499 default: XABORTM("cannot encode compressed type; data typ not available");
500 }
501 XASSERT(t != zfp_type::zfp_type_none);
502
503 // declare needed zfp internal variables:
504 zfp_field* field;
505 zfp_stream* zfp;
506 std::size_t bytes;
507 std::size_t x_size, y_size;
508 void* temp_arr = nullptr;
509
510 // calculate needed representation size, e.g. 4 times (size/4 +1):
511 x_size = 4u;
512 y_size = count / x_size + 1;
513
514 // check if we lose significant bits through type conversion...
515 if((sizeof(std::size_t) > sizeof(uint)) && (count > std::numeric_limits<uint>::max()))
516 XABORTM("cannot encode compressed type; array size to big for internal data");
517
518 // initialize zfp field as 2D variant, that src is not right type does not
519 // matter at this point...( memory has to be freed in the end):
520 field = zfp_field_2d(temp_arr, t, (uint)x_size, (uint)y_size);
521 // open stream(has to be freed)
522 zfp = zfp_stream_open(NULL);
523 // set error tolerance of stream:
524 zfp_stream_set_accuracy(zfp, tolerance);
525 // get a conservativ estimate for the buffer size(header size included)
526 bytes = zfp_stream_maximum_size(zfp, field);
527
528 // free allocated data:
529 zfp_field_free(field);
530 zfp_stream_close(zfp);
531
532 // return compression size
533 return bytes;
534
535#else // no FEAT_HAVE_ZFP
536 (void)type;
537 (void)tolerance;
538 XABORTM("cannot encode compressed type; zfp not available");
539 return std::size_t(0);
540#endif // FEAT_HAVE_ZFP*/
541 }
542
543 std::size_t estimate_size(const std::size_t count, const Pack::Type type, const double tolerance)
544 {
545 if((type & Pack::Type::Mask_P) != Pack::Type::None)
546 {
547 return lossy_estimate_size(count, type, tolerance);
548 }
549 // compute raw element size
550 std::size_t raw_size = count * Pack::element_size(type & Pack::Type::Mask_T);
551
552#ifdef FEAT_HAVE_ZLIB
553 if((type & Pack::Type::Mask_Z) != Pack::Type::None)
554 {
555 return std::size_t(::compressBound(uLong(raw_size)));
556 }
557#else // no FEAT_HAVE_ZLIB
558 XASSERTM((type & Pack::Type::Mask_Z) == Pack::Type::None, "cannot estimate compressed size; zlib not available");
559#endif // FEAT_HAVE_ZLIB
560
561 // return raw size
562 return raw_size;
563 }
564
565 template<typename T_>
566 std::size_t encode(
567 void* buf,
568 const T_* src,
569 const std::size_t buf_size,
570 const std::size_t count,
571 const Pack::Type pack_type,
572 bool swap_bytes,
573 double tolerance)
574 {
575 if(count <= std::size_t(0))
576 {
577 return std::size_t(0);
578 }
579
580 XASSERT(buf != nullptr);
581 XASSERT(src != nullptr);
582
583 // get raw type
584 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
585
586 // no compression required?
587 if((pack_type & (Pack::Type::Mask_Z | Pack::Type::Mask_P)) == Pack::Type::None)
588 {
589 return encode_raw(buf, src, count, raw_type, swap_bytes);
590 }
591
592 // zlib compression?
593 if((pack_type & Pack::Type::Mask_Z) == Pack::Type::Mask_Z)
594 {
595 return lossless_encode(buf, src, buf_size, count, pack_type, swap_bytes);
596 }
597
598 // zfp compression?
599 if((pack_type & Pack::Type::Mask_P) == Pack::Type::Mask_P)
600 {
601 return lossy_encode(buf, src, buf_size, count, pack_type, swap_bytes, tolerance);
602 }
603
604 return std::size_t(0);
605 }
606
632 template<typename T_>
633 static std::size_t lossless_encode(
634 void* buf,
635 const T_* src,
636 const std::size_t buf_size,
637 const std::size_t count,
638 const Pack::Type pack_type,
639 bool swap_bytes)
640 {
641 // get raw type
642 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
643
644#ifdef FEAT_HAVE_ZLIB
645 // ensure that the temporary buffer is large enough
646 std::size_t raw_size = element_size(raw_type) * count;
647 std::vector<char> tmp(raw_size);
648
649 // encode into temporary buffer
650 encode_raw(tmp.data(), src, count, raw_type, swap_bytes);
651
652 // cast buffer lengths to zlib types
653 uLongf dl = static_cast<uLongf>(buf_size);
654 uLong sl = static_cast<uLong>(raw_size);
655
656 // cast buffer pointers to zlib types
657 Bytef* dbuf = reinterpret_cast<Bytef*>(buf);
658 const Bytef* sbuf = reinterpret_cast<const Bytef*>(tmp.data());
659
660 // compress via zlib
661 if(::compress(dbuf, &dl, sbuf, sl) != Z_OK)
662 XABORTM("zlib compression error");
663
664 // return final destination buffer usage as reported by zlib
665 return static_cast<std::size_t>(dl);
666#else // no FEAT_HAVE_ZLIB
667 (void)buf_size;
668 (void)buf;
669 (void)src;
670 (void)raw_type;
671 (void)swap_bytes;
672 (void)pack_type;
673 (void)count;
674 XABORTM("cannot encode compressed type; zlib not available");
675 return std::size_t(0);
676#endif // FEAT_HAVE_ZLIB
677 }
678
679 template<typename T_>
680 std::size_t decode(
681 T_* dst,
682 void* buf,
683 const std::size_t count,
684 const std::size_t buf_size,
685 const Pack::Type pack_type,
686 bool swap_bytes)
687 {
688 if(count <= std::size_t(0))
689 {
690 return std::size_t(0);
691 }
692
693 XASSERT(dst != nullptr);
694 XASSERT(buf != nullptr);
695
696 // get raw type
697 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
698
699 // no compression required?
700 if((pack_type & (Pack::Type::Mask_Z | Pack::Type::Mask_P)) == Pack::Type::None)
701 {
702 return decode_raw(dst, buf, count, raw_type, swap_bytes);
703 }
704
705 // zlib compression?
706 if((pack_type & Pack::Type::Mask_Z) == Pack::Type::Mask_Z)
707 {
708 return lossless_decode(dst, buf, count, buf_size, pack_type, swap_bytes);
709 }
710
711 // zfp compression?
712 if((pack_type & Pack::Type::Mask_P) == Pack::Type::Mask_P)
713 {
714 return lossy_decode(dst, buf, count, buf_size, pack_type, swap_bytes);
715 }
716
717 return std::size_t(0);
718 }
719
744 template<typename T_>
745 static std::size_t lossless_decode(
746 T_* dst,
747 const void* buf,
748 const std::size_t count,
749 const std::size_t buf_size,
750 const Pack::Type pack_type,
751 bool swap_bytes)
752 {
753 // get raw type
754 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
755
756#ifdef FEAT_HAVE_ZLIB
757 // ensure that the temporary buffer is large enough
758 std::size_t raw_size = element_size(raw_type) * count + 1024u; // + 1KB
759 std::vector<char> tmp(raw_size);
760
761 // cast buffer lengths to zlib types
762 uLongf dl = static_cast<uLongf>(raw_size);
763 uLong sl = static_cast<uLong>(buf_size);
764
765 // cast buffer pointers to zlib types
766 Bytef* dbuf = reinterpret_cast<Bytef*>(tmp.data());
767 const Bytef* sbuf = reinterpret_cast<const Bytef*>(buf);
768
769 // decompress via zlib
770 if(::uncompress2(dbuf, &dl, sbuf, &sl) != Z_OK)
771 XABORTM("zlib decompression error");
772
773 // decode from temporary buffer
774 decode_raw(dst, tmp.data(), count, raw_type, swap_bytes);
775
776 // return final source buffer usage as reported by zlib
777 return static_cast<std::size_t>(sl);
778#else // no FEAT_HAVE_ZLIB
779 (void)buf_size;
780 (void)buf;
781 (void)dst;
782 (void)raw_type;
783 (void)swap_bytes;
784 (void)pack_type;
785 (void)count;
786 XABORTM("cannot decode compressed type; zlib not available");
787 return std::size_t(0);
788#endif // FEAT_HAVE_ZLIB
789 }
790
824 template<typename T_>
825 static std::size_t lossy_encode(
826 void* buf,
827 T_* src,
828 const std::size_t buf_size,
829 const std::size_t count,
830 const Pack::Type pack_type,
831 bool swap_bytes,
832 const double tolerance)
833 {
834 // get raw type
835 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
836 // Test if zfp is loaded:
837#ifdef FEAT_HAVE_ZFP
838 // get type T_ :
839 zfp_type t = zfp_type::zfp_type_none;
840 switch(pack_type)
841 {
842 case Pack::Type::PF32: t = zfp_type::zfp_type_float; break;
843 case Pack::Type::PF64: t = zfp_type::zfp_type_double; break;
844 default: XABORTM("cannot encode compressed type; data typ not available");
845 }
846 XASSERT(t != zfp_type::zfp_type_none);
847 // check if header can hold size of the array, in case it cant (more than 1
848 // petabyte of double data) give out error for now limitation is only for the
849 // header, not for the underlying zfp_array, so there could be a workaround if
850 // needed...
851 XASSERT(count <= u64(2e14));
852
853 // cast src to the needed type:
854 // ensure that the temporary buffer is large enough
855 std::size_t raw_size = element_size(raw_type) * count + 3 * element_size(raw_type);
856 std::vector<char> tmp(raw_size);
857
858 // encode into temporary buffer
859 encode_raw(tmp.data(), src, count, raw_type, swap_bytes);
860
861 // declare needed zfp internal variables:
862 zfp_field* field;
863 zfp_stream* zfp;
864 std::size_t real_bytes;
865 bitstream* stream;
866 std::size_t x_size, y_size;
867
868 // check if we lose significant bits through type conversion...
869 if((sizeof(std::size_t) > sizeof(uint)) && (count > std::numeric_limits<uint>::max()))
870 XABORTM("cannot encode compressed type; array size to big for internal "
871 "data structure");
872 // calculate needed representation size and rest:
873 x_size = 4u;
874 if(count % 4u == 0)
875 y_size = count / x_size;
876 else
877 y_size = count / x_size + 1;
878
879 // initialize zfp structures:
880 field = zfp_field_2d(tmp.data(), t, (uint)x_size, (uint)y_size);
881 zfp = zfp_stream_open(NULL);
882 zfp_stream_set_accuracy(zfp, tolerance);
883 stream = stream_open(buf, buf_size);
884 zfp_stream_set_bit_stream(zfp, stream);
885 stream_rewind(stream);
886 // write header to stream
887 zfp_write_header(zfp, field, zfp_header_mask);
888 // compress
889 real_bytes = zfp_compress(zfp, field);
890
891 // free allocated data:
892 zfp_field_free(field);
893 zfp_stream_close(zfp);
894 stream_close(stream);
895
896 return real_bytes;
897#else
898 (void)buf_size;
899 (void)buf;
900 (void)src;
901 (void)raw_type;
902 (void)swap_bytes;
903 (void)pack_type;
904 (void)count;
905 (void)tolerance;
906 XABORTM("cannot encode compressed type; zfp not available");
907 return std::size_t(0);
908#endif // FEAT_HAVE_ZFP
909 }
910
936 template<typename T_>
937 static std::size_t lossy_decode(
938 T_* dst,
939 void* buf,
940 const std::size_t count,
941 const std::size_t buf_size,
942 const Pack::Type pack_type,
943 bool swap_bytes)
944 {
945 // get raw type
946 const Pack::Type raw_type = pack_type & Pack::Type::Mask_T;
947#ifdef FEAT_HAVE_ZFP
948 // get type T_ :
949 zfp_type t = zfp_type::zfp_type_none;
950 switch(pack_type)
951 {
952 case Pack::Type::PF32: t = zfp_type::zfp_type_float; break;
953 case Pack::Type::PF64: t = zfp_type::zfp_type_double; break;
954 default: XABORTM("cannot encode compressed type; data typ not available");
955 }
956 XASSERT(t != zfp_type::zfp_type_none);
957
958 // ensure that the temporary buffer is large enough
959 std::size_t raw_size = element_size(raw_type) * count + 1024u; // + 1KB
960 std::vector<char> tmp(raw_size);
961
962 // declare intern zfp variables
963 zfp_field* field;
964 zfp_stream* zfp;
965 bitstream* stream;
966 std::size_t array_size;
967 std::size_t real_bytes;
968 // allocating memory
969 field = zfp_field_alloc();
970 zfp = zfp_stream_open(NULL);
971 // aligning stream with buf:
972 stream = stream_open(buf, buf_size);
973 // read in Codec:
974 stream_rseek(stream, 24u);
975 uint codec = (uint)stream_read_bits(stream, 8u);
976 XASSERTM(
977 codec == zfp_codec_version,
978 "cannot decode compressed type; zfp version not compatible \n "
979 "zfp_Systemcodec: " +
980 stringify(zfp_codec_version) + "\n zfp_Compressed codec: " + stringify(codec));
981 stream_rewind(stream);
982 // aligning zfp_stream with bitsream
983 zfp_stream_set_bit_stream(zfp, stream);
984 // read header
985 zfp_read_header(zfp, field, zfp_header_mask);
986 array_size = zfp_field_size(field, NULL);
987 // check if T_ and type to be decompressed is same:
988 if(t != field->type)
989 XABORTM("cannot decode compressed type; given array and saved data do not "
990 "have the same type");
991 // checking if buffersize of given array is enough to take up saved array....
992 if(array_size - 3 > count)
993 XABORTM("cannot decode compressed data; given count is too small for "
994 "decompressed data!");
995 // alligning field and tmp
996 field->data = tmp.data();
997 // decompress data
998 real_bytes = zfp_decompress(zfp, field);
999
1000 // decode from temporary buffer
1001 decode_raw(dst, tmp.data(), count, raw_type, swap_bytes);
1002
1003 // free memory
1004 zfp_field_free(field);
1005 zfp_stream_close(zfp);
1006 stream_close(stream);
1007
1008 return real_bytes;
1009#else
1010 (void)buf_size;
1011 (void)buf;
1012 (void)dst;
1013 (void)count;
1014 (void)raw_type;
1015 (void)swap_bytes;
1016 (void)pack_type;
1017 XABORTM("cannot decode compressed type; zfp not available");
1018 return std::size_t(0);
1019#endif // FEAT_HAVE_ZFP
1020 }
1021
1023 // Explicit template instantiations for supported data types
1025
1026 template Pack::Type deduct_type<i8>();
1027 template Pack::Type deduct_type<i16>();
1028 template Pack::Type deduct_type<i32>();
1029 template Pack::Type deduct_type<i64>();
1030
1031 template Pack::Type deduct_type<u8>();
1032 template Pack::Type deduct_type<u16>();
1033 template Pack::Type deduct_type<u32>();
1034 template Pack::Type deduct_type<u64>();
1035
1036#if defined(FEAT_HAVE_PACK_TYPE_F16)
1037 template Pack::Type deduct_type<f16>();
1038#endif
1039 template Pack::Type deduct_type<f32>();
1040 template Pack::Type deduct_type<f64>();
1041
1042#if defined(FEAT_HAVE_PACK_TYPE_F128)
1043 template Pack::Type deduct_type<f128>();
1044#endif
1045
1046 template std::size_t encode<i8>(void*, const i8*, std::size_t, std::size_t, Pack::Type, bool, double);
1047 template std::size_t encode<i16>(void*, const i16*, std::size_t, std::size_t, Pack::Type, bool, double);
1048 template std::size_t encode<i32>(void*, const i32*, std::size_t, std::size_t, Pack::Type, bool, double);
1049 template std::size_t encode<i64>(void*, const i64*, std::size_t, std::size_t, Pack::Type, bool, double);
1050
1051 template std::size_t encode<u8>(void*, const u8*, std::size_t, std::size_t, Pack::Type, bool, double);
1052 template std::size_t encode<u16>(void*, const u16*, std::size_t, std::size_t, Pack::Type, bool, double);
1053 template std::size_t encode<u32>(void*, const u32*, std::size_t, std::size_t, Pack::Type, bool, double);
1054 template std::size_t encode<u64>(void*, const u64*, std::size_t, std::size_t, Pack::Type, bool, double);
1055
1056 template std::size_t encode<long long>(void*, const long long*, std::size_t, std::size_t, Pack::Type, bool, double);
1057
1058#if defined(FEAT_HAVE_PACK_TYPE_F16)
1059 template std::size_t encode<f16>(void*, const f16*, std::size_t, std::size_t, Pack::Type, bool, double);
1060#endif
1061 template std::size_t encode<f32>(void*, const f32*, std::size_t, std::size_t, Pack::Type, bool, double);
1062 template std::size_t encode<f64>(void*, const f64*, std::size_t, std::size_t, Pack::Type, bool, double);
1063
1064#if defined(FEAT_HAVE_PACK_TYPE_F128)
1065 template std::size_t encode<f128>(void*, const f128*, std::size_t, std::size_t, Pack::Type, bool, double);
1066#endif
1067
1068 template std::size_t decode<i8>(i8*, void*, std::size_t, std::size_t, Pack::Type, bool);
1069 template std::size_t decode<i16>(i16*, void*, std::size_t, std::size_t, Pack::Type, bool);
1070 template std::size_t decode<i32>(i32*, void*, std::size_t, std::size_t, Pack::Type, bool);
1071 template std::size_t decode<i64>(i64*, void*, std::size_t, std::size_t, Pack::Type, bool);
1072
1073 template std::size_t decode<u8>(u8*, void*, std::size_t, std::size_t, Pack::Type, bool);
1074 template std::size_t decode<u16>(u16*, void*, std::size_t, std::size_t, Pack::Type, bool);
1075 template std::size_t decode<u32>(u32*, void*, std::size_t, std::size_t, Pack::Type, bool);
1076 template std::size_t decode<u64>(u64*, void*, std::size_t, std::size_t, Pack::Type, bool);
1077
1078 template std::size_t decode<long long>(long long*, void*, std::size_t, std::size_t, Pack::Type, bool);
1079
1080#if defined(FEAT_HAVE_PACK_TYPE_F16)
1081 template std::size_t decode<f16>(f16*, void*, std::size_t, std::size_t, Pack::Type, bool);
1082#endif
1083 template std::size_t decode<f32>(f32*, void*, std::size_t, std::size_t, Pack::Type, bool);
1084 template std::size_t decode<f64>(f64*, void*, std::size_t, std::size_t, Pack::Type, bool);
1085
1086#if defined(FEAT_HAVE_PACK_TYPE_F128)
1087 template std::size_t decode<f128>(f128*, void*, std::size_t, std::size_t, Pack::Type, bool);
1088#endif
1089} // namespace FEAT::Pack
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERT(expr)
Assertion macro definition.
Definition: assertion.hpp:262
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
Tag class for floating data types.
Definition: type_traits.hpp:62
Tag class for integral data types.
Definition: type_traits.hpp:60
Data Array Pack namespace.
Definition: pack.cpp:28
static std::size_t xdecode(T_ *dest, const void *buf, const std::size_t count, bool swap_bytes)
Encodes an array by converting each of its elements to a desired type.
Definition: pack.cpp:184
static std::size_t lossy_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 for lossy compression.
Definition: pack.cpp:486
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:566
std::uint64_t u64
64-bit unsigned integer type
Definition: pack.hpp:42
static std::size_t lossless_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)
Encodes an array into a packed buffer.
Definition: pack.cpp:633
std::size_t element_size(const Pack::Type type)
Returns the size of a Pack::Type element in bytes.
Definition: pack.hpp:267
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:543
static std::size_t lossless_decode(T_ *dst, const 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:745
static std::size_t decode_raw(T_ *dst, const void *buf, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
Decodes an array from a packed buffer without compression support.
Definition: pack.cpp:443
Half f16
16-bit floating point type
Definition: pack.hpp:47
float f32
32-bit floating point type
Definition: pack.hpp:54
Type
bitmask for zfp header
Definition: pack.hpp:81
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
static std::size_t lossy_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 with lossy saved compression data.
Definition: pack.cpp:937
static std::size_t encode_raw(void *buf, const T_ *src, const std::size_t count, const Pack::Type pack_type, bool swap_bytes)
Encodes an array into a packed buffer without compression support.
Definition: pack.cpp:394
std::int8_t i8
8-bit signed integer type
Definition: pack.hpp:27
static std::size_t lossy_encode(void *buf, T_ *src, const std::size_t buf_size, const std::size_t count, const Pack::Type pack_type, bool swap_bytes, const double tolerance)
Encodes an array into a packed buffer.
Definition: pack.cpp:825
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:680
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:362
X_ xswap(X_ x)
Swaps the bytes of an object.
Definition: pack.cpp:96
static std::size_t xencode(void *buf, const T_ *src, const std::size_t count, bool swap_bytes)
Encodes an array by converting each of its elements to a desired type.
Definition: pack.cpp:133
FEAT namespace.
Definition: adjactor.hpp:12
String stringify(const T_ &item)
Converts an item into a String.
Definition: string.hpp:944
auxiliary helper class: swaps the bytes of an 8/16/32/64/128 byte type
Definition: pack.cpp:31
basic Type Traits struct
Definition: type_traits.hpp:73