2 Copyright 2008 Kristian Nielsen
4 This file is part of BeeDB.
6 Foobar is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
11 Foobar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Foobar. If not, see <http://www.gnu.org/licenses/>.
24 Version of packed_mask.h that uses uint64_t throughout, in an attempt to
25 avoid sign extension overhead.
29 ToDo: Need big-endian version of this, that will store from high bit down,
30 so that the trailing bytes of any final partial word will be at the end.
33 struct pack_ptr_unsigned
{
36 Should be 64-bit aligned, and must be readable as 64-bit words, even
37 if trailing bits are undefined (ie. for a 9-byte buffer we will read
38 16 bytes, though we will only actually look at the first 9).
41 /* Current word, equal to b[i-1]. */
43 /* Index of next word. */
45 /* Bit position in current word. */
48 /* Methods, all inline. */
49 uint64_t used() { return i
; }
51 pack_ptr_unsigned(uint64_t *base
);
52 /* Read the next NUMBITS bits, updating pointer. */
53 uint64_t getbits(uint64_t numbits
);
55 Put value DATA of size NUMBITS into current position.
57 Assumes that DATA fits in a word of size NUMBITS, so we don't have to
60 ToDo: We can have a more efficient version of this that assumes the data
61 before the write is zero.
63 Then there is no need to mask off the destination, and we don't have to
64 write into the destination array except when moving to the next word (in
65 this case we need a flush() method to be called at the end).
67 We might want to have another struct for this, as we will need another
68 constructor to initialise v=0, and we won't mix well with reading anyway.
70 void putbits(uint64_t numbits
, uint64_t data
);
71 /* Read/store 64-bit value packed with 3 length bits. */
73 void pack1(uint64_t v
);
75 void pack2(uint64_t v
);
77 void pack3(uint64_t v
);
79 void pack4(uint64_t v
);
83 pack_ptr_unsigned::pack_ptr_unsigned(uint64_t *base
)
92 pack_ptr_unsigned::getbits(uint64_t numbits
)
96 if (unlikely(p
>= 64))
99 ToDo: Hm, seems we might be reading one extra word off the end here.
101 May be worthwhile, but needs to be taken into account.
106 Shift by 64 bit is undefined in C.
107 We make the conditional on numbits==64 so that for compile-time known
108 value of numbits the compiler can optimize the conditional away.
109 For numbits < 64 and p = 0, the redundant |= (which is masked away
110 immediately below) is cheaper than an extra conditional.
112 if (likely(!(numbits
== 64 && p
== 0)))
113 r
|= v
<< (numbits
- p
);
115 r
&= (~(uint64_t)0 >> (64 - numbits
));
116 //printf("getbits(%u) -> %lu\n", numbits, (unsigned long)r);
121 pack_ptr_unsigned::putbits(uint64_t numbits
, uint64_t data
)
123 //printf("putbits(%u, %lu)\n", numbits, (unsigned long)data);
124 uint64_t mask
= (~(uint64_t)0 >> (64 - numbits
));
125 v
= (v
& ~(mask
<< p
)) | (data
<< p
);
128 if (unlikely(p
>= 64))
132 if (likely(!(numbits
== 64 && p
== 0)))
134 v
= (v
& (~(uint64_t)0 << p
)) | (data
>> (numbits
- p
));
142 pack_ptr_unsigned::unpack1()
144 uint64_t n
= getbits(3);
145 return getbits(n
*9+1);
149 pack_ptr_unsigned::pack1(uint64_t v
)
152 Compute the 3-bit header counter C, where we store C*9+1 bits.
153 We have C = ((#bits - 1) + 8) / 9 [rounding down].
154 And #bits = 64 - #leading zeroes, and 64 - 1 + 8 == 71.
155 We use |1 to be sure to get at least a size of one bit (__builtin_clzl is
156 undefined for argument of zero).
158 uint64_t bits
= (71 - COUNT_LEADING_ZEROS_64(v
| 1))/9;
160 putbits(bits
*9+1, v
);
164 pack_ptr_unsigned::unpack2()
166 uint64_t n
= getbits(2);
167 return getbits(n
*20+4);
171 pack_ptr_unsigned::pack2(uint64_t v
)
173 uint64_t bits
= (79 - COUNT_LEADING_ZEROS_64(v
| 1))/20;
175 putbits(bits
*20+4, v
);
185 /* ToDo: Only one copy of this table! */
189 #ifndef WORDS_BIGENDIAN
192 } unpack3_table_unsigned
[8]= {
193 #ifdef WORDS_BIGENDIAN
199 /* 5 */ { 10, 1024 },
204 /* 1 */ { 10, 0, 1 },
206 /* 3 */ { 20, 0, 0 },
208 /* 5 */ { 10, 1, 1 },
215 pack_ptr_unsigned::unpack3()
217 uint64_t prefix
= getbits(3);
218 return ( getbits(unpack3_table_unsigned
[prefix
].bits
)
219 #ifndef WORDS_BIGENDIAN
220 << unpack3_table_unsigned
[prefix
].lshift
222 ) | unpack3_table_unsigned
[prefix
].or_value
;
225 static struct { uint64_t tag_bits
; uint64_t data_bits
; uint64_t tag_value
; }
226 pack3_table_unsigned
[64]= {
227 #ifdef WORDS_BIGENDIAN
228 /* 64 */ { 3, 64, 7 },
229 /* 63 */ { 3, 64, 7 },
230 /* 62 */ { 3, 64, 7 },
231 /* 61 */ { 3, 64, 7 },
232 /* 60 */ { 3, 64, 7 },
233 /* 59 */ { 3, 64, 7 },
234 /* 58 */ { 3, 64, 7 },
235 /* 57 */ { 3, 64, 7 },
236 /* 56 */ { 3, 64, 7 },
237 /* 55 */ { 3, 64, 7 },
238 /* 54 */ { 3, 64, 7 },
239 /* 53 */ { 3, 64, 7 },
240 /* 52 */ { 3, 64, 7 },
241 /* 51 */ { 3, 64, 7 },
242 /* 50 */ { 3, 64, 7 },
243 /* 49 */ { 3, 64, 7 },
244 /* 48 */ { 3, 64, 7 },
245 /* 47 */ { 3, 64, 7 },
246 /* 46 */ { 3, 64, 7 },
247 /* 45 */ { 3, 64, 7 },
248 /* 44 */ { 3, 64, 7 },
249 /* 43 */ { 3, 64, 7 },
250 /* 42 */ { 3, 64, 7 },
251 /* 41 */ { 3, 64, 7 },
252 /* 40 */ { 3, 64, 7 },
253 /* 39 */ { 3, 64, 7 },
254 /* 38 */ { 3, 64, 7 },
255 /* 37 */ { 3, 64, 7 },
256 /* 36 */ { 3, 64, 7 },
257 /* 35 */ { 3, 64, 7 },
258 /* 34 */ { 3, 64, 7 },
259 /* 33 */ { 3, 64, 7 },
260 /* 32 */ { 3, 64, 7 },
261 /* 31 */ { 3, 64, 7 },
262 /* 30 */ { 3, 64, 7 },
263 /* 29 */ { 3, 64, 7 },
264 /* 28 */ { 3, 64, 7 },
265 /* 27 */ { 3, 64, 7 },
266 /* 26 */ { 3, 64, 7 },
267 /* 25 */ { 3, 64, 7 },
268 /* 24 */ { 3, 64, 7 },
269 /* 23 */ { 3, 64, 7 },
270 /* 22 */ { 3, 64, 7 },
271 /* 21 */ { 3, 64, 7 },
272 /* 20 */ { 3, 20, 6 },
273 /* 19 */ { 3, 20, 6 },
274 /* 18 */ { 3, 20, 6 },
275 /* 17 */ { 3, 20, 6 },
276 /* 16 */ { 3, 20, 6 },
277 /* 15 */ { 3, 20, 6 },
278 /* 14 */ { 3, 20, 6 },
279 /* 13 */ { 3, 20, 6 },
280 /* 12 */ { 3, 20, 6 },
281 /* 11 */ { 2, 11, 2 },
282 /* 10 */ { 2, 11, 2 },
283 /* 9 */ { 2, 11, 2 },
284 /* 8 */ { 2, 11, 2 },
285 /* 7 */ { 2, 11, 2 },
286 /* 6 */ { 2, 11, 2 },
287 /* 5 */ { 2, 11, 2 },
288 /* 4 */ { 2, 11, 2 },
293 /* 64 */ { 3, 64, 7 },
294 /* 63 */ { 3, 64, 7 },
295 /* 62 */ { 3, 64, 7 },
296 /* 61 */ { 3, 64, 7 },
297 /* 60 */ { 3, 64, 7 },
298 /* 59 */ { 3, 64, 7 },
299 /* 58 */ { 3, 64, 7 },
300 /* 57 */ { 3, 64, 7 },
301 /* 56 */ { 3, 64, 7 },
302 /* 55 */ { 3, 64, 7 },
303 /* 54 */ { 3, 64, 7 },
304 /* 53 */ { 3, 64, 7 },
305 /* 52 */ { 3, 64, 7 },
306 /* 51 */ { 3, 64, 7 },
307 /* 50 */ { 3, 64, 7 },
308 /* 49 */ { 3, 64, 7 },
309 /* 48 */ { 3, 64, 7 },
310 /* 47 */ { 3, 64, 7 },
311 /* 46 */ { 3, 64, 7 },
312 /* 45 */ { 3, 64, 7 },
313 /* 44 */ { 3, 64, 7 },
314 /* 43 */ { 3, 64, 7 },
315 /* 42 */ { 3, 64, 7 },
316 /* 41 */ { 3, 64, 7 },
317 /* 40 */ { 3, 64, 7 },
318 /* 39 */ { 3, 64, 7 },
319 /* 38 */ { 3, 64, 7 },
320 /* 37 */ { 3, 64, 7 },
321 /* 36 */ { 3, 64, 7 },
322 /* 35 */ { 3, 64, 7 },
323 /* 34 */ { 3, 64, 7 },
324 /* 33 */ { 3, 64, 7 },
325 /* 32 */ { 3, 64, 7 },
326 /* 31 */ { 3, 64, 7 },
327 /* 30 */ { 3, 64, 7 },
328 /* 29 */ { 3, 64, 7 },
329 /* 28 */ { 3, 64, 7 },
330 /* 27 */ { 3, 64, 7 },
331 /* 26 */ { 3, 64, 7 },
332 /* 25 */ { 3, 64, 7 },
333 /* 24 */ { 3, 64, 7 },
334 /* 23 */ { 3, 64, 7 },
335 /* 22 */ { 3, 64, 7 },
336 /* 21 */ { 3, 64, 7 },
337 /* 20 */ { 3, 20, 3 },
338 /* 19 */ { 3, 20, 3 },
339 /* 18 */ { 3, 20, 3 },
340 /* 17 */ { 3, 20, 3 },
341 /* 16 */ { 3, 20, 3 },
342 /* 15 */ { 3, 20, 3 },
343 /* 14 */ { 3, 20, 3 },
344 /* 13 */ { 3, 20, 3 },
345 /* 12 */ { 3, 20, 3 },
346 /* 11 */ { 2, 11, 1 },
347 /* 10 */ { 2, 11, 1 },
348 /* 9 */ { 2, 11, 1 },
349 /* 8 */ { 2, 11, 1 },
350 /* 7 */ { 2, 11, 1 },
351 /* 6 */ { 2, 11, 1 },
352 /* 5 */ { 2, 11, 1 },
353 /* 4 */ { 2, 11, 1 },
361 pack_ptr_unsigned::pack3(uint64_t v
)
363 uint64_t bits
= COUNT_LEADING_ZEROS_64(v
| 1);
364 putbits(pack3_table_unsigned
[bits
].tag_bits
, pack3_table_unsigned
[bits
].tag_value
);
365 putbits(pack3_table_unsigned
[bits
].data_bits
, v
);
376 /* ToDo: Only one copy of this table! */
380 #ifndef WORDS_BIGENDIAN
383 } unpack4_table_unsigned
[8]= {
384 #ifdef WORDS_BIGENDIAN
390 /* 5 */ { 15, 32768 },
396 /* 2 */ { 15, 0, 1 },
397 /* 3 */ { 24, 0, 0 },
400 /* 6 */ { 15, 1, 1 },
406 pack_ptr_unsigned::unpack4()
408 uint64_t prefix
= getbits(3);
409 return ( getbits(unpack4_table_unsigned
[prefix
].bits
)
410 #ifndef WORDS_BIGENDIAN
411 << unpack4_table_unsigned
[prefix
].lshift
413 ) | unpack4_table_unsigned
[prefix
].or_value
;
416 static struct { uint64_t tag_bits
; uint64_t data_bits
; uint64_t tag_value
; }
417 pack4_table_unsigned
[64]= {
418 #ifdef WORDS_BIGENDIAN
419 /* 64 */ { 3, 64, 7 },
420 /* 63 */ { 3, 64, 7 },
421 /* 62 */ { 3, 64, 7 },
422 /* 61 */ { 3, 64, 7 },
423 /* 60 */ { 3, 64, 7 },
424 /* 59 */ { 3, 64, 7 },
425 /* 58 */ { 3, 64, 7 },
426 /* 57 */ { 3, 64, 7 },
427 /* 56 */ { 3, 64, 7 },
428 /* 55 */ { 3, 64, 7 },
429 /* 54 */ { 3, 64, 7 },
430 /* 53 */ { 3, 64, 7 },
431 /* 52 */ { 3, 64, 7 },
432 /* 51 */ { 3, 64, 7 },
433 /* 50 */ { 3, 64, 7 },
434 /* 49 */ { 3, 64, 7 },
435 /* 48 */ { 3, 64, 7 },
436 /* 47 */ { 3, 64, 7 },
437 /* 46 */ { 3, 64, 7 },
438 /* 45 */ { 3, 64, 7 },
439 /* 44 */ { 3, 64, 7 },
440 /* 43 */ { 3, 64, 7 },
441 /* 42 */ { 3, 64, 7 },
442 /* 41 */ { 3, 64, 7 },
443 /* 40 */ { 3, 64, 7 },
444 /* 39 */ { 3, 64, 7 },
445 /* 38 */ { 3, 64, 7 },
446 /* 37 */ { 3, 64, 7 },
447 /* 36 */ { 3, 64, 7 },
448 /* 35 */ { 3, 64, 7 },
449 /* 34 */ { 3, 64, 7 },
450 /* 33 */ { 3, 64, 7 },
451 /* 32 */ { 3, 64, 7 },
452 /* 31 */ { 3, 64, 7 },
453 /* 30 */ { 3, 64, 7 },
454 /* 29 */ { 3, 64, 7 },
455 /* 28 */ { 3, 64, 7 },
456 /* 27 */ { 3, 64, 7 },
457 /* 26 */ { 3, 64, 7 },
458 /* 25 */ { 3, 64, 7 },
459 /* 24 */ { 3, 24, 6 },
460 /* 23 */ { 3, 24, 6 },
461 /* 22 */ { 3, 24, 6 },
462 /* 21 */ { 3, 24, 6 },
463 /* 20 */ { 3, 24, 6 },
464 /* 19 */ { 3, 24, 6 },
465 /* 18 */ { 3, 24, 6 },
466 /* 17 */ { 3, 24, 6 },
467 /* 16 */ { 2, 16, 2 },
468 /* 15 */ { 2, 16, 2 },
469 /* 14 */ { 2, 16, 2 },
470 /* 13 */ { 2, 16, 2 },
471 /* 12 */ { 2, 16, 2 },
472 /* 11 */ { 2, 16, 2 },
473 /* 10 */ { 2, 16, 2 },
474 /* 9 */ { 2, 16, 2 },
484 /* 64 */ { 3, 64, 7 },
485 /* 63 */ { 3, 64, 7 },
486 /* 62 */ { 3, 64, 7 },
487 /* 61 */ { 3, 64, 7 },
488 /* 60 */ { 3, 64, 7 },
489 /* 59 */ { 3, 64, 7 },
490 /* 58 */ { 3, 64, 7 },
491 /* 57 */ { 3, 64, 7 },
492 /* 56 */ { 3, 64, 7 },
493 /* 55 */ { 3, 64, 7 },
494 /* 54 */ { 3, 64, 7 },
495 /* 53 */ { 3, 64, 7 },
496 /* 52 */ { 3, 64, 7 },
497 /* 51 */ { 3, 64, 7 },
498 /* 50 */ { 3, 64, 7 },
499 /* 49 */ { 3, 64, 7 },
500 /* 48 */ { 3, 64, 7 },
501 /* 47 */ { 3, 64, 7 },
502 /* 46 */ { 3, 64, 7 },
503 /* 45 */ { 3, 64, 7 },
504 /* 44 */ { 3, 64, 7 },
505 /* 43 */ { 3, 64, 7 },
506 /* 42 */ { 3, 64, 7 },
507 /* 41 */ { 3, 64, 7 },
508 /* 40 */ { 3, 64, 7 },
509 /* 39 */ { 3, 64, 7 },
510 /* 38 */ { 3, 64, 7 },
511 /* 37 */ { 3, 64, 7 },
512 /* 36 */ { 3, 64, 7 },
513 /* 35 */ { 3, 64, 7 },
514 /* 34 */ { 3, 64, 7 },
515 /* 33 */ { 3, 64, 7 },
516 /* 32 */ { 3, 64, 7 },
517 /* 31 */ { 3, 64, 7 },
518 /* 30 */ { 3, 64, 7 },
519 /* 29 */ { 3, 64, 7 },
520 /* 28 */ { 3, 64, 7 },
521 /* 27 */ { 3, 64, 7 },
522 /* 26 */ { 3, 64, 7 },
523 /* 25 */ { 3, 64, 7 },
524 /* 24 */ { 3, 24, 3 },
525 /* 23 */ { 3, 24, 3 },
526 /* 22 */ { 3, 24, 3 },
527 /* 21 */ { 3, 24, 3 },
528 /* 20 */ { 3, 24, 3 },
529 /* 19 */ { 3, 24, 3 },
530 /* 18 */ { 3, 24, 3 },
531 /* 17 */ { 3, 24, 3 },
532 /* 16 */ { 2, 16, 2 },
533 /* 15 */ { 2, 16, 2 },
534 /* 14 */ { 2, 16, 2 },
535 /* 13 */ { 2, 16, 2 },
536 /* 12 */ { 2, 16, 2 },
537 /* 11 */ { 2, 16, 2 },
538 /* 10 */ { 2, 16, 2 },
539 /* 9 */ { 2, 16, 2 },
552 pack_ptr_unsigned::pack4(uint64_t v
)
554 uint64_t bits
= COUNT_LEADING_ZEROS_64(v
| 1);
555 putbits(pack4_table_unsigned
[bits
].tag_bits
, pack4_table_unsigned
[bits
].tag_value
);
556 putbits(pack4_table_unsigned
[bits
].data_bits
, v
);
564 10 xxxxxxxxxxxxxxxxxxxxxx
565 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx