blob: 16feaa7578ed109d297e75d10863a61ee54b4cc0 [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
tanjent@gmail.com603c8782011-04-01 08:50:06 +000017void printbits ( const void * blob, int len )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000018{
tanjent@gmail.com603c8782011-04-01 08:50:06 +000019 const uint8_t * data = (const uint8_t *)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000020
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000021 printf("[");
22 for(int i = 0; i < len; i++)
23 {
24 unsigned char byte = data[i];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000025
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000026 int hi = (byte >> 4);
27 int lo = (byte & 0xF);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000028
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000029 if(hi) printf("%01x",hi);
30 else printf(".");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000031
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000032 if(lo) printf("%01x",lo);
33 else printf(".");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000034
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000035 if(i != len-1) printf(" ");
36 }
37 printf("]");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000038}
39
tanjent@gmail.com603c8782011-04-01 08:50:06 +000040void printbits2 ( const uint8_t * k, int nbytes )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000041{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000042 printf("[");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000043
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000044 for(int i = nbytes-1; i >= 0; i--)
45 {
46 uint8_t b = k[i];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000047
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000048 for(int j = 7; j >= 0; j--)
49 {
50 uint8_t c = (b & (1 << j)) ? '#' : ' ';
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000051
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000052 putc(c,stdout);
53 }
54 }
55 printf("]");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000056}
57
tanjent@gmail.com603c8782011-04-01 08:50:06 +000058void printhex32 ( const void * blob, int len )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000059{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000060 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000061
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000062 uint32_t * d = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000063
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000064 printf("{ ");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000065
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000066 for(int i = 0; i < len/4; i++)
67 {
68 printf("0x%08x, ",d[i]);
69 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000070
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000071 printf("}");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +000072}
73
tanjent@gmail.com603c8782011-04-01 08:50:06 +000074void printbytes ( const void * blob, int len )
tanjent@gmail.combabb5532011-02-28 06:03:12 +000075{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000076 uint8_t * d = (uint8_t*)blob;
tanjent@gmail.combabb5532011-02-28 06:03:12 +000077
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000078 printf("{ ");
tanjent@gmail.combabb5532011-02-28 06:03:12 +000079
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000080 for(int i = 0; i < len; i++)
81 {
82 printf("0x%02x, ",d[i]);
83 }
tanjent@gmail.combabb5532011-02-28 06:03:12 +000084
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +000085 printf(" };");
tanjent@gmail.combabb5532011-02-28 06:03:12 +000086}
87
tanjent@gmail.com603c8782011-04-01 08:50:06 +000088void 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
103uint32_t popcount ( uint32_t v )
104{
105 v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
106 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
aappleby@google.comcc592162011-04-08 20:49:43 +0000107 uint32_t c = ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000108
109 return c;
110}
111
112uint32_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
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000120//-----------------------------------------------------------------------------
121
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000122uint32_t getbit ( const void * block, int len, uint32_t bit )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000123{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000124 uint8_t * b = (uint8_t*)block;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000125
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000126 int byte = bit >> 3;
127 bit = bit & 0x7;
128
129 if(byte < len) return (b[byte] >> bit) & 1;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000130
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000131 return 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000132}
133
tanjent@gmail.com603c8782011-04-01 08:50:06 +0000134uint32_t getbit_wrap ( const void * block, int len, uint32_t bit )
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000135{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000136 uint8_t * b = (uint8_t*)block;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000137
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000138 int byte = bit >> 3;
139 bit = bit & 0x7;
140
141 byte %= len;
142
143 return (b[byte] >> bit) & 1;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000144}
145
146void setbit ( void * block, int len, uint32_t bit )
147{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000148 uint8_t * b = (uint8_t*)block;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000149
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000150 int byte = bit >> 3;
151 bit = bit & 0x7;
152
153 if(byte < len) b[byte] |= (1 << bit);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000154}
155
156void setbit ( void * block, int len, uint32_t bit, uint32_t val )
157{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000158 val ? setbit(block,len,bit) : clearbit(block,len,bit);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000159}
160
161void clearbit ( void * block, int len, uint32_t bit )
162{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000163 uint8_t * b = (uint8_t*)block;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000164
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000165 int byte = bit >> 3;
166 bit = bit & 0x7;
167
168 if(byte < len) b[byte] &= ~(1 << bit);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000169}
170
171void flipbit ( void * block, int len, uint32_t bit )
172{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000173 uint8_t * b = (uint8_t*)block;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000174
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000175 int byte = bit >> 3;
176 bit = bit & 0x7;
177
178 if(byte < len) b[byte] ^= (1 << bit);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000179}
180
tanjent@gmail.comf67ce942011-03-14 09:11:18 +0000181// from the "Bit Twiddling Hacks" webpage
182
183int countbits ( uint32_t v )
184{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000185 v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
186 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
aappleby@google.comcc592162011-04-08 20:49:43 +0000187 int c = ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
tanjent@gmail.comf67ce942011-03-14 09:11:18 +0000188
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000189 return c;
tanjent@gmail.comf67ce942011-03-14 09:11:18 +0000190}
191
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000192//-----------------------------------------------------------------------------
193
194void lshift1 ( void * blob, int len, int c )
195{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000196 int nbits = len*8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000197
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000198 for(int i = nbits-1; i >= 0; i--)
199 {
200 setbit(blob,len,i,getbit(blob,len,i-c));
201 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000202}
203
204
205void lshift8 ( void * blob, int nbytes, int c )
206{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000207 uint8_t * k = (uint8_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000208
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000209 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000210
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000211 int b = c >> 3;
212 c &= 7;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000213
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000214 for(int i = nbytes-1; i >= b; i--)
215 {
216 k[i] = k[i-b];
217 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000218
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000219 for(int i = b-1; i >= 0; i--)
220 {
221 k[i] = 0;
222 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000223
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000224 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000225
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000226 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000230
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000231 k[i] = (a << c) | (b >> (8-c));
232 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000233}
234
235void lshift32 ( void * blob, int len, int c )
236{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000237 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000238
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000239 int nbytes = len;
240 int ndwords = nbytes / 4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000241
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000242 uint32_t * k = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000243
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000244 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000245
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000246 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000247
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000248 int b = c / 32;
249 c &= (32-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000250
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000251 for(int i = ndwords-1; i >= b; i--)
252 {
253 k[i] = k[i-b];
254 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000255
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000256 for(int i = b-1; i >= 0; i--)
257 {
258 k[i] = 0;
259 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000260
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000261 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000262
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000263 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000267
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000268 k[i] = (a << c) | (b >> (32-c));
269 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000270}
271
272//-----------------------------------------------------------------------------
273
274void rshift1 ( void * blob, int len, int c )
275{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000276 int nbits = len*8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000277
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000278 for(int i = 0; i < nbits; i++)
279 {
280 setbit(blob,len,i,getbit(blob,len,i+c));
281 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000282}
283
284void rshift8 ( void * blob, int nbytes, int c )
285{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000286 uint8_t * k = (uint8_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000287
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000288 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000289
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000290 int b = c >> 3;
291 c &= 7;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000292
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000293 for(int i = 0; i < nbytes-b; i++)
294 {
295 k[i] = k[i+b];
296 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000297
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000298 for(int i = nbytes-b; i < nbytes; i++)
299 {
300 k[i] = 0;
301 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000302
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000303 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000304
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000305 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000309
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000310 k[i] = (a << (8-c) ) | (b >> c);
311 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000312}
313
314void rshift32 ( void * blob, int len, int c )
315{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000316 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000317
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000318 int nbytes = len;
319 int ndwords = nbytes / 4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000320
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000321 uint32_t * k = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000322
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000323 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000324
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000325 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000326
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000327 int b = c / 32;
328 c &= (32-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000329
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000330 for(int i = 0; i < ndwords-b; i++)
331 {
332 k[i] = k[i+b];
333 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000334
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000335 for(int i = ndwords-b; i < ndwords; i++)
336 {
337 k[i] = 0;
338 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000339
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000340 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000341
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000342 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000346
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000347 k[i] = (a << (32-c) ) | (b >> c);
348 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000349}
350
351//-----------------------------------------------------------------------------
352
353void lrot1 ( void * blob, int len, int c )
354{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000355 int nbits = len * 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000356
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000357 for(int i = 0; i < c; i++)
358 {
359 uint32_t bit = getbit(blob,len,nbits-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000360
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000361 lshift1(blob,len,1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000362
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000363 setbit(blob,len,0,bit);
364 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000365}
366
367void lrot8 ( void * blob, int len, int c )
368{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000369 int nbytes = len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000370
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000371 uint8_t * k = (uint8_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000372
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000373 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000374
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000375 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000376
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000377 int b = c / 8;
378 c &= (8-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000379
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000380 for(int j = 0; j < b; j++)
381 {
382 uint8_t t = k[nbytes-1];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000383
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000384 for(int i = nbytes-1; i > 0; i--)
385 {
386 k[i] = k[i-1];
387 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000388
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000389 k[0] = t;
390 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000391
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000392 uint8_t t = k[nbytes-1];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000393
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000394 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000395
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000396 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000400
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000401 k[i] = (a << c) | (b >> (8-c));
402 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000403}
404
405void lrot32 ( void * blob, int len, int c )
406{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000407 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000408
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000409 int nbytes = len;
410 int ndwords = nbytes/4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000411
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000412 uint32_t * k = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000413
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000414 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000415
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000416 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000417
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000418 int b = c / 32;
419 c &= (32-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000420
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000421 for(int j = 0; j < b; j++)
422 {
423 uint32_t t = k[ndwords-1];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000424
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000425 for(int i = ndwords-1; i > 0; i--)
426 {
427 k[i] = k[i-1];
428 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000429
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000430 k[0] = t;
431 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000432
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000433 uint32_t t = k[ndwords-1];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000434
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000435 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000436
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000437 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000441
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000442 k[i] = (a << c) | (b >> (32-c));
443 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000444}
445
446//-----------------------------------------------------------------------------
447
448void rrot1 ( void * blob, int len, int c )
449{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000450 int nbits = len * 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000451
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000452 for(int i = 0; i < c; i++)
453 {
454 uint32_t bit = getbit(blob,len,0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000455
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000456 rshift1(blob,len,1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000457
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000458 setbit(blob,len,nbits-1,bit);
459 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000460}
461
462void rrot8 ( void * blob, int len, int c )
463{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000464 int nbytes = len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000465
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000466 uint8_t * k = (uint8_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000467
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000468 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000469
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000470 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000471
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000472 int b = c / 8;
473 c &= (8-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000474
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000475 for(int j = 0; j < b; j++)
476 {
477 uint8_t t = k[0];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000478
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000479 for(int i = 0; i < nbytes-1; i++)
480 {
481 k[i] = k[i+1];
482 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000483
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000484 k[nbytes-1] = t;
485 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000486
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000487 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000488
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000489 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000490
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000491 uint8_t t = k[0];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000492
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000493 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000497
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000498 k[i] = (a << (8-c)) | (b >> c);
499 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000500}
501
502void rrot32 ( void * blob, int len, int c )
503{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000504 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000505
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000506 int nbytes = len;
507 int ndwords = nbytes/4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000508
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000509 uint32_t * k = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000510
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000511 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000512
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000513 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000514
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000515 int b = c / 32;
516 c &= (32-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000517
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000518 for(int j = 0; j < b; j++)
519 {
520 uint32_t t = k[0];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000521
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000522 for(int i = 0; i < ndwords-1; i++)
523 {
524 k[i] = k[i+1];
525 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000526
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000527 k[ndwords-1] = t;
528 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000529
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000530 if(c == 0) return;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000531
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000532 //----------
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000533
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000534 uint32_t t = k[0];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000535
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000536 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];
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000540
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000541 k[i] = (a << (32-c)) | (b >> c);
542 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000543}
544
545//-----------------------------------------------------------------------------
546
547uint32_t window1 ( void * blob, int len, int start, int count )
548{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000549 int nbits = len*8;
550 start %= nbits;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000551
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000552 uint32_t t = 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000553
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000554 for(int i = 0; i < count; i++)
555 {
556 setbit(&t,sizeof(t),i, getbit_wrap(blob,len,start+i));
557 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000558
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000559 return t;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000560}
561
562uint32_t window8 ( void * blob, int len, int start, int count )
563{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000564 int nbits = len*8;
565 start %= nbits;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000566
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000567 uint32_t t = 0;
568 uint8_t * k = (uint8_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000569
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000570 if(count == 0) return 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000571
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000572 int c = start & (8-1);
573 int d = start / 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000574
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000575 for(int i = 0; i < 4; i++)
576 {
577 int ia = (i + d + 1) % len;
578 int ib = (i + d + 0) % len;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000579
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000580 uint32_t a = k[ia];
581 uint32_t b = k[ib];
582
583 uint32_t m = (a << (8-c)) | (b >> c);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000584
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000585 t |= (m << (8*i));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000586
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000587 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000588
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000589 t &= ((1 << count)-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000590
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000591 return t;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000592}
593
594uint32_t window32 ( void * blob, int len, int start, int count )
595{
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000596 int nbits = len*8;
597 start %= nbits;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000598
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000599 assert((len & 3) == 0);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000600
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000601 int ndwords = len / 4;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000602
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000603 uint32_t * k = (uint32_t*)blob;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000604
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000605 if(count == 0) return 0;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000606
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000607 int c = start & (32-1);
608 int d = start / 32;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000609
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000610 if(c == 0) return (k[d] & ((1 << count) - 1));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000611
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000612 int ia = (d + 1) % ndwords;
613 int ib = (d + 0) % ndwords;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000614
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000615 uint32_t a = k[ia];
616 uint32_t b = k[ib];
617
618 uint32_t t = (a << (32-c)) | (b >> c);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000619
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000620 t &= ((1 << count)-1);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000621
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000622 return t;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000623}
624
625//-----------------------------------------------------------------------------
626
627bool test_shift ( void )
628{
aappleby@google.com7f20a312011-03-21 20:55:06 +0000629 Rand r(1123);
630
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000631 int nbits = 64;
632 int nbytes = nbits / 8;
633 int reps = 10000;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000634
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000635 for(int j = 0; j < reps; j++)
636 {
637 if(j % (reps/10) == 0) printf(".");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000638
aappleby@google.com7f20a312011-03-21 20:55:06 +0000639 uint64_t a = r.rand_u64();
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000640 uint64_t b;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000641
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000642 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));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000647
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000648 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));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000651
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000652 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));
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000655
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000656 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 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000661
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000662 printf("PASS\n");
663 return true;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000664}
665
666//-----------------------------------------------------------------------------
667
668template < int nbits >
669bool test_window2 ( void )
670{
aappleby@google.com7f20a312011-03-21 20:55:06 +0000671 Rand r(83874);
672
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000673 struct keytype
674 {
675 uint8_t bytes[nbits/8];
676 };
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000677
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000678 int nbytes = nbits / 8;
679 int reps = 10000;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000680
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000681 for(int j = 0; j < reps; j++)
682 {
683 if(j % (reps/10) == 0) printf(".");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000684
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000685 keytype k;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000686
aappleby@google.com7f20a312011-03-21 20:55:06 +0000687 r.rand_p(&k,nbytes);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000688
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000689 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);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000696
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000697 assert(a == b);
698 assert(a == c);
699 }
700 }
701 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000702
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000703 printf("PASS %d\n",nbits);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000704
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000705 return true;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000706}
707
708bool test_window ( void )
709{
aappleby@google.com7f20a312011-03-21 20:55:06 +0000710 Rand r(48402);
711
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000712 int reps = 10000;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000713
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000714 for(int j = 0; j < reps; j++)
715 {
716 if(j % (reps/10) == 0) printf(".");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000717
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000718 int nbits = 64;
719 int nbytes = nbits / 8;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000720
aappleby@google.com7f20a312011-03-21 20:55:06 +0000721 uint64_t x = r.rand_u64();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000722
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000723 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);
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000734
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000735 assert(a == b);
736 assert(a == c);
737 assert(a == d);
738 assert(a == e);
739 }
740 }
741 }
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000742
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000743 printf("PASS 64\n");
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000744
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000745 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>();
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000753
tanjent@gmail.com6ffe0102011-03-19 21:28:26 +0000754 return true;
tanjent@gmail.com7e5c3632010-11-02 00:50:04 +0000755}
756
757//-----------------------------------------------------------------------------