1 #include "Bitvec.h"
2
3 #include "Random.h"
4
5 #include <assert.h>
6 #include <stdio.h>
7
8 #ifndef DEBUG
9 #undef assert
assert(bool)10 void assert ( bool )
11 {
12 }
13 #endif
14
15 //----------------------------------------------------------------------------
16
printbits(const void * blob,int len)17 void 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
printbits2(const uint8_t * k,int nbytes)40 void 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
printhex32(const void * blob,int len)58 void 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
printbytes(const void * blob,int len)74 void 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
printbytes2(const void * blob,int len)88 void 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
popcount(uint32_t v)103 uint32_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
parity(uint32_t v)112 uint32_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
getbit(const void * block,int len,uint32_t bit)122 uint32_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
getbit_wrap(const void * block,int len,uint32_t bit)134 uint32_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
setbit(void * block,int len,uint32_t bit)146 void 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
setbit(void * block,int len,uint32_t bit,uint32_t val)156 void setbit ( void * block, int len, uint32_t bit, uint32_t val )
157 {
158 val ? setbit(block,len,bit) : clearbit(block,len,bit);
159 }
160
clearbit(void * block,int len,uint32_t bit)161 void 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
flipbit(void * block,int len,uint32_t bit)171 void 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
countbits(uint32_t v)183 int 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
lshift1(void * blob,int len,int c)194 void 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
lshift8(void * blob,int nbytes,int c)205 void 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
lshift32(void * blob,int len,int c)235 void 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
rshift1(void * blob,int len,int c)274 void 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
rshift8(void * blob,int nbytes,int c)284 void 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
rshift32(void * blob,int len,int c)314 void 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
lrot1(void * blob,int len,int c)353 void 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
lrot8(void * blob,int len,int c)367 void 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
lrot32(void * blob,int len,int c)405 void 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
rrot1(void * blob,int len,int c)448 void 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
rrot8(void * blob,int len,int c)462 void 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
rrot32(void * blob,int len,int c)502 void 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
window1(void * blob,int len,int start,int count)547 uint32_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
window8(void * blob,int len,int start,int count)562 uint32_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
window32(void * blob,int len,int start,int count)594 uint32_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
test_shift(void)627 bool 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
668 template < int nbits >
test_window2(void)669 bool 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
test_window(void)708 bool 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 //-----------------------------------------------------------------------------
758