blob: 07ac8151a13f71cc3e91f512fa90edabb5ad15f5 [file] [log] [blame]
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +00001#include "Bitvec.h"
2
3#include "Random.h"
4
5#include <assert.h>
6#include <stdio.h>
7
8#ifndef DEBUG
9#undef assert
10void assert ( bool )
11{
12}
13#endif
14
15//----------------------------------------------------------------------------
16
17void printbits ( void * blob, int len )
18{
19 uint8_t * data = (uint8_t*)blob;
20
21 printf("[");
22 for(int i = 0; i < len; i++)
23 {
24 unsigned char byte = data[i];
25
26 int hi = (byte >> 4);
27 int lo = (byte & 0xF);
28
29 if(hi) printf("%01x",hi);
30 else printf(".");
31
32 if(lo) printf("%01x",lo);
33 else printf(".");
34
35 if(i != len-1) printf(" ");
36 }
37 printf("]");
38}
39
40void printbits2 ( uint8_t * k, int nbytes )
41{
42 printf("[");
43
44 for(int i = nbytes-1; i >= 0; i--)
45 {
46 uint8_t b = k[i];
47
48 for(int j = 7; j >= 0; j--)
49 {
50 uint8_t c = (b & (1 << j)) ? '#' : ' ';
51
52 putc(c,stdout);
53 }
54 }
55 printf("]");
56}
57
58void printhex32 ( void * blob, int len )
59{
60 assert((len & 3) == 0);
61
62 uint32_t * d = (uint32_t*)blob;
63
64 printf("{ ");
65
66 for(int i = 0; i < len/4; i++)
67 {
68 printf("0x%08x, ",d[i]);
69 }
70
71 printf("}");
72}
73
74
75//-----------------------------------------------------------------------------
76// Bit-level manipulation
77
78// These are from the "Bit Twiddling Hacks" webpage
79
80uint32_t popcount ( uint32_t v )
81{
82 v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
83 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
84 uint32_t c = ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; // count
85
86 return c;
87}
88
89uint32_t popcount128 ( uint32_t * v )
90{
91 uint32_t c = popcount(v[0]);
92
93 c += popcount(v[1]);
94 c += popcount(v[2]);
95 c += popcount(v[3]);
96
97 return c;
98}
99
100uint32_t parity ( uint32_t v )
101{
102 v ^= v >> 16;
103 v ^= v >> 8;
104 v ^= v >> 4;
105 v &= 0xf;
106
107 return (0x6996 >> v) & 1;
108}
109
110uint64_t parity ( uint64_t v )
111{
112 v ^= v >> 32;
113 v ^= v >> 16;
114 v ^= v >> 8;
115 v ^= v >> 4;
116 v &= 0xf;
117
118 return (0x6996 >> v) & 1;
119}
120
121//-----------------------------------------------------------------------------
122
123uint32_t getbit ( void * block, int len, uint32_t bit )
124{
125 uint8_t * b = (uint8_t*)block;
126
127 int byte = bit >> 3;
128 bit = bit & 0x7;
129
130 if(byte < len) return (b[byte] >> bit) & 1;
131
132 return 0;
133}
134
135uint32_t getbit_wrap ( void * block, int len, uint32_t bit )
136{
137 uint8_t * b = (uint8_t*)block;
138
139 int byte = bit >> 3;
140 bit = bit & 0x7;
141
142 byte %= len;
143
144 return (b[byte] >> bit) & 1;
145}
146
147void setbit ( void * block, int len, uint32_t bit )
148{
149 uint8_t * b = (uint8_t*)block;
150
151 int byte = bit >> 3;
152 bit = bit & 0x7;
153
154 if(byte < len) b[byte] |= (1 << bit);
155}
156
157void setbit ( void * block, int len, uint32_t bit, uint32_t val )
158{
159 val ? setbit(block,len,bit) : clearbit(block,len,bit);
160}
161
162void clearbit ( void * block, int len, uint32_t bit )
163{
164 uint8_t * b = (uint8_t*)block;
165
166 int byte = bit >> 3;
167 bit = bit & 0x7;
168
169 if(byte < len) b[byte] &= ~(1 << bit);
170}
171
172void flipbit ( void * block, int len, uint32_t bit )
173{
174 uint8_t * b = (uint8_t*)block;
175
176 int byte = bit >> 3;
177 bit = bit & 0x7;
178
179 if(byte < len) b[byte] ^= (1 << bit);
180}
181
182//-----------------------------------------------------------------------------
183
184void lshift1 ( void * blob, int len, int c )
185{
186 int nbits = len*8;
187
188 for(int i = nbits-1; i >= 0; i--)
189 {
190 setbit(blob,len,i,getbit(blob,len,i-c));
191 }
192}
193
194
195void lshift8 ( void * blob, int nbytes, int c )
196{
197 uint8_t * k = (uint8_t*)blob;
198
199 if(c == 0) return;
200
201 int b = c >> 3;
202 c &= 7;
203
204 for(int i = nbytes-1; i >= b; i--)
205 {
206 k[i] = k[i-b];
207 }
208
209 for(int i = b-1; i >= 0; i--)
210 {
211 k[i] = 0;
212 }
213
214 if(c == 0) return;
215
216 for(int i = nbytes-1; i >= 0; i--)
217 {
218 uint8_t a = k[i];
219 uint8_t b = (i == 0) ? 0 : k[i-1];
220
221 k[i] = (a << c) | (b >> (8-c));
222 }
223}
224
225void lshift32 ( void * blob, int len, int c )
226{
227 assert((len & 3) == 0);
228
229 int nbytes = len;
230 int ndwords = nbytes / 4;
231
232 uint32_t * k = (uint32_t*)blob;
233
234 if(c == 0) return;
235
236 //----------
237
238 int b = c / 32;
239 c &= (32-1);
240
241 for(int i = ndwords-1; i >= b; i--)
242 {
243 k[i] = k[i-b];
244 }
245
246 for(int i = b-1; i >= 0; i--)
247 {
248 k[i] = 0;
249 }
250
251 if(c == 0) return;
252
253 for(int i = ndwords-1; i >= 0; i--)
254 {
255 uint32_t a = k[i];
256 uint32_t b = (i == 0) ? 0 : k[i-1];
257
258 k[i] = (a << c) | (b >> (32-c));
259 }
260}
261
262//-----------------------------------------------------------------------------
263
264void rshift1 ( void * blob, int len, int c )
265{
266 int nbits = len*8;
267
268 for(int i = 0; i < nbits; i++)
269 {
270 setbit(blob,len,i,getbit(blob,len,i+c));
271 }
272}
273
274void rshift8 ( void * blob, int nbytes, int c )
275{
276 uint8_t * k = (uint8_t*)blob;
277
278 if(c == 0) return;
279
280 int b = c >> 3;
281 c &= 7;
282
283 for(int i = 0; i < nbytes-b; i++)
284 {
285 k[i] = k[i+b];
286 }
287
288 for(int i = nbytes-b; i < nbytes; i++)
289 {
290 k[i] = 0;
291 }
292
293 if(c == 0) return;
294
295 for(int i = 0; i < nbytes; i++)
296 {
297 uint8_t a = (i == nbytes-1) ? 0 : k[i+1];
298 uint8_t b = k[i];
299
300 k[i] = (a << (8-c) ) | (b >> c);
301 }
302}
303
304void rshift32 ( void * blob, int len, int c )
305{
306 assert((len & 3) == 0);
307
308 int nbytes = len;
309 int ndwords = nbytes / 4;
310
311 uint32_t * k = (uint32_t*)blob;
312
313 //----------
314
315 if(c == 0) return;
316
317 int b = c / 32;
318 c &= (32-1);
319
320 for(int i = 0; i < ndwords-b; i++)
321 {
322 k[i] = k[i+b];
323 }
324
325 for(int i = ndwords-b; i < ndwords; i++)
326 {
327 k[i] = 0;
328 }
329
330 if(c == 0) return;
331
332 for(int i = 0; i < ndwords; i++)
333 {
334 uint32_t a = (i == ndwords-1) ? 0 : k[i+1];
335 uint32_t b = k[i];
336
337 k[i] = (a << (32-c) ) | (b >> c);
338 }
339}
340
341//-----------------------------------------------------------------------------
342
343void lrot1 ( void * blob, int len, int c )
344{
345 int nbits = len * 8;
346
347 for(int i = 0; i < c; i++)
348 {
349 uint32_t bit = getbit(blob,len,nbits-1);
350
351 lshift1(blob,len,1);
352
353 setbit(blob,len,0,bit);
354 }
355}
356
357void lrot8 ( void * blob, int len, int c )
358{
359 int nbytes = len;
360
361 uint8_t * k = (uint8_t*)blob;
362
363 if(c == 0) return;
364
365 //----------
366
367 int b = c / 8;
368 c &= (8-1);
369
370 for(int j = 0; j < b; j++)
371 {
372 uint8_t t = k[nbytes-1];
373
374 for(int i = nbytes-1; i > 0; i--)
375 {
376 k[i] = k[i-1];
377 }
378
379 k[0] = t;
380 }
381
382 uint8_t t = k[nbytes-1];
383
384 if(c == 0) return;
385
386 for(int i = nbytes-1; i >= 0; i--)
387 {
388 uint8_t a = k[i];
389 uint8_t b = (i == 0) ? t : k[i-1];
390
391 k[i] = (a << c) | (b >> (8-c));
392 }
393}
394
395void lrot32 ( void * blob, int len, int c )
396{
397 assert((len & 3) == 0);
398
399 int nbytes = len;
400 int ndwords = nbytes/4;
401
402 uint32_t * k = (uint32_t*)blob;
403
404 if(c == 0) return;
405
406 //----------
407
408 int b = c / 32;
409 c &= (32-1);
410
411 for(int j = 0; j < b; j++)
412 {
413 uint32_t t = k[ndwords-1];
414
415 for(int i = ndwords-1; i > 0; i--)
416 {
417 k[i] = k[i-1];
418 }
419
420 k[0] = t;
421 }
422
423 uint32_t t = k[ndwords-1];
424
425 if(c == 0) return;
426
427 for(int i = ndwords-1; i >= 0; i--)
428 {
429 uint32_t a = k[i];
430 uint32_t b = (i == 0) ? t : k[i-1];
431
432 k[i] = (a << c) | (b >> (32-c));
433 }
434}
435
436//-----------------------------------------------------------------------------
437
438void rrot1 ( void * blob, int len, int c )
439{
440 int nbits = len * 8;
441
442 for(int i = 0; i < c; i++)
443 {
444 uint32_t bit = getbit(blob,len,0);
445
446 rshift1(blob,len,1);
447
448 setbit(blob,len,nbits-1,bit);
449 }
450}
451
452void rrot8 ( void * blob, int len, int c )
453{
454 int nbytes = len;
455
456 uint8_t * k = (uint8_t*)blob;
457
458 if(c == 0) return;
459
460 //----------
461
462 int b = c / 8;
463 c &= (8-1);
464
465 for(int j = 0; j < b; j++)
466 {
467 uint8_t t = k[0];
468
469 for(int i = 0; i < nbytes-1; i++)
470 {
471 k[i] = k[i+1];
472 }
473
474 k[nbytes-1] = t;
475 }
476
477 if(c == 0) return;
478
479 //----------
480
481 uint8_t t = k[0];
482
483 for(int i = 0; i < nbytes; i++)
484 {
485 uint8_t a = (i == nbytes-1) ? t : k[i+1];
486 uint8_t b = k[i];
487
488 k[i] = (a << (8-c)) | (b >> c);
489 }
490}
491
492void rrot32 ( void * blob, int len, int c )
493{
494 assert((len & 3) == 0);
495
496 int nbytes = len;
497 int ndwords = nbytes/4;
498
499 uint32_t * k = (uint32_t*)blob;
500
501 if(c == 0) return;
502
503 //----------
504
505 int b = c / 32;
506 c &= (32-1);
507
508 for(int j = 0; j < b; j++)
509 {
510 uint32_t t = k[0];
511
512 for(int i = 0; i < ndwords-1; i++)
513 {
514 k[i] = k[i+1];
515 }
516
517 k[ndwords-1] = t;
518 }
519
520 if(c == 0) return;
521
522 //----------
523
524 uint32_t t = k[0];
525
526 for(int i = 0; i < ndwords; i++)
527 {
528 uint32_t a = (i == ndwords-1) ? t : k[i+1];
529 uint32_t b = k[i];
530
531 k[i] = (a << (32-c)) | (b >> c);
532 }
533}
534
535//-----------------------------------------------------------------------------
536
537uint32_t window1 ( void * blob, int len, int start, int count )
538{
539 int nbits = len*8;
540 start %= nbits;
541
542 uint32_t t = 0;
543
544 for(int i = 0; i < count; i++)
545 {
546 setbit(&t,sizeof(t),i, getbit_wrap(blob,len,start+i));
547 }
548
549 return t;
550}
551
552uint32_t window8 ( void * blob, int len, int start, int count )
553{
554 int nbits = len*8;
555 start %= nbits;
556
557 uint32_t t = 0;
558 uint8_t * k = (uint8_t*)blob;
559
560 if(count == 0) return 0;
561
562 int c = start & (8-1);
563 int d = start / 8;
564
565 for(int i = 0; i < 4; i++)
566 {
567 int ia = (i + d + 1) % len;
568 int ib = (i + d + 0) % len;
569
570 uint32_t a = k[ia];
571 uint32_t b = k[ib];
572
573 uint32_t m = (a << (8-c)) | (b >> c);
574
575 t |= (m << (8*i));
576
577 }
578
579 t &= ((1 << count)-1);
580
581 return t;
582}
583
584uint32_t window32 ( void * blob, int len, int start, int count )
585{
586 int nbits = len*8;
587 start %= nbits;
588
589 assert((len & 3) == 0);
590
591 int ndwords = len / 4;
592
593 uint32_t * k = (uint32_t*)blob;
594
595 if(count == 0) return 0;
596
597 int c = start & (32-1);
598 int d = start / 32;
599
600 if(c == 0) return (k[d] & ((1 << count) - 1));
601
602 int ia = (d + 1) % ndwords;
603 int ib = (d + 0) % ndwords;
604
605 uint32_t a = k[ia];
606 uint32_t b = k[ib];
607
608 uint32_t t = (a << (32-c)) | (b >> c);
609
610 t &= ((1 << count)-1);
611
612 return t;
613}
614
615//-----------------------------------------------------------------------------
616
617bool test_shift ( void )
618{
619 int nbits = 64;
620 int nbytes = nbits / 8;
621 int reps = 10000;
622
623 for(int j = 0; j < reps; j++)
624 {
625 if(j % (reps/10) == 0) printf(".");
626
627 uint64_t a = rand_u64();
628 uint64_t b;
629
630 for(int i = 0; i < nbits; i++)
631 {
632 b = a; lshift1 (&b,nbytes,i); assert(b == (a << i));
633 b = a; lshift8 (&b,nbytes,i); assert(b == (a << i));
634 b = a; lshift32 (&b,nbytes,i); assert(b == (a << i));
635
636 b = a; rshift1 (&b,nbytes,i); assert(b == (a >> i));
637 b = a; rshift8 (&b,nbytes,i); assert(b == (a >> i));
638 b = a; rshift32 (&b,nbytes,i); assert(b == (a >> i));
639
640 b = a; lrot1 (&b,nbytes,i); assert(b == _rotl64(a,i));
641 b = a; lrot8 (&b,nbytes,i); assert(b == _rotl64(a,i));
642 b = a; lrot32 (&b,nbytes,i); assert(b == _rotl64(a,i));
643
644 b = a; rrot1 (&b,nbytes,i); assert(b == _rotr64(a,i));
645 b = a; rrot8 (&b,nbytes,i); assert(b == _rotr64(a,i));
646 b = a; rrot32 (&b,nbytes,i); assert(b == _rotr64(a,i));
647 }
648 }
649
650 printf("PASS\n");
651 return true;
652}
653
654//-----------------------------------------------------------------------------
655
656template < int nbits >
657bool test_window2 ( void )
658{
659 struct keytype
660 {
661 uint8_t bytes[nbits/8];
662 };
663
664 int nbytes = nbits / 8;
665 int reps = 10000;
666
667 for(int j = 0; j < reps; j++)
668 {
669 if(j % (reps/10) == 0) printf(".");
670
671 keytype k;
672
673 rand_p(&k,nbytes);
674
675 for(int start = 0; start < nbits; start++)
676 {
677 for(int count = 0; count < 32; count++)
678 {
679 uint32_t a = window1(&k,nbytes,start,count);
680 uint32_t b = window8(&k,nbytes,start,count);
681 uint32_t c = window(&k,nbytes,start,count);
682
683 assert(a == b);
684 assert(a == c);
685 }
686 }
687 }
688
689 printf("PASS %d\n",nbits);
690
691 return true;
692}
693
694bool test_window ( void )
695{
696 int reps = 10000;
697
698 for(int j = 0; j < reps; j++)
699 {
700 if(j % (reps/10) == 0) printf(".");
701
702 int nbits = 64;
703 int nbytes = nbits / 8;
704
705 uint64_t x = rand_u64();
706
707 for(int start = 0; start < nbits; start++)
708 {
709 for(int count = 0; count < 32; count++)
710 {
711 uint32_t a = (uint32_t)_rotr64(x,start);
712 a &= ((1 << count)-1);
713
714 uint32_t b = window1 (&x,nbytes,start,count);
715 uint32_t c = window8 (&x,nbytes,start,count);
716 uint32_t d = window32(&x,nbytes,start,count);
717 uint32_t e = window (x,start,count);
718
719 assert(a == b);
720 assert(a == c);
721 assert(a == d);
722 assert(a == e);
723 }
724 }
725 }
726
727 printf("PASS 64\n");
728
729 test_window2<8>();
730 test_window2<16>();
731 test_window2<24>();
732 test_window2<32>();
733 test_window2<40>();
734 test_window2<48>();
735 test_window2<56>();
736 test_window2<64>();
737
738 return true;
739}
740
741//-----------------------------------------------------------------------------