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