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