• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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