vibe_zstd 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.standard.yml +3 -0
  3. data/CHANGELOG.md +22 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +978 -0
  6. data/Rakefile +20 -0
  7. data/benchmark/README.md +198 -0
  8. data/benchmark/compression_levels.rb +99 -0
  9. data/benchmark/context_reuse.rb +174 -0
  10. data/benchmark/decompression_speed_by_level.rb +65 -0
  11. data/benchmark/dictionary_training.rb +182 -0
  12. data/benchmark/dictionary_usage.rb +121 -0
  13. data/benchmark/for_readme.rb +157 -0
  14. data/benchmark/generate_fixture.rb +82 -0
  15. data/benchmark/helpers.rb +237 -0
  16. data/benchmark/multithreading.rb +105 -0
  17. data/benchmark/run_all.rb +150 -0
  18. data/benchmark/streaming.rb +154 -0
  19. data/ext/vibe_zstd/Makefile +270 -0
  20. data/ext/vibe_zstd/cctx.c +565 -0
  21. data/ext/vibe_zstd/dctx.c +493 -0
  22. data/ext/vibe_zstd/dict.c +587 -0
  23. data/ext/vibe_zstd/extconf.rb +52 -0
  24. data/ext/vibe_zstd/frames.c +132 -0
  25. data/ext/vibe_zstd/libzstd/LICENSE +30 -0
  26. data/ext/vibe_zstd/libzstd/common/allocations.h +55 -0
  27. data/ext/vibe_zstd/libzstd/common/bits.h +205 -0
  28. data/ext/vibe_zstd/libzstd/common/bitstream.h +454 -0
  29. data/ext/vibe_zstd/libzstd/common/compiler.h +464 -0
  30. data/ext/vibe_zstd/libzstd/common/cpu.h +249 -0
  31. data/ext/vibe_zstd/libzstd/common/debug.c +30 -0
  32. data/ext/vibe_zstd/libzstd/common/debug.h +107 -0
  33. data/ext/vibe_zstd/libzstd/common/entropy_common.c +340 -0
  34. data/ext/vibe_zstd/libzstd/common/error_private.c +64 -0
  35. data/ext/vibe_zstd/libzstd/common/error_private.h +158 -0
  36. data/ext/vibe_zstd/libzstd/common/fse.h +625 -0
  37. data/ext/vibe_zstd/libzstd/common/fse_decompress.c +315 -0
  38. data/ext/vibe_zstd/libzstd/common/huf.h +277 -0
  39. data/ext/vibe_zstd/libzstd/common/mem.h +422 -0
  40. data/ext/vibe_zstd/libzstd/common/pool.c +371 -0
  41. data/ext/vibe_zstd/libzstd/common/pool.h +81 -0
  42. data/ext/vibe_zstd/libzstd/common/portability_macros.h +171 -0
  43. data/ext/vibe_zstd/libzstd/common/threading.c +182 -0
  44. data/ext/vibe_zstd/libzstd/common/threading.h +142 -0
  45. data/ext/vibe_zstd/libzstd/common/xxhash.c +18 -0
  46. data/ext/vibe_zstd/libzstd/common/xxhash.h +7094 -0
  47. data/ext/vibe_zstd/libzstd/common/zstd_common.c +48 -0
  48. data/ext/vibe_zstd/libzstd/common/zstd_deps.h +123 -0
  49. data/ext/vibe_zstd/libzstd/common/zstd_internal.h +324 -0
  50. data/ext/vibe_zstd/libzstd/common/zstd_trace.h +156 -0
  51. data/ext/vibe_zstd/libzstd/compress/clevels.h +134 -0
  52. data/ext/vibe_zstd/libzstd/compress/fse_compress.c +625 -0
  53. data/ext/vibe_zstd/libzstd/compress/hist.c +191 -0
  54. data/ext/vibe_zstd/libzstd/compress/hist.h +82 -0
  55. data/ext/vibe_zstd/libzstd/compress/huf_compress.c +1464 -0
  56. data/ext/vibe_zstd/libzstd/compress/zstd_compress.c +7843 -0
  57. data/ext/vibe_zstd/libzstd/compress/zstd_compress_internal.h +1636 -0
  58. data/ext/vibe_zstd/libzstd/compress/zstd_compress_literals.c +235 -0
  59. data/ext/vibe_zstd/libzstd/compress/zstd_compress_literals.h +39 -0
  60. data/ext/vibe_zstd/libzstd/compress/zstd_compress_sequences.c +442 -0
  61. data/ext/vibe_zstd/libzstd/compress/zstd_compress_sequences.h +55 -0
  62. data/ext/vibe_zstd/libzstd/compress/zstd_compress_superblock.c +688 -0
  63. data/ext/vibe_zstd/libzstd/compress/zstd_compress_superblock.h +32 -0
  64. data/ext/vibe_zstd/libzstd/compress/zstd_cwksp.h +765 -0
  65. data/ext/vibe_zstd/libzstd/compress/zstd_double_fast.c +778 -0
  66. data/ext/vibe_zstd/libzstd/compress/zstd_double_fast.h +42 -0
  67. data/ext/vibe_zstd/libzstd/compress/zstd_fast.c +985 -0
  68. data/ext/vibe_zstd/libzstd/compress/zstd_fast.h +30 -0
  69. data/ext/vibe_zstd/libzstd/compress/zstd_lazy.c +2199 -0
  70. data/ext/vibe_zstd/libzstd/compress/zstd_lazy.h +193 -0
  71. data/ext/vibe_zstd/libzstd/compress/zstd_ldm.c +745 -0
  72. data/ext/vibe_zstd/libzstd/compress/zstd_ldm.h +109 -0
  73. data/ext/vibe_zstd/libzstd/compress/zstd_ldm_geartab.h +106 -0
  74. data/ext/vibe_zstd/libzstd/compress/zstd_opt.c +1580 -0
  75. data/ext/vibe_zstd/libzstd/compress/zstd_opt.h +72 -0
  76. data/ext/vibe_zstd/libzstd/compress/zstd_preSplit.c +238 -0
  77. data/ext/vibe_zstd/libzstd/compress/zstd_preSplit.h +33 -0
  78. data/ext/vibe_zstd/libzstd/compress/zstdmt_compress.c +1923 -0
  79. data/ext/vibe_zstd/libzstd/compress/zstdmt_compress.h +102 -0
  80. data/ext/vibe_zstd/libzstd/decompress/huf_decompress.c +1944 -0
  81. data/ext/vibe_zstd/libzstd/decompress/huf_decompress_amd64.S +602 -0
  82. data/ext/vibe_zstd/libzstd/decompress/zstd_ddict.c +244 -0
  83. data/ext/vibe_zstd/libzstd/decompress/zstd_ddict.h +44 -0
  84. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress.c +2410 -0
  85. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_block.c +2209 -0
  86. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_block.h +73 -0
  87. data/ext/vibe_zstd/libzstd/decompress/zstd_decompress_internal.h +240 -0
  88. data/ext/vibe_zstd/libzstd/deprecated/zbuff.h +214 -0
  89. data/ext/vibe_zstd/libzstd/deprecated/zbuff_common.c +26 -0
  90. data/ext/vibe_zstd/libzstd/deprecated/zbuff_compress.c +167 -0
  91. data/ext/vibe_zstd/libzstd/deprecated/zbuff_decompress.c +77 -0
  92. data/ext/vibe_zstd/libzstd/dictBuilder/cover.c +1302 -0
  93. data/ext/vibe_zstd/libzstd/dictBuilder/cover.h +152 -0
  94. data/ext/vibe_zstd/libzstd/dictBuilder/divsufsort.c +1913 -0
  95. data/ext/vibe_zstd/libzstd/dictBuilder/divsufsort.h +57 -0
  96. data/ext/vibe_zstd/libzstd/dictBuilder/fastcover.c +766 -0
  97. data/ext/vibe_zstd/libzstd/dictBuilder/zdict.c +1133 -0
  98. data/ext/vibe_zstd/libzstd/zdict.h +481 -0
  99. data/ext/vibe_zstd/libzstd/zstd.h +3198 -0
  100. data/ext/vibe_zstd/libzstd/zstd_errors.h +107 -0
  101. data/ext/vibe_zstd/streaming.c +410 -0
  102. data/ext/vibe_zstd/vibe_zstd.c +293 -0
  103. data/ext/vibe_zstd/vibe_zstd.h +56 -0
  104. data/ext/vibe_zstd/vibe_zstd_internal.h +27 -0
  105. data/lib/vibe_zstd/constants.rb +67 -0
  106. data/lib/vibe_zstd/version.rb +5 -0
  107. data/lib/vibe_zstd.rb +255 -0
  108. data/sig/vibe_zstd.rbs +76 -0
  109. metadata +179 -0
@@ -0,0 +1,132 @@
1
+ // Frame utilities implementation for VibeZstd
2
+ #include "vibe_zstd_internal.h"
3
+
4
+ // VibeZstd.compress_bound(size)
5
+ static VALUE
6
+ vibe_zstd_compress_bound(VALUE self, VALUE size) {
7
+ size_t src_size = NUM2SIZET(size);
8
+ size_t bound = ZSTD_compressBound(src_size);
9
+ return SIZET2NUM(bound);
10
+ }
11
+
12
+ static VALUE
13
+ vibe_zstd_skippable_frame_p(VALUE self, VALUE data) {
14
+ (void)self;
15
+ StringValue(data);
16
+ unsigned result = ZSTD_isSkippableFrame(RSTRING_PTR(data), RSTRING_LEN(data));
17
+ return result ? Qtrue : Qfalse;
18
+ }
19
+
20
+ static VALUE
21
+ vibe_zstd_write_skippable_frame(int argc, VALUE *argv, VALUE self) {
22
+ (void)self;
23
+ VALUE data, options;
24
+ rb_scan_args(argc, argv, "11", &data, &options);
25
+
26
+ StringValue(data);
27
+
28
+ unsigned magic_variant = 0; // Default to 0
29
+ if (!NIL_P(options)) {
30
+ Check_Type(options, T_HASH);
31
+ VALUE magic_num = rb_hash_aref(options, ID2SYM(rb_intern("magic_number")));
32
+ if (!NIL_P(magic_num)) {
33
+ magic_variant = NUM2UINT(magic_num);
34
+ if (magic_variant > 15) {
35
+ rb_raise(rb_eArgError, "magic_number %u out of bounds (valid: 0-15)", magic_variant);
36
+ }
37
+ }
38
+ }
39
+
40
+ const char* src = RSTRING_PTR(data);
41
+ size_t src_size = RSTRING_LEN(data);
42
+
43
+ // Skippable frame structure: 4-byte magic (0x184D2A5X) + 4-byte size + content
44
+ // Decoders skip these frames, allowing custom metadata/padding
45
+ size_t frame_size = 8 + src_size;
46
+ VALUE result = rb_str_buf_new(frame_size);
47
+
48
+ size_t written = ZSTD_writeSkippableFrame(
49
+ RSTRING_PTR(result),
50
+ frame_size,
51
+ src,
52
+ src_size,
53
+ magic_variant
54
+ );
55
+
56
+ if (ZSTD_isError(written)) {
57
+ rb_raise(rb_eRuntimeError, "Failed to write skippable frame: %s", ZSTD_getErrorName(written));
58
+ }
59
+
60
+ rb_str_set_len(result, written);
61
+ return result;
62
+ }
63
+
64
+ static VALUE
65
+ vibe_zstd_read_skippable_frame(VALUE self, VALUE data) {
66
+ (void)self;
67
+ StringValue(data);
68
+
69
+ if (!ZSTD_isSkippableFrame(RSTRING_PTR(data), RSTRING_LEN(data))) {
70
+ rb_raise(rb_eArgError, "data is not a skippable frame (%zu bytes provided)", RSTRING_LEN(data));
71
+ }
72
+
73
+ const char* src = RSTRING_PTR(data);
74
+ size_t src_size = RSTRING_LEN(data);
75
+
76
+ // Content size is in bytes 4-7 (little-endian uint32)
77
+ if (src_size < 8) {
78
+ rb_raise(rb_eArgError, "skippable frame too small (%zu bytes, minimum 8 bytes required)", src_size);
79
+ }
80
+
81
+ uint32_t content_size;
82
+ memcpy(&content_size, src + 4, 4);
83
+
84
+ VALUE result = rb_str_buf_new(content_size);
85
+ unsigned magic_variant;
86
+
87
+ size_t bytes_read = ZSTD_readSkippableFrame(
88
+ RSTRING_PTR(result),
89
+ content_size,
90
+ &magic_variant,
91
+ src,
92
+ src_size
93
+ );
94
+
95
+ if (ZSTD_isError(bytes_read)) {
96
+ rb_raise(rb_eRuntimeError, "Failed to read skippable frame: %s", ZSTD_getErrorName(bytes_read));
97
+ }
98
+
99
+ rb_str_set_len(result, bytes_read);
100
+
101
+ // Return [content, magic_variant]
102
+ VALUE result_ary = rb_ary_new_capa(2);
103
+ rb_ary_push(result_ary, result);
104
+ rb_ary_push(result_ary, UINT2NUM(magic_variant));
105
+ return result_ary;
106
+ }
107
+
108
+ static VALUE
109
+ vibe_zstd_find_frame_compressed_size(VALUE self, VALUE data) {
110
+ (void)self;
111
+ StringValue(data);
112
+
113
+ // Returns compressed size of first complete frame (including header/checksum)
114
+ // Useful for splitting concatenated frames in multi-frame archives
115
+ size_t frame_size = ZSTD_findFrameCompressedSize(RSTRING_PTR(data), RSTRING_LEN(data));
116
+
117
+ if (ZSTD_isError(frame_size)) {
118
+ rb_raise(rb_eRuntimeError, "Failed to find frame size: %s", ZSTD_getErrorName(frame_size));
119
+ }
120
+
121
+ return SIZET2NUM(frame_size);
122
+ }
123
+
124
+ // Module method initialization called from main Init_vibe_zstd
125
+ void
126
+ vibe_zstd_frames_init_module_methods(VALUE rb_mVibeZstd) {
127
+ rb_define_module_function(rb_mVibeZstd, "compress_bound", vibe_zstd_compress_bound, 1);
128
+ rb_define_module_function(rb_mVibeZstd, "skippable_frame?", vibe_zstd_skippable_frame_p, 1);
129
+ rb_define_module_function(rb_mVibeZstd, "write_skippable_frame", vibe_zstd_write_skippable_frame, -1);
130
+ rb_define_module_function(rb_mVibeZstd, "read_skippable_frame", vibe_zstd_read_skippable_frame, 1);
131
+ rb_define_module_function(rb_mVibeZstd, "find_frame_compressed_size", vibe_zstd_find_frame_compressed_size, 1);
132
+ }
@@ -0,0 +1,30 @@
1
+ BSD License
2
+
3
+ For Zstandard software
4
+
5
+ Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without modification,
8
+ are permitted provided that the following conditions are met:
9
+
10
+ * Redistributions of source code must retain the above copyright notice, this
11
+ list of conditions and the following disclaimer.
12
+
13
+ * Redistributions in binary form must reproduce the above copyright notice,
14
+ this list of conditions and the following disclaimer in the documentation
15
+ and/or other materials provided with the distribution.
16
+
17
+ * Neither the name Facebook, nor Meta, nor the names of its contributors may
18
+ be used to endorse or promote products derived from this software without
19
+ specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+ /* This file provides custom allocation primitives
12
+ */
13
+
14
+ #define ZSTD_DEPS_NEED_MALLOC
15
+ #include "zstd_deps.h" /* ZSTD_malloc, ZSTD_calloc, ZSTD_free, ZSTD_memset */
16
+
17
+ #include "compiler.h" /* MEM_STATIC */
18
+ #define ZSTD_STATIC_LINKING_ONLY
19
+ #include "../zstd.h" /* ZSTD_customMem */
20
+
21
+ #ifndef ZSTD_ALLOCATIONS_H
22
+ #define ZSTD_ALLOCATIONS_H
23
+
24
+ /* custom memory allocation functions */
25
+
26
+ MEM_STATIC void* ZSTD_customMalloc(size_t size, ZSTD_customMem customMem)
27
+ {
28
+ if (customMem.customAlloc)
29
+ return customMem.customAlloc(customMem.opaque, size);
30
+ return ZSTD_malloc(size);
31
+ }
32
+
33
+ MEM_STATIC void* ZSTD_customCalloc(size_t size, ZSTD_customMem customMem)
34
+ {
35
+ if (customMem.customAlloc) {
36
+ /* calloc implemented as malloc+memset;
37
+ * not as efficient as calloc, but next best guess for custom malloc */
38
+ void* const ptr = customMem.customAlloc(customMem.opaque, size);
39
+ ZSTD_memset(ptr, 0, size);
40
+ return ptr;
41
+ }
42
+ return ZSTD_calloc(1, size);
43
+ }
44
+
45
+ MEM_STATIC void ZSTD_customFree(void* ptr, ZSTD_customMem customMem)
46
+ {
47
+ if (ptr!=NULL) {
48
+ if (customMem.customFree)
49
+ customMem.customFree(customMem.opaque, ptr);
50
+ else
51
+ ZSTD_free(ptr);
52
+ }
53
+ }
54
+
55
+ #endif /* ZSTD_ALLOCATIONS_H */
@@ -0,0 +1,205 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under both the BSD-style license (found in the
6
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7
+ * in the COPYING file in the root directory of this source tree).
8
+ * You may select, at your option, one of the above-listed licenses.
9
+ */
10
+
11
+ #ifndef ZSTD_BITS_H
12
+ #define ZSTD_BITS_H
13
+
14
+ #include "mem.h"
15
+
16
+ MEM_STATIC unsigned ZSTD_countTrailingZeros32_fallback(U32 val)
17
+ {
18
+ assert(val != 0);
19
+ {
20
+ static const U32 DeBruijnBytePos[32] = {0, 1, 28, 2, 29, 14, 24, 3,
21
+ 30, 22, 20, 15, 25, 17, 4, 8,
22
+ 31, 27, 13, 23, 21, 19, 16, 7,
23
+ 26, 12, 18, 6, 11, 5, 10, 9};
24
+ return DeBruijnBytePos[((U32) ((val & -(S32) val) * 0x077CB531U)) >> 27];
25
+ }
26
+ }
27
+
28
+ MEM_STATIC unsigned ZSTD_countTrailingZeros32(U32 val)
29
+ {
30
+ assert(val != 0);
31
+ #if defined(_MSC_VER)
32
+ # if STATIC_BMI2
33
+ return (unsigned)_tzcnt_u32(val);
34
+ # else
35
+ if (val != 0) {
36
+ unsigned long r;
37
+ _BitScanForward(&r, val);
38
+ return (unsigned)r;
39
+ } else {
40
+ __assume(0); /* Should not reach this code path */
41
+ }
42
+ # endif
43
+ #elif defined(__GNUC__) && (__GNUC__ >= 4)
44
+ return (unsigned)__builtin_ctz(val);
45
+ #elif defined(__ICCARM__)
46
+ return (unsigned)__builtin_ctz(val);
47
+ #else
48
+ return ZSTD_countTrailingZeros32_fallback(val);
49
+ #endif
50
+ }
51
+
52
+ MEM_STATIC unsigned ZSTD_countLeadingZeros32_fallback(U32 val)
53
+ {
54
+ assert(val != 0);
55
+ {
56
+ static const U32 DeBruijnClz[32] = {0, 9, 1, 10, 13, 21, 2, 29,
57
+ 11, 14, 16, 18, 22, 25, 3, 30,
58
+ 8, 12, 20, 28, 15, 17, 24, 7,
59
+ 19, 27, 23, 6, 26, 5, 4, 31};
60
+ val |= val >> 1;
61
+ val |= val >> 2;
62
+ val |= val >> 4;
63
+ val |= val >> 8;
64
+ val |= val >> 16;
65
+ return 31 - DeBruijnClz[(val * 0x07C4ACDDU) >> 27];
66
+ }
67
+ }
68
+
69
+ MEM_STATIC unsigned ZSTD_countLeadingZeros32(U32 val)
70
+ {
71
+ assert(val != 0);
72
+ #if defined(_MSC_VER)
73
+ # if STATIC_BMI2
74
+ return (unsigned)_lzcnt_u32(val);
75
+ # else
76
+ if (val != 0) {
77
+ unsigned long r;
78
+ _BitScanReverse(&r, val);
79
+ return (unsigned)(31 - r);
80
+ } else {
81
+ __assume(0); /* Should not reach this code path */
82
+ }
83
+ # endif
84
+ #elif defined(__GNUC__) && (__GNUC__ >= 4)
85
+ return (unsigned)__builtin_clz(val);
86
+ #elif defined(__ICCARM__)
87
+ return (unsigned)__builtin_clz(val);
88
+ #else
89
+ return ZSTD_countLeadingZeros32_fallback(val);
90
+ #endif
91
+ }
92
+
93
+ MEM_STATIC unsigned ZSTD_countTrailingZeros64(U64 val)
94
+ {
95
+ assert(val != 0);
96
+ #if defined(_MSC_VER) && defined(_WIN64)
97
+ # if STATIC_BMI2
98
+ return (unsigned)_tzcnt_u64(val);
99
+ # else
100
+ if (val != 0) {
101
+ unsigned long r;
102
+ _BitScanForward64(&r, val);
103
+ return (unsigned)r;
104
+ } else {
105
+ __assume(0); /* Should not reach this code path */
106
+ }
107
+ # endif
108
+ #elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(__LP64__)
109
+ return (unsigned)__builtin_ctzll(val);
110
+ #elif defined(__ICCARM__)
111
+ return (unsigned)__builtin_ctzll(val);
112
+ #else
113
+ {
114
+ U32 mostSignificantWord = (U32)(val >> 32);
115
+ U32 leastSignificantWord = (U32)val;
116
+ if (leastSignificantWord == 0) {
117
+ return 32 + ZSTD_countTrailingZeros32(mostSignificantWord);
118
+ } else {
119
+ return ZSTD_countTrailingZeros32(leastSignificantWord);
120
+ }
121
+ }
122
+ #endif
123
+ }
124
+
125
+ MEM_STATIC unsigned ZSTD_countLeadingZeros64(U64 val)
126
+ {
127
+ assert(val != 0);
128
+ #if defined(_MSC_VER) && defined(_WIN64)
129
+ # if STATIC_BMI2
130
+ return (unsigned)_lzcnt_u64(val);
131
+ # else
132
+ if (val != 0) {
133
+ unsigned long r;
134
+ _BitScanReverse64(&r, val);
135
+ return (unsigned)(63 - r);
136
+ } else {
137
+ __assume(0); /* Should not reach this code path */
138
+ }
139
+ # endif
140
+ #elif defined(__GNUC__) && (__GNUC__ >= 4)
141
+ return (unsigned)(__builtin_clzll(val));
142
+ #elif defined(__ICCARM__)
143
+ return (unsigned)(__builtin_clzll(val));
144
+ #else
145
+ {
146
+ U32 mostSignificantWord = (U32)(val >> 32);
147
+ U32 leastSignificantWord = (U32)val;
148
+ if (mostSignificantWord == 0) {
149
+ return 32 + ZSTD_countLeadingZeros32(leastSignificantWord);
150
+ } else {
151
+ return ZSTD_countLeadingZeros32(mostSignificantWord);
152
+ }
153
+ }
154
+ #endif
155
+ }
156
+
157
+ MEM_STATIC unsigned ZSTD_NbCommonBytes(size_t val)
158
+ {
159
+ if (MEM_isLittleEndian()) {
160
+ if (MEM_64bits()) {
161
+ return ZSTD_countTrailingZeros64((U64)val) >> 3;
162
+ } else {
163
+ return ZSTD_countTrailingZeros32((U32)val) >> 3;
164
+ }
165
+ } else { /* Big Endian CPU */
166
+ if (MEM_64bits()) {
167
+ return ZSTD_countLeadingZeros64((U64)val) >> 3;
168
+ } else {
169
+ return ZSTD_countLeadingZeros32((U32)val) >> 3;
170
+ }
171
+ }
172
+ }
173
+
174
+ MEM_STATIC unsigned ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus */
175
+ {
176
+ assert(val != 0);
177
+ return 31 - ZSTD_countLeadingZeros32(val);
178
+ }
179
+
180
+ /* ZSTD_rotateRight_*():
181
+ * Rotates a bitfield to the right by "count" bits.
182
+ * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts
183
+ */
184
+ MEM_STATIC
185
+ U64 ZSTD_rotateRight_U64(U64 const value, U32 count) {
186
+ assert(count < 64);
187
+ count &= 0x3F; /* for fickle pattern recognition */
188
+ return (value >> count) | (U64)(value << ((0U - count) & 0x3F));
189
+ }
190
+
191
+ MEM_STATIC
192
+ U32 ZSTD_rotateRight_U32(U32 const value, U32 count) {
193
+ assert(count < 32);
194
+ count &= 0x1F; /* for fickle pattern recognition */
195
+ return (value >> count) | (U32)(value << ((0U - count) & 0x1F));
196
+ }
197
+
198
+ MEM_STATIC
199
+ U16 ZSTD_rotateRight_U16(U16 const value, U32 count) {
200
+ assert(count < 16);
201
+ count &= 0x0F; /* for fickle pattern recognition */
202
+ return (value >> count) | (U16)(value << ((0U - count) & 0x0F));
203
+ }
204
+
205
+ #endif /* ZSTD_BITS_H */