Home | History | Annotate | Download | only in src
      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
     10 void assert ( bool )
     11 {
     12 }
     13 #endif
     14 
     15 //----------------------------------------------------------------------------
     16 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 >
    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 
    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