38 #include "ThirdParty/lzo/minilzo.h"
40 #pragma GCC diagnostic ignored "-Wpedantic"
46 #define BM_M2 (0xffff - 4)
48 #define BM_MASK16 0xffff
49 #define BM_MASK24 0xffffff
50 #define BM_MASK32 0xffffffff
51 #define BM_MASKSZ BM_MASK32
57 #define BM_MAX_LEN 0xfdffffffffffull
58 #define BM_MAX_1B 0xfd
59 #define BM_MAX_2B 0xfdff
60 #define BM_MAX_3B 0xfdffff
61 #define BM_MAX_4B 0xfdfffffful
62 #define BM_MAX_5B 0xfdffffffffull
65 #define BM_MAX_V1B 0x7f
66 #define BM_MAX_V2B 0x3fff
67 #define BM_MAX_V3B 0x1fffff
68 #define BM_MAX_V4B 0xfffffff
69 #define BM_MAX_V5B 0x7ffffffffull
70 #define BM_MAX_V6B 0x3ffffffffffull
73 #define BM_COLLISION_ABORT_THRESH 1
74 #define BM_ABORT_COLLISIONS \
75 ((BM_COLLISION_ABORT_THRESH + 1) * collision_thresh + 1)
78 #define BM_COLOR_DBG "\x1b[31m"
79 #define BM_COLOR_ALT "\x1b[32m"
80 #define BM_COLOR_END "\x1b[m"
90 typedef long long unsigned Llu;
93 #define BM_NPOS ((size_t)-1)
96 #define BM_ALIGN(_mem_, _n_) (Byte *)(_mem_) + _n_ - (((size_t)(_mem_))%(_n_))
100 3, 5, 7, 11, 13, 17, 19, 23, 29,
101 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
102 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
103 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
104 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
105 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
106 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
107 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
108 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
109 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
110 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
111 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
112 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
113 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
114 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
115 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
116 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
117 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
118 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
119 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
120 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
121 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
122 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
123 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
124 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
125 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
126 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
127 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
128 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
129 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
130 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
131 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
132 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
133 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
134 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
135 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
136 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
137 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
138 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
139 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
140 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
141 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
142 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
143 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
144 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
145 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
146 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
147 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
148 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
149 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
150 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
151 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
152 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
153 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
154 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
155 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
156 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
157 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
158 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
159 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
160 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493,
161 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583,
162 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657,
163 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
164 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831,
165 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937,
166 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003,
167 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
168 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179,
169 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279,
170 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387,
171 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
172 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521,
173 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639,
174 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693,
175 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
176 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857,
177 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939,
178 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053,
179 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
180 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221,
181 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301,
182 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367,
183 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
184 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571,
185 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673,
186 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761,
187 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
188 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917,
189 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997,
190 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103,
191 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
192 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297,
193 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411,
194 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499,
195 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
196 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643,
197 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723,
198 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829,
199 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
200 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017
211 fwrite(buf, 1, len, stderr);
223 #define BM_LOG(_level_, _fmt_, ...) if (s_verbosity >= _level_) do { \
225 int len = snprintf(msg, sizeof(msg), "%s: " _fmt_, __FUNCTION__, \
227 s_out_proc(msg, len); \
230 #define BM_LOG_(_level_, _buf_, _len_) if (s_verbosity >= _level_) do { \
231 s_out_proc((char *)_buf_, _len_); \
234 #define BM_DIE(_fmt_, ...) do { \
236 snprintf(msg, sizeof(msg), "fatal: %s: " _fmt_ "\n", \
237 __FUNCTION__, ##__VA_ARGS__); \
241 #define BM_CHECK(_cond_) \
242 if (_cond_); else BM_DIE("%s:%d: expects: %s", \
243 __FILE__, __LINE__, #_cond_)
271 const size_t n =
sizeof(
s_primes) /
sizeof(
size_t);
276 static int sranded = 0;
286 if (s != excluded)
return s;
305 }
while (x < n * 8 / 5);
315 size_t size, collisions, adapts, probes;
327 for (p = table->
entries, endp = p + table->
size; p < endp; ++p)
334 #define BM_LOOKUP(_lut_, _hash_, _entry_) do { \
335 size_t sz = _lut_.size, idx = (_hash_) & (sz - 1), probes = 0; \
336 BmLutEntry *b = _lut_.entries, *p = b + idx, *endp = b + sz; \
338 while (p->pos != BM_NPOS) { \
339 if (p->hash == _hash_) break; \
341 if (p >= endp) p = b; \
344 if (probes) _lut_.probes += probes; \
349 #define R_HASH_MOD_BODY(_int_type_) \
350 _int_type_ h = 0, p = 1; \
379 #define POW_MOD_BODY(_pow_fun_, _int_type_) \
380 if (n == 0) return 1; \
381 if (n == 1) return x % m; \
383 _int_type_ sqr = (x * x) % m; \
384 _int_type_ pow = _pow_fun_(sqr, n / 2, m); \
385 if (n & 1) return (pow * x) % m; \
400 #define UPDATE_HASH_MOD_BODY \
402 h -= (out * pow_n) % m; \
427 #define R_HASH_MASK_BODY(int_type) \
428 int_type h = 0, p = 1; \
461 #define POW_MASK_BODY(_pow_fun_, _int_type_) \
462 if (n == 0) return 1; \
463 if (n == 1) return (x & m); \
465 _int_type_ sqr = (x * x) & m; \
466 _int_type_ pow = _pow_fun_(sqr, n / 2, m); \
467 if (n & 1) return ((pow * x) & m); \
481 #define UPDATE_HASH_MASK_BODY \
483 h -= (out * pow_n) & m; \
520 size_t m1,
size_t m2) {
540 #define BM_HASH_CHECK_BODY(_init_hash_, _rehash_, _update_hash_) \
542 Byte *in = (Byte *)src, *ip = in, *in_end = in + in_len; \
545 BM_CHECK(fp_len < in_len); \
548 for (; ip < in_end - fp_len - 1; ++ip) { \
549 size_t h0 = _rehash_; \
550 hash = _update_hash_; \
552 BM_LOG(0, "mismatch at pos %ld: %lx vs %lx\n", \
553 (long)(ip - in), (long)h0, (long)hash); \
557 BM_LOG(1, "total errors: %d\n", errs); \
558 return errs ? BMZ_E_ERROR : BMZ_E_OK
560 #define BM_HASH_BENCH_BODY(_init_hash_, _update_hash_) \
562 Byte *in = (Byte *)src, *ip = in, *in_end = in + in_len; \
564 BM_CHECK(fp_len < in_len); \
567 for (; ip < in_end - fp_len - 1; ++ip) { \
568 hash = _update_hash_; \
570 BM_LOG(1, "last hash: %lx\n", (long)hash)
574 size_t b,
size_t m) {
595 size_t b1,
size_t b2,
size_t m1,
size_t m2) {
596 size_t pow_n_b1, pow_n_b2;
603 pow_n_b2, b1, b2, m1, m2));
614 pow_n_b2, b1, b2, m1, m2));
619 size_t b1,
size_t b2) {
620 size_t pow_n_b1, pow_n_b2;
632 size_t pow_n_b1, pow_n_b2, b1 =
BM_B1, b2 =
BM_B2;
663 size_t b1,
size_t b2) {
664 size_t pow_n_b1, pow_n_b2;
676 size_t pow_n_b1, pow_n_b2, b1 =
BM_B1, b2 =
BM_B2;
708 #define BM_LUT_BENCH_BODY(_init_hash_, _update_hash_) \
710 Byte *in = (Byte *)src, *ip = in, *in_end = in + in_len; \
711 size_t scan_len = in_len - fp_len, c, boundary; \
715 BM_CHECK(fp_len < in_len); \
716 init_bmlut(&lut, in_len / fp_len, work_mem); \
719 for (boundary = fp_len; ip < in_end - fp_len - 1; ++ip) { \
720 size_t pos = ip - in; \
721 BM_LOOKUP(lut, hash, entry); \
723 if (entry->pos != BM_NPOS) { \
724 if (memcmp(in + entry->pos, ip, fp_len) != 0) ++lut.collisions; \
726 if (pos == boundary) { \
727 entry->hash = hash; \
729 boundary += fp_len; \
731 hash = _update_hash_; \
733 c = lut.collisions; \
734 BM_LOG(1, "length: %llu, lut.size: %llu, lut.collisions: %llu (eff. bits: " \
735 "%.3f), lut.probes: %llu (%.3f/lu)\n", (Llu)in_len, (Llu)lut.size, \
736 (Llu)c, c ? log((double)in_len / fp_len * scan_len / c) / log(2) \
737 : sizeof(size_t) * 8., \
738 (Llu)lut.probes, (double)lut.probes / scan_len)
742 void *work_mem,
size_t b,
size_t m) {
752 void *work_mem,
size_t b1,
size_t b2,
753 size_t m1,
size_t m2) {
754 size_t pow_n_b1, pow_n_b2;
760 pow_n_b2, b1, b2, m1, m2));
765 void *work_mem,
size_t b1,
size_t b2) {
766 size_t pow_n_b1, pow_n_b2;
777 void *work_mem,
size_t b) {
787 void *work_mem,
size_t b1,
size_t b2) {
788 size_t pow_n_b1, pow_n_b2;
801 #define BM_NEED_IN(_n_) \
802 if ((int)(in_end - ip) < (int)(_n_)) goto input_overrun
804 #define BM_NEED_OUT(_n_) \
805 if ((int)(out_end - op) < (int)(_n_)) goto output_overrun
807 #define BM_ENCODE_OUTPUT(_op_, _ip_, _ip_end_) \
808 while (_ip_ < _ip_end_) { \
809 if (*_ip_ == BM_ESC) { \
818 #define BM_ENCODE_FINAL_OUTPUT(_op_, _ip_, _ip_end_) \
819 BM_NEED_OUT((_ip_end_) - (_ip_)); \
820 while (_ip_ < _ip_end_) { \
821 if (*_ip_ == BM_ESC) { \
822 BM_NEED_OUT((_ip_end_) - (_ip_) + 1); \
828 #define BM_ENCODE_PASS do { \
830 memcpy(out + 1, in, in_len); \
831 *out_len_p = in_len + 1; \
832 BM_ENCODE_STAT("no reduction"); \
836 #define BM_ENCODE_INT(_op_, _n_, _width_) do { \
840 *_op_++ = (Byte) _n; \
843 *_op_++ = (Byte)(_n >> 8); \
844 *_op_++ = (Byte)(_n); \
847 *_op_++ = (Byte)(_n >> 16); \
848 *_op_++ = (Byte)(_n >> 8); \
849 *_op_++ = (Byte)(_n); \
852 *_op_++ = (Byte)(_n >> 24); \
853 *_op_++ = (Byte)(_n >> 16); \
854 *_op_++ = (Byte)(_n >> 8); \
855 *_op_++ = (Byte)(_n); \
858 *_op_++ = (Byte)(_n >> 32); \
859 *_op_++ = (Byte)(_n >> 24); \
860 *_op_++ = (Byte)(_n >> 16); \
861 *_op_++ = (Byte)(_n >> 8); \
862 *_op_++ = (Byte)(_n); \
865 *_op_++ = (Byte)(_n >> 40); \
866 *_op_++ = (Byte)(_n >> 32); \
867 *_op_++ = (Byte)(_n >> 24); \
868 *_op_++ = (Byte)(_n >> 16); \
869 *_op_++ = (Byte)(_n >> 8); \
870 *_op_++ = (Byte)(_n); \
873 BM_DIE("%s", "256TB ought to be enough for anyone!"); \
877 #define BM_ENCODE_VINT(_op_, _n_, _width_) do { \
881 *_op_++ = (Byte)((_n) & 0x7f); \
884 *_op_++ = (Byte)(_n | 0x80); \
885 *_op_++ = (Byte)((_n >> 7) & 0x7f); \
888 *_op_++ = (Byte)(_n | 0x80); \
889 *_op_++ = (Byte)((_n >> 7) | 0x80); \
890 *_op_++ = (Byte)((_n >> 14) & 0x7f); \
893 *_op_++ = (Byte)(_n | 0x80); \
894 *_op_++ = (Byte)((_n >> 7) | 0x80); \
895 *_op_++ = (Byte)((_n >> 14) | 0x80); \
896 *_op_++ = (Byte)((_n >> 21) & 0x7f); \
899 *_op_++ = (Byte)(_n | 0x80); \
900 *_op_++ = (Byte)((_n >> 7) | 0x80); \
901 *_op_++ = (Byte)((_n >> 14) | 0x80); \
902 *_op_++ = (Byte)((_n >> 21) | 0x80); \
903 *_op_++ = (Byte)((_n >> 28) & 0x7f); \
906 *_op_++ = (Byte)(_n | 0x80); \
907 *_op_++ = (Byte)((_n >> 7) | 0x80); \
908 *_op_++ = (Byte)((_n >> 14) | 0x80); \
909 *_op_++ = (Byte)((_n >> 21) | 0x80); \
910 *_op_++ = (Byte)((_n >> 28) | 0x80); \
911 *_op_++ = (Byte)((_n >> 35) & 0x7f); \
914 *_op_++ = (Byte)(_n | 0x80); \
915 *_op_++ = (Byte)((_n >> 7) | 0x80); \
916 *_op_++ = (Byte)((_n >> 14) | 0x80); \
917 *_op_++ = (Byte)((_n >> 21) | 0x80); \
918 *_op_++ = (Byte)((_n >> 28) | 0x80); \
919 *_op_++ = (Byte)((_n >> 35) | 0x80); \
920 *_op_++ = (Byte)((_n >> 42) & 0x7f); \
923 BM_DIE("%s", "512TB ought to be enough for anyone!"); \
927 #define BM_DECODE_VINT(_n_) do { \
929 _n_ = (*ip++ & 0x7f); \
930 if (ip[-1] & 0x80) { \
932 _n_ |= ((*ip++ & 0x7f) << 7); \
934 if (ip[-1] & 0x80) { \
936 _n_ |= ((*ip++ & 0x7f) << 14); \
938 if (ip[-1] & 0x80) { \
940 _n_ |= ((*ip++ & 0x7f) << 21); \
942 if (ip[-1] & 0x80) { \
944 _n_ |= ((UInt64)(*ip++ & 0x7f) << 28); \
946 if (ip[-1] & 0x80) { \
948 _n_ |= ((UInt64)(*ip++ & 0x7f) << 35); \
950 if (ip[-1] & 0x80) { \
952 _n_ |= ((UInt64)(*ip++ & 0x7f) << 42); \
956 #define BM_INT_WIDTH(_n_) \
957 (_n_ > BM_MAX_5B ? 6 : \
958 (_n_ > BM_MAX_4B ? 5 : \
959 (_n_ > BM_MAX_3B ? 4 : \
960 (_n_ > BM_MAX_2B ? 3 : \
961 (_n_ > BM_MAX_1B ? 2 : 1)))))
963 #define BM_VINT_WIDTH(_n_) \
964 (_n_ > BM_MAX_V6B ? 7 : \
965 (_n_ > BM_MAX_V5B ? 6 : \
966 (_n_ > BM_MAX_V4B ? 5 : \
967 (_n_ > BM_MAX_V3B ? 4 : \
968 (_n_ > BM_MAX_V2B ? 3 : \
969 (_n_ > BM_MAX_V1B ? 2 : 1))))))
971 #define BM_ENCODE_DELTA(_op_, _ipos_, _pos_, _len_) do { \
972 UInt64 _ipos = _ipos_, _len = _len_; \
973 int pos_w = BM_INT_WIDTH(_ipos); \
974 int len_w = BM_VINT_WIDTH(_len); \
975 BM_NEED_OUT(pos_w + len_w + 1); \
977 BM_ENCODE_INT(_op_, _pos_, pos_w); \
978 BM_ENCODE_VINT(_op_, _len_, len_w); \
981 #define BM_HANDLE_COLLISIONS(_randomize_, _init_hash_) do { \
982 size_t adapts = lut.adapts, collisions = ++lut.collisions; \
984 if (adapts > BM_COLLISION_ABORT_THRESH) { \
986 BM_LOG(1, "too much collisions: %llu, giving up.\n", \
987 (Llu)BM_ABORT_COLLISIONS); \
988 goto output_overrun; \
990 else if (collisions > collision_thresh) { \
994 BM_LOG(2, "hash collision %llu: %llx: pos: %llu and %llu: [" BM_COLOR_DBG, \
995 (Llu)lut.collisions, (Llu)hash, (Llu)pos, (Llu)i); \
996 BM_LOG_(2, in + pos, fp_len); \
997 BM_LOG(2, "%s", BM_COLOR_END "] vs [" BM_COLOR_ALT); \
998 BM_LOG_(2, in + i, fp_len); \
999 BM_LOG(2, "%s", BM_COLOR_END "] trying to adapt.\n"); \
1001 boundary = last_i = i = offset; \
1003 init_bmlut(&lut, in_len / fp_len, work_mem); \
1004 lut.adapts = adapts + 1; \
1011 #define BM_ENCODE_STAT(_msg_) do { \
1012 size_t c = lut.collisions; \
1013 BM_LOG(1, "%s: in: %llu, out: %llu, lut.collisions: %llu (eff. bits: %.3f) " \
1014 "thresh: %llu), lut.probes: %llu (%.3f/lu)\n", _msg_, (Llu)in_len, \
1015 (Llu)*out_len_p, (Llu)c, \
1016 c ? log((double)nfps * scan_len / c) / log(2) : sizeof(size_t) * 8., \
1017 (Llu)collision_thresh, (Llu)lut.probes, \
1018 (double)lut.probes / scan_len); \
1022 #define BM_ENCODE_BODY(_init_hash_, _update_hash_, _randomize_) \
1023 size_t i = offset, last_i = i, end_i = in_len - fp_len; \
1024 size_t boundary = i, scan_len = end_i - offset; \
1025 size_t nfps, hash, pos, collision_thresh; \
1026 Byte *in = (Byte *) src, *out = (Byte *) dst; \
1027 Byte *ip = in, *last_ip = ip, *in_end = in + in_len; \
1028 Byte *op = out, *out_end; \
1029 BmLut lut = { 0, 0, 0, 0, NULL }; \
1030 BmLutEntry *entry = NULL; \
1032 BM_CHECK(fp_len > 0); \
1033 nfps = in_len / fp_len; \
1034 collision_thresh = s_collision_thresh ? s_collision_thresh \
1035 : scan_len / 1e9 * nfps + 8; \
1036 if (in_len <= offset + fp_len) BM_ENCODE_PASS; \
1038 init_bmlut(&lut, nfps, work_mem); \
1042 out_end = op + (*out_len_p < in_len ? *out_len_p : in_len); \
1044 for (; i <= end_i; ++i) { \
1046 BM_LOOKUP(lut, hash, entry); \
1049 if (pos != BM_NPOS) { \
1050 Byte *ip0 = in + pos, *cp = in + i, *cp0 = cp; \
1051 Byte *ip1 = ip0 + fp_len, *cp1 = cp0 + fp_len; \
1053 if (memcmp(ip0, cp0, fp_len) == 0) { \
1057 for (ip = ip0; ip > in && cp > last_ip && \
1058 mlen < fp_len - 1 && *--ip == *--cp; ++mlen); \
1060 BM_ENCODE_OUTPUT(op, last_ip, cp); \
1061 pos = ip0 - mlen - in; \
1064 for (ip = ip1, cp = cp1; cp < in_end && *ip++ == *cp++; ++mlen); \
1065 BM_ENCODE_DELTA(op, last_ip - in, pos, mlen); \
1066 last_ip = cp0 - (ip0 - (in + pos)) + mlen; \
1067 if (last_ip == in_end) break; \
1068 last_i = last_ip - in; \
1070 else BM_HANDLE_COLLISIONS(_randomize_, _init_hash_); \
1073 if ((i - offset) == boundary) { \
1074 if (i <= last_i) BM_LOOKUP(lut, hash, entry); \
1076 entry->hash = hash; \
1078 boundary += fp_len; \
1080 if (i < end_i) hash = _update_hash_; \
1083 BM_ENCODE_FINAL_OUTPUT(op, last_ip, in_end); \
1084 *out_len_p = op - out; \
1085 BM_ENCODE_STAT("success"); \
1090 if (*out_len_p > in_len) BM_ENCODE_PASS; \
1091 BM_ENCODE_STAT("tip: make output buffer at least input length + 1"); \
1092 return BMZ_E_OUTPUT_OVERRUN
1097 size_t offset,
size_t fp_len,
void *work_mem,
1098 size_t b,
size_t m) {
1101 pow_n =
pow_mod(b, fp_len, m),
1108 size_t *out_len_p,
size_t offset,
size_t fp_len,
1109 void *work_mem,
size_t b1,
size_t b2,
1110 size_t m1,
size_t m2) {
1111 size_t pow_n_b1, pow_n_b2;
1116 pow_n_b1, pow_n_b2, b1, b2, m1, m2),
1123 size_t *out_len_p,
size_t offset,
size_t fp_len,
1124 void *work_mem,
size_t b1,
size_t b2) {
1125 size_t pow_n_b1, pow_n_b2;
1130 pow_n_b1, pow_n_b2, b1, b2),
1137 size_t offset,
size_t fp_len,
void *work_mem,
size_t b) {
1148 size_t *out_len_p,
size_t offset,
size_t fp_len,
1149 void *work_mem,
size_t b1,
size_t b2) {
1150 size_t pow_n_b1, pow_n_b2;
1155 pow_n_b1, pow_n_b2, b1, b2),
1161 #define BM_LZ_MAX(_len_) ((_len_) / 16 + 64 + 3)
1181 return bm_worklen > lz_worklen ? bm_worklen : lz_worklen;
1196 #define BMZ_PACK_BODY(_bm_pack_) \
1197 size_t tlen = in_len + 1; \
1198 Byte *dst = (Byte *)work_mem; \
1199 Byte *aux_mem = dst + tlen; \
1200 Byte *work_mem_aligned = BM_ALIGN(aux_mem, 8); \
1210 if (ret != BMZ_E_OK) return ret; \
1211 return bmz_lz_pack(dst, tlen, out, out_len_p, work_mem_aligned)
1215 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem,
1216 size_t b,
size_t m) {
1218 offset, fp_len, work_mem_aligned, b, m));
1223 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem,
1224 size_t b1,
size_t b2,
size_t m1,
size_t m2) {
1226 offset, fp_len, work_mem_aligned, b1, b2, m1, m2));
1231 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem,
1232 size_t b1,
size_t b2) {
1234 offset, fp_len, work_mem_aligned, b1, b2));
1239 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem,
1242 offset, fp_len, work_mem_aligned, b));
1247 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem,
1248 size_t b1,
size_t b2) {
1250 offset, fp_len, work_mem_aligned, b1, b2));
1254 bmz_pack(
const void *in,
size_t in_len,
void *out,
size_t *out_len_p,
1255 size_t offset,
size_t fp_len,
unsigned flags,
void *work_mem) {
1256 switch (flags >> 24) {
1258 return bmz_pack_mod(in, in_len, out, out_len_p, offset, fp_len, flags,
1268 return bmz_pack_mask(in, in_len, out, out_len_p, offset, fp_len, flags,
1274 BM_DIE(
"unknown hash algorithm: %u", (flags >> 24));
1280 bmz_unpack(
const void *in,
size_t in_len,
void *out,
size_t *out_len_p,
1283 size_t tlen = *out_len_p + 1;
1292 #define BM_DECODE_POS(_cpos_, _n_) do { \
1293 UInt64 _ipos = _cpos_; \
1294 int w = BM_INT_WIDTH(_ipos); \
1302 _n_ = (*ip++ << 8); \
1306 _n_ = (*ip++ << 16); \
1307 _n_ |= (*ip++ << 8); \
1311 _n_ = (*ip++ << 24); \
1312 _n_ |= (*ip++ << 16); \
1313 _n_ |= (*ip++ << 8); \
1317 _n_ = ((UInt64)*ip++ << 32); \
1318 _n_ |= (*ip++ << 24); \
1319 _n_ |= (*ip++ << 16); \
1320 _n_ |= (*ip++ << 8); \
1324 _n_ = ((UInt64)*ip++ << 40); \
1325 _n_ |= ((UInt64)*ip++ << 32); \
1326 _n_ |= (*ip++ << 24); \
1327 _n_ |= (*ip++ << 16); \
1328 _n_ |= (*ip++ << 8); \
1331 BM_DIE("%s", "256TB ought to be enough for anyone!"); \
1335 #define BM_DECODE_LEN(_n_) BM_DECODE_VINT(_n_)
1340 Byte *ip = in, *last_ip = ip + 1, *op = out, *cp;
1341 Byte *in_end = ip + in_len, *out_end = op + *out_len_p;
1345 memcpy(out, ip, --in_len);
1346 *out_len_p = in_len;
1350 while (ip < in_end) {
1352 UInt64 len = ip - last_ip, pos = 0;
1356 memcpy(op, last_ip, len);
1374 while (len--) *op++ = *cp++;
1379 remains = in_end - last_ip;
1381 memcpy(op, last_ip, remains);
1382 *out_len_p = op - out + remains;
1387 *out_len_p = op - out;
1391 *out_len_p = op - out;
1397 Byte *in = (
Byte *)src, *ip = in, *in_end = ip + in_len;
1398 UInt64 pos = 0, len, cpos = 0, tot_pte_sz = 0, tot_ptr_sz = 0, nptrs = 0;
1404 fwrite(ip, 1, in_end - ip, stdout);
1408 while (ip < in_end) {
1418 (
unsigned long long)pos, (
unsigned long long)len);
1421 tot_ptr_sz += ip - ip0;
1435 BM_LOG(1,
"%llu pointers, avg pointee size: %.3f, avg pointer size: %.3f\n",
1436 (
unsigned long long)nptrs, (
double)tot_pte_sz / nptrs,
1437 (
double)tot_ptr_sz / nptrs);
1446 int ret = lzo_init();
1451 bmz_lz_pack(
const void *in,
size_t in_len,
void *out,
size_t *out_len_p,
1453 lzo_uint olen = *out_len_p;
1454 int ret = lzo1x_1_compress((
Byte *)in, in_len, (
Byte *)out, &olen, work_mem);
1461 return LZO1X_MEM_COMPRESS;
1466 lzo_uint olen = *out_len_p;
1467 int ret = lzo1x_decompress((
Byte *)in, in_len, (
Byte *)out, &olen, NULL);
1474 return lzo_adler32(1, (
Byte *)in, in_len);
1479 return lzo_adler32(s, (
Byte *)in, in_len);
int bmz_pack(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem)
Perform bmz compression.
int bmz_bm_pack_mod(const void *src, size_t in_len, void *dst, size_t *out_len_p, size_t offset, size_t fp_len, void *work_mem, size_t b, size_t m)
static void builtin_out(const char *buf, size_t len)
int bmz_bm_pack_mask(const void *src, size_t in_len, void *dst, size_t *out_len_p, size_t offset, size_t fp_len, void *work_mem, size_t b)
static UInt32 pow_mask32(UInt32 x, UInt32 n, UInt32 m)
#define BM_HASH_BENCH_BODY(_init_hash_, _update_hash_)
static void init_bmlut(BmLut *table, size_t n, void *work_mem)
unsigned bmz_update_checksum(unsigned s, const void *in, size_t in_len)
int bmz_set_collision_thresh(int thresh)
int bmz_bm_pack_mask32x2(const void *src, size_t in_len, void *dst, size_t *out_len_p, size_t offset, size_t fp_len, void *work_mem, size_t b1, size_t b2)
static UInt32 r_hash_mask16x2(const Byte *buf, size_t len, UInt32 b1, UInt32 b2)
static UInt64 pow_mod(UInt64 x, UInt64 n, UInt64 m)
void bmz_bench_lut_mod(const void *src, size_t in_len, size_t fp_len, void *work_mem, size_t b, size_t m)
int bmz_check_hash_mask32x2(const void *src, size_t in_len, size_t fp_len, size_t b1, size_t b2)
static Int64 update_hash_mod(Int64 h, Byte in, Byte out, Int64 pow_n, Int64 b, Int64 m)
int bmz_bm_pack_mod16x2(const void *src, size_t in_len, void *dst, size_t *out_len_p, size_t offset, size_t fp_len, void *work_mem, size_t b1, size_t b2, size_t m1, size_t m2)
static BmzOutProc s_out_proc
size_t bmz_bm_pack_worklen(size_t in_len, size_t fp_len)
#define BMZ_E_OUTPUT_OVERRUN
#define BM_HASH_CHECK_BODY(_init_hash_, _rehash_, _update_hash_)
static size_t bmz_pack_auxlen(size_t in_len, size_t fp_len)
static UInt64 r_hash_mask(const Byte *buf, size_t len, UInt64 b, UInt64 m)
#define R_HASH_MASK_BODY(int_type)
size_t bmz_hash_mod(const void *in, size_t in_len, size_t b, size_t m)
static UInt64 r_hash_mask32x2(const Byte *buf, size_t len, UInt64 b1, UInt64 b2)
#define BM_ENCODE_BODY(_init_hash_, _update_hash_, _randomize_)
size_t bmz_lz_pack_worklen(size_t in_len)
int bmz_pack_mask32x2(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem, size_t b1, size_t b2)
size_t bmz_hash_mask(const void *in, size_t in_len, size_t b)
int bmz_set_verbosity(int verbosity)
Set the verbosity of library for testing and debugging.
static UInt32 update_hash_mask16x2(UInt32 h, int in, int out, UInt32 pow1, UInt32 pow2, UInt32 b1, UInt32 b2)
int bmz_pack_mask16x2(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem, size_t b1, size_t b2)
int bmz_check_hash_mod16x2(const void *src, size_t in_len, size_t fp_len, size_t b1, size_t b2, size_t m1, size_t m2)
static size_t random_prime(size_t excluded)
void bmz_bench_hash_mod(const void *src, size_t in_len, size_t fp_len)
static Int32 update_hash_mod32(Int32 h, Byte in, Byte out, Int32 pow_n, Int32 b, Int32 m)
static UInt32 r_hash_mod32(const Byte *buf, size_t len, UInt32 b, UInt32 m)
size_t bmz_hash_mask16x2(const void *in, size_t in_len, size_t b1, size_t b2)
static UInt64 r_hash_mod(const Byte *buf, size_t len, size_t b, UInt64 m)
static UInt64 pow_mask(UInt64 x, UInt64 n, UInt64 m)
#define UPDATE_HASH_MASK_BODY
static UInt64 update_hash_mask32x2(UInt64 h, int in, int out, UInt64 pow1, UInt64 pow2, UInt64 b1, UInt64 b2)
int bmz_lz_pack(const void *in, size_t in_len, void *out, size_t *out_len_p, void *work_mem)
#define BMZ_HASH_MASK16X2
void(* BmzDieProc)(const char *msg) HT_NORETURN
Signature of the fatal procedure.
size_t bmz_hash_mask32x2(const void *in, size_t in_len, size_t b1, size_t b2)
int bmz_check_hash_mod(const void *src, size_t in_len, size_t fp_len, size_t b, size_t m)
#define BMZ_E_INPUT_OVERRUN
int bmz_init()
Perform bmz initialization only needs to be called once, mostly for sanity checks.
void bmz_bench_hash_mask16x2(const void *src, size_t in_len, size_t fp_len)
void bmz_bench_lut_mask16x2(const void *src, size_t in_len, size_t fp_len, void *work_mem, size_t b1, size_t b2)
int bmz_unpack(const void *in, size_t in_len, void *out, size_t *out_len_p, void *work_mem)
Perform bmz decompression.
static UInt32 r_hash_mod16x2(const Byte *buf, size_t len, UInt32 b1, UInt32 b2, UInt32 m1, UInt32 m2)
int bmz_check_hash_mask(const void *src, size_t in_len, size_t fp_len, size_t b)
void bmz_bench_lut_mask(const void *src, size_t in_len, size_t fp_len, void *work_mem, size_t b)
static UInt32 update_hash_mod16x2(UInt32 h, int in, int out, UInt32 pow1, UInt32 pow2, UInt32 b1, UInt32 b2, UInt32 m1, UInt32 m2)
#define POW_MASK_BODY(_pow_fun_, _int_type_)
#define BM_DECODE_LEN(_n_)
size_t bmz_pack_buflen(size_t in_len)
Compute bmz compression output buffer length.
#define POW_MOD_BODY(_pow_fun_, _int_type_)
size_t bmz_unpack_worklen(size_t out_len)
Return size of work memory for bmz decompression.
BmzOutProc bmz_set_out_proc(BmzOutProc proc)
Set messaging/logging procedure.
#define BM_DIE(_fmt_,...)
static HT_NORETURN void builtin_die(const char *msg)
int bmz_pack_mod(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem, size_t b, size_t m)
int bmz_lz_unpack(const void *in, size_t in_len, void *out, size_t *out_len_p)
static UInt32 pow_mod32(UInt32 x, UInt32 n, UInt32 m)
void bmz_bench_lut_mask32x2(const void *src, size_t in_len, size_t fp_len, void *work_mem, size_t b1, size_t b2)
int bmz_bm_pack_mask16x2(const void *src, size_t in_len, void *dst, size_t *out_len_p, size_t offset, size_t fp_len, void *work_mem, size_t b1, size_t b2)
#define BMZ_PACK_BODY(_bm_pack_)
void bmz_bench_hash_mod16x2(const void *src, size_t in_len, size_t fp_len)
#define BM_LOG(_level_, _fmt_,...)
#define R_HASH_MOD_BODY(_int_type_)
#define UPDATE_HASH_MOD_BODY
int bmz_pack_mod16x2(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem, size_t b1, size_t b2, size_t m1, size_t m2)
#define BM_DECODE_POS(_cpos_, _n_)
static UInt32 update_hash_mask32(UInt32 h, int in, int out, UInt32 pow_n, UInt32 b, UInt32 m)
#define BMZ_HASH_MASK32X2
void bmz_bench_lut_mod16x2(const void *src, size_t in_len, size_t fp_len, void *work_mem, size_t b1, size_t b2, size_t m1, size_t m2)
static UInt64 update_hash_mask(UInt64 h, int in, int out, UInt64 pow_n, UInt64 b, UInt64 m)
unsigned bmz_checksum(const void *in, size_t in_len)
A fast checksum (adler32) function that might be useful.
int bmz_bm_unpack(const void *src, size_t in_len, void *dst, size_t *out_len_p)
void(* BmzOutProc)(const char *msg, size_t len)
Signature of the messaging/logging procedure.
int bmz_pack_mask(const void *in, size_t in_len, void *out, size_t *out_len_p, size_t offset, size_t fp_len, unsigned flags, void *work_mem, size_t b)
int bmz_bm_dump(const void *src, size_t in_len)
void bmz_bench_hash(const void *in, size_t in_len, unsigned type)
void bmz_bench_hash_mask(const void *src, size_t in_len, size_t fp_len)
static BmzDieProc s_die_proc
#define BM_LUT_BENCH_BODY(_init_hash_, _update_hash_)
static size_t bm_lut_size(size_t n)
static UInt32 r_hash_mask32(const Byte *buf, size_t len, UInt32 b, UInt32 m)
void bmz_bench_hash_mask32x2(const void *src, size_t in_len, size_t fp_len)
size_t bmz_hash_mod16x2(const void *in, size_t in_len, size_t b1, size_t b2, size_t m1, size_t m2)
size_t bmz_pack_worklen(size_t in_len, size_t fp_len)
Return size of work memory for bmz compression.
int bmz_check_hash_mask16x2(const void *src, size_t in_len, size_t fp_len, size_t b1, size_t b2)
static size_t s_collision_thresh