123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- #include "Bitvec.h"
- #include "Random.h"
- #include <assert.h>
- #include <stdio.h>
- #ifndef DEBUG
- #undef assert
- void assert ( bool )
- {
- }
- #endif
- //----------------------------------------------------------------------------
- void printbits ( const void * blob, int len )
- {
- const uint8_t * data = (const uint8_t *)blob;
- printf("[");
- for(int i = 0; i < len; i++)
- {
- unsigned char byte = data[i];
- int hi = (byte >> 4);
- int lo = (byte & 0xF);
- if(hi) printf("%01x",hi);
- else printf(".");
- if(lo) printf("%01x",lo);
- else printf(".");
- if(i != len-1) printf(" ");
- }
- printf("]");
- }
- void printbits2 ( const uint8_t * k, int nbytes )
- {
- printf("[");
- for(int i = nbytes-1; i >= 0; i--)
- {
- uint8_t b = k[i];
- for(int j = 7; j >= 0; j--)
- {
- uint8_t c = (b & (1 << j)) ? '#' : ' ';
- putc(c,stdout);
- }
- }
- printf("]");
- }
- void printhex32 ( const void * blob, int len )
- {
- assert((len & 3) == 0);
- uint32_t * d = (uint32_t*)blob;
- printf("{ ");
- for(int i = 0; i < len/4; i++)
- {
- printf("0x%08x, ",d[i]);
- }
- printf("}");
- }
- void printbytes ( const void * blob, int len )
- {
- uint8_t * d = (uint8_t*)blob;
- printf("{ ");
- for(int i = 0; i < len; i++)
- {
- printf("0x%02x, ",d[i]);
- }
- printf(" };");
- }
- void printbytes2 ( const void * blob, int len )
- {
- uint8_t * d = (uint8_t*)blob;
- for(int i = 0; i < len; i++)
- {
- printf("%02x ",d[i]);
- }
- }
- //-----------------------------------------------------------------------------
- // Bit-level manipulation
- // These two are from the "Bit Twiddling Hacks" webpage
- uint32_t popcount ( uint32_t v )
- {
- v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
- v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
- uint32_t c = ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
- return c;
- }
- uint32_t parity ( uint32_t v )
- {
- v ^= v >> 1;
- v ^= v >> 2;
- v = (v & 0x11111111U) * 0x11111111U;
- return (v >> 28) & 1;
- }
- //-----------------------------------------------------------------------------
- uint32_t getbit ( const void * block, int len, uint32_t bit )
- {
- uint8_t * b = (uint8_t*)block;
- int byte = bit >> 3;
- bit = bit & 0x7;
-
- if(byte < len) return (b[byte] >> bit) & 1;
- return 0;
- }
- uint32_t getbit_wrap ( const void * block, int len, uint32_t bit )
- {
- uint8_t * b = (uint8_t*)block;
- int byte = bit >> 3;
- bit = bit & 0x7;
-
- byte %= len;
-
- return (b[byte] >> bit) & 1;
- }
- void setbit ( void * block, int len, uint32_t bit )
- {
- uint8_t * b = (uint8_t*)block;
- int byte = bit >> 3;
- bit = bit & 0x7;
-
- if(byte < len) b[byte] |= (1 << bit);
- }
- void setbit ( void * block, int len, uint32_t bit, uint32_t val )
- {
- val ? setbit(block,len,bit) : clearbit(block,len,bit);
- }
- void clearbit ( void * block, int len, uint32_t bit )
- {
- uint8_t * b = (uint8_t*)block;
- int byte = bit >> 3;
- bit = bit & 0x7;
-
- if(byte < len) b[byte] &= ~(1 << bit);
- }
- void flipbit ( void * block, int len, uint32_t bit )
- {
- uint8_t * b = (uint8_t*)block;
- int byte = bit >> 3;
- bit = bit & 0x7;
-
- if(byte < len) b[byte] ^= (1 << bit);
- }
- // from the "Bit Twiddling Hacks" webpage
- int countbits ( uint32_t v )
- {
- v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
- v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
- int c = ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
- return c;
- }
- //-----------------------------------------------------------------------------
- void lshift1 ( void * blob, int len, int c )
- {
- int nbits = len*8;
- for(int i = nbits-1; i >= 0; i--)
- {
- setbit(blob,len,i,getbit(blob,len,i-c));
- }
- }
- void lshift8 ( void * blob, int nbytes, int c )
- {
- uint8_t * k = (uint8_t*)blob;
- if(c == 0) return;
- int b = c >> 3;
- c &= 7;
- for(int i = nbytes-1; i >= b; i--)
- {
- k[i] = k[i-b];
- }
- for(int i = b-1; i >= 0; i--)
- {
- k[i] = 0;
- }
- if(c == 0) return;
- for(int i = nbytes-1; i >= 0; i--)
- {
- uint8_t a = k[i];
- uint8_t b = (i == 0) ? 0 : k[i-1];
- k[i] = (a << c) | (b >> (8-c));
- }
- }
- void lshift32 ( void * blob, int len, int c )
- {
- assert((len & 3) == 0);
- int nbytes = len;
- int ndwords = nbytes / 4;
- uint32_t * k = reinterpret_cast<uint32_t*>(blob);
- if(c == 0) return;
- //----------
- int b = c / 32;
- c &= (32-1);
- for(int i = ndwords-1; i >= b; i--)
- {
- k[i] = k[i-b];
- }
- for(int i = b-1; i >= 0; i--)
- {
- k[i] = 0;
- }
- if(c == 0) return;
- for(int i = ndwords-1; i >= 0; i--)
- {
- uint32_t a = k[i];
- uint32_t b = (i == 0) ? 0 : k[i-1];
- k[i] = (a << c) | (b >> (32-c));
- }
- }
- //-----------------------------------------------------------------------------
- void rshift1 ( void * blob, int len, int c )
- {
- int nbits = len*8;
- for(int i = 0; i < nbits; i++)
- {
- setbit(blob,len,i,getbit(blob,len,i+c));
- }
- }
- void rshift8 ( void * blob, int nbytes, int c )
- {
- uint8_t * k = (uint8_t*)blob;
- if(c == 0) return;
- int b = c >> 3;
- c &= 7;
- for(int i = 0; i < nbytes-b; i++)
- {
- k[i] = k[i+b];
- }
- for(int i = nbytes-b; i < nbytes; i++)
- {
- k[i] = 0;
- }
- if(c == 0) return;
- for(int i = 0; i < nbytes; i++)
- {
- uint8_t a = (i == nbytes-1) ? 0 : k[i+1];
- uint8_t b = k[i];
- k[i] = (a << (8-c) ) | (b >> c);
- }
- }
- void rshift32 ( void * blob, int len, int c )
- {
- assert((len & 3) == 0);
- int nbytes = len;
- int ndwords = nbytes / 4;
- uint32_t * k = (uint32_t*)blob;
- //----------
- if(c == 0) return;
- int b = c / 32;
- c &= (32-1);
- for(int i = 0; i < ndwords-b; i++)
- {
- k[i] = k[i+b];
- }
- for(int i = ndwords-b; i < ndwords; i++)
- {
- k[i] = 0;
- }
- if(c == 0) return;
- for(int i = 0; i < ndwords; i++)
- {
- uint32_t a = (i == ndwords-1) ? 0 : k[i+1];
- uint32_t b = k[i];
- k[i] = (a << (32-c) ) | (b >> c);
- }
- }
- //-----------------------------------------------------------------------------
- void lrot1 ( void * blob, int len, int c )
- {
- int nbits = len * 8;
- for(int i = 0; i < c; i++)
- {
- uint32_t bit = getbit(blob,len,nbits-1);
- lshift1(blob,len,1);
- setbit(blob,len,0,bit);
- }
- }
- void lrot8 ( void * blob, int len, int c )
- {
- int nbytes = len;
- uint8_t * k = (uint8_t*)blob;
- if(c == 0) return;
- //----------
- int b = c / 8;
- c &= (8-1);
- for(int j = 0; j < b; j++)
- {
- uint8_t t = k[nbytes-1];
- for(int i = nbytes-1; i > 0; i--)
- {
- k[i] = k[i-1];
- }
- k[0] = t;
- }
- uint8_t t = k[nbytes-1];
- if(c == 0) return;
- for(int i = nbytes-1; i >= 0; i--)
- {
- uint8_t a = k[i];
- uint8_t b = (i == 0) ? t : k[i-1];
- k[i] = (a << c) | (b >> (8-c));
- }
- }
- void lrot32 ( void * blob, int len, int c )
- {
- assert((len & 3) == 0);
- int nbytes = len;
- int ndwords = nbytes/4;
- uint32_t * k = (uint32_t*)blob;
- if(c == 0) return;
- //----------
- int b = c / 32;
- c &= (32-1);
- for(int j = 0; j < b; j++)
- {
- uint32_t t = k[ndwords-1];
- for(int i = ndwords-1; i > 0; i--)
- {
- k[i] = k[i-1];
- }
- k[0] = t;
- }
- uint32_t t = k[ndwords-1];
- if(c == 0) return;
- for(int i = ndwords-1; i >= 0; i--)
- {
- uint32_t a = k[i];
- uint32_t b = (i == 0) ? t : k[i-1];
- k[i] = (a << c) | (b >> (32-c));
- }
- }
- //-----------------------------------------------------------------------------
- void rrot1 ( void * blob, int len, int c )
- {
- int nbits = len * 8;
- for(int i = 0; i < c; i++)
- {
- uint32_t bit = getbit(blob,len,0);
- rshift1(blob,len,1);
- setbit(blob,len,nbits-1,bit);
- }
- }
- void rrot8 ( void * blob, int len, int c )
- {
- int nbytes = len;
- uint8_t * k = (uint8_t*)blob;
- if(c == 0) return;
- //----------
- int b = c / 8;
- c &= (8-1);
- for(int j = 0; j < b; j++)
- {
- uint8_t t = k[0];
- for(int i = 0; i < nbytes-1; i++)
- {
- k[i] = k[i+1];
- }
- k[nbytes-1] = t;
- }
- if(c == 0) return;
- //----------
- uint8_t t = k[0];
- for(int i = 0; i < nbytes; i++)
- {
- uint8_t a = (i == nbytes-1) ? t : k[i+1];
- uint8_t b = k[i];
- k[i] = (a << (8-c)) | (b >> c);
- }
- }
- void rrot32 ( void * blob, int len, int c )
- {
- assert((len & 3) == 0);
- int nbytes = len;
- int ndwords = nbytes/4;
- uint32_t * k = (uint32_t*)blob;
- if(c == 0) return;
- //----------
- int b = c / 32;
- c &= (32-1);
- for(int j = 0; j < b; j++)
- {
- uint32_t t = k[0];
- for(int i = 0; i < ndwords-1; i++)
- {
- k[i] = k[i+1];
- }
- k[ndwords-1] = t;
- }
- if(c == 0) return;
- //----------
- uint32_t t = k[0];
- for(int i = 0; i < ndwords; i++)
- {
- uint32_t a = (i == ndwords-1) ? t : k[i+1];
- uint32_t b = k[i];
- k[i] = (a << (32-c)) | (b >> c);
- }
- }
- //-----------------------------------------------------------------------------
- uint32_t window1 ( void * blob, int len, int start, int count )
- {
- int nbits = len*8;
- start %= nbits;
- uint32_t t = 0;
- for(int i = 0; i < count; i++)
- {
- setbit(&t,sizeof(t),i, getbit_wrap(blob,len,start+i));
- }
- return t;
- }
- uint32_t window8 ( void * blob, int len, int start, int count )
- {
- int nbits = len*8;
- start %= nbits;
- uint32_t t = 0;
- uint8_t * k = (uint8_t*)blob;
- if(count == 0) return 0;
- int c = start & (8-1);
- int d = start / 8;
- for(int i = 0; i < 4; i++)
- {
- int ia = (i + d + 1) % len;
- int ib = (i + d + 0) % len;
- uint32_t a = k[ia];
- uint32_t b = k[ib];
-
- uint32_t m = (a << (8-c)) | (b >> c);
- t |= (m << (8*i));
- }
- t &= ((1 << count)-1);
- return t;
- }
- uint32_t window32 ( void * blob, int len, int start, int count )
- {
- int nbits = len*8;
- start %= nbits;
- assert((len & 3) == 0);
- int ndwords = len / 4;
- uint32_t * k = (uint32_t*)blob;
- if(count == 0) return 0;
- int c = start & (32-1);
- int d = start / 32;
- if(c == 0) return (k[d] & ((1 << count) - 1));
- int ia = (d + 1) % ndwords;
- int ib = (d + 0) % ndwords;
- uint32_t a = k[ia];
- uint32_t b = k[ib];
-
- uint32_t t = (a << (32-c)) | (b >> c);
- t &= ((1 << count)-1);
- return t;
- }
- //-----------------------------------------------------------------------------
- bool test_shift ( void )
- {
- Rand r(1123);
- int nbits = 64;
- int nbytes = nbits / 8;
- int reps = 10000;
- for(int j = 0; j < reps; j++)
- {
- if(j % (reps/10) == 0) printf(".");
- uint64_t a = r.rand_u64();
- uint64_t b;
- for(int i = 0; i < nbits; i++)
- {
- b = a; lshift1 (&b,nbytes,i); assert(b == (a << i));
- b = a; lshift8 (&b,nbytes,i); assert(b == (a << i));
- b = a; lshift32 (&b,nbytes,i); assert(b == (a << i));
- b = a; rshift1 (&b,nbytes,i); assert(b == (a >> i));
- b = a; rshift8 (&b,nbytes,i); assert(b == (a >> i));
- b = a; rshift32 (&b,nbytes,i); assert(b == (a >> i));
- b = a; lrot1 (&b,nbytes,i); assert(b == ROTL64(a,i));
- b = a; lrot8 (&b,nbytes,i); assert(b == ROTL64(a,i));
- b = a; lrot32 (&b,nbytes,i); assert(b == ROTL64(a,i));
- b = a; rrot1 (&b,nbytes,i); assert(b == ROTR64(a,i));
- b = a; rrot8 (&b,nbytes,i); assert(b == ROTR64(a,i));
- b = a; rrot32 (&b,nbytes,i); assert(b == ROTR64(a,i));
- }
- }
- printf("PASS\n");
- return true;
- }
- //-----------------------------------------------------------------------------
- template < int nbits >
- bool test_window2 ( void )
- {
- Rand r(83874);
-
- struct keytype
- {
- uint8_t bytes[nbits/8];
- };
- int nbytes = nbits / 8;
- int reps = 10000;
- for(int j = 0; j < reps; j++)
- {
- if(j % (reps/10) == 0) printf(".");
- keytype k;
- r.rand_p(&k,nbytes);
- for(int start = 0; start < nbits; start++)
- {
- for(int count = 0; count < 32; count++)
- {
- uint32_t a = window1(&k,nbytes,start,count);
- uint32_t b = window8(&k,nbytes,start,count);
- uint32_t c = window(&k,nbytes,start,count);
- assert(a == b);
- assert(a == c);
- }
- }
- }
- printf("PASS %d\n",nbits);
- return true;
- }
- bool test_window ( void )
- {
- Rand r(48402);
-
- int reps = 10000;
- for(int j = 0; j < reps; j++)
- {
- if(j % (reps/10) == 0) printf(".");
- int nbits = 64;
- int nbytes = nbits / 8;
- uint64_t x = r.rand_u64();
- for(int start = 0; start < nbits; start++)
- {
- for(int count = 0; count < 32; count++)
- {
- uint32_t a = (uint32_t)ROTR64(x,start);
- a &= ((1 << count)-1);
-
- uint32_t b = window1 (&x,nbytes,start,count);
- uint32_t c = window8 (&x,nbytes,start,count);
- uint32_t d = window32(&x,nbytes,start,count);
- uint32_t e = window (x,start,count);
- assert(a == b);
- assert(a == c);
- assert(a == d);
- assert(a == e);
- }
- }
- }
- printf("PASS 64\n");
- test_window2<8>();
- test_window2<16>();
- test_window2<24>();
- test_window2<32>();
- test_window2<40>();
- test_window2<48>();
- test_window2<56>();
- test_window2<64>();
- return true;
- }
- //-----------------------------------------------------------------------------
|