Guest User

Untitled

a guest
Aug 29th, 2015
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.27 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #include "util.h"
  5.  
  6. /* This reads Msieve's matrix file format, and writes Msieve's
  7. dependency file format. Some of the I/O code is adapted from Msieve,
  8. due of course to Jason Papadopoulos.
  9.  
  10. The method of solving the system is a recent innovation discovered by
  11. Prasad Raghavendra. You can read about his method and see his paper here:
  12. http://rjlipton.wordpress.com/2012/08/09/a-new-way-to-solve-linear-equations/
  13. */
  14.  
  15. uint32 seed1, seed2; // used for random number generation
  16.  
  17. typedef struct {
  18. uint32* cols; /* The array of occupied columns in this row */
  19. uint32 weight; /* Length of data */
  20. uint32 size; /* Mem alloc'd (should always be >= weight) */
  21. } sparse_row_t;
  22.  
  23. typedef struct {
  24. uint32 nrows, ncols, n_dense_rows, n_sparse_rows;
  25. sparse_row_t* row_list; // A list of the sparse rows
  26. uint32** dense_row_list, dense_row_length;
  27. /* Store the dense rows as bit arrays each (ncols+31)/32 words long */
  28. } matrix_t;
  29.  
  30. void sparse_row_add_entry(sparse_row_t* row, uint32 col) {
  31. // We have to be careful since sparse_row_t.cols is built on the fly
  32. if(row->weight > row->size) {
  33. fprintf(stderr, "...Uh, Houston, we have a problem. "
  34. "There's more data than array holding the data.\n");
  35. exit(-1);
  36. } else if(row->weight == row->size)
  37. row->cols = xrealloc(row->cols, (size_t)((row->size += 5) * sizeof(uint32)));
  38. row->cols[row->weight++] = col;
  39. }
  40.  
  41. void matrix_init(uint32 n_sparse_rows, uint32 n_dense_rows, uint32 dense_row_length,
  42. sparse_row_t** sparse_out, uint32*** dense_out)
  43. {
  44. uint32 i;
  45. sparse_row_t* row_list;
  46. uint32** dense_row_list;
  47.  
  48. printf("calloc sparse row list\n");
  49. row_list = (sparse_row_t*)xcalloc(n_sparse_rows, sizeof(sparse_row_t));
  50. // A list of the sparse rows
  51. for(i = 0; i < n_sparse_rows; i++) {
  52. //printf("calloc one sparse row\n");
  53. row_list[i].cols = (uint32*)xcalloc(20, sizeof(uint32));
  54. row_list[i].size = 20;
  55. row_list[i].weight = 0;
  56. }
  57.  
  58. printf("calloc dense list\n");
  59. dense_row_list = (uint32**)xcalloc(n_dense_rows, sizeof(uint32*));
  60. /* Store the dense rows as bit arrays each (ncols+31)/32 words long */
  61. for(i = 0; i < n_dense_rows; i++) {
  62. //printf("calloc one dense row\n");
  63. dense_row_list[i] = (uint32*)xcalloc(dense_row_length, sizeof(uint32));
  64. }
  65.  
  66. *sparse_out = row_list;
  67. *dense_out = dense_row_list;
  68. }
  69.  
  70. matrix_t* read_matrix(char* file) {
  71. uint32 i, j, k;
  72. uint32 nrows, ncols, n_dense_rows, n_sparse_rows, col_dense_words,
  73. dense_row_length;
  74. FILE* f;
  75. sparse_row_t* row_list;
  76. uint32** dense_row_list;
  77. matrix_t* matrix = (matrix_t*)xcalloc(1, sizeof(matrix_t));
  78.  
  79. printf("Attempting to read matrix from %s\n", file);
  80.  
  81. if((f = fopen(file, "rb")) == NULL) {
  82. fprintf(stderr, "Couldn't open matrix file\n");
  83. exit(-1);
  84. }
  85.  
  86. fread(&nrows, sizeof(uint32), (size_t)1, f);
  87. fread(&n_dense_rows, sizeof(uint32), (size_t)1, f);
  88. fread(&ncols, sizeof(uint32), (size_t)1, f);
  89. col_dense_words = (n_dense_rows + 31) / 32;
  90. n_sparse_rows = nrows - n_dense_rows;
  91. dense_row_length = (ncols + 31) / 32;
  92. printf("Matrix is %u x %u with %u dense rows\n", nrows, ncols, n_dense_rows);
  93.  
  94. matrix_init(n_sparse_rows, n_dense_rows, dense_row_length,
  95. &row_list, &dense_row_list);
  96.  
  97. for(i = 0; i < ncols; i++) {
  98. uint32 sparse_count, word, d_row; // word/d_row used in second loop
  99.  
  100. fread(&sparse_count, sizeof(uint32), (size_t)1, f);
  101.  
  102. for(j = 0; j < sparse_count; j++) {
  103. // read in the sparse row data
  104. uint32 row_entry;
  105. sparse_row_t* row;
  106.  
  107. fread(&row_entry, sizeof(uint32), (size_t)1, f);
  108. // Read in which row has an entry in this col
  109.  
  110. row = row_list + (row_entry - n_dense_rows);
  111. // Find the data for that row (as a pointer)
  112.  
  113. sparse_row_add_entry(row, i);
  114. // Add this col (i) to that row's data
  115. }
  116.  
  117. for(j = 0; j < col_dense_words - 1; j++) {
  118. // now read in the dense row data
  119. // do the last word separately
  120. fread(&word, sizeof(uint32), (size_t)1, f);
  121.  
  122. for(k = 0; k < 32; k++) {
  123. //uint32* row = dense_row_list[32*j + k];
  124. //uint32 row_word = i / 32; // i is the column...
  125. //uint32 word_bit = i % 32;
  126. //row[row_word] |= ((word >> k) & 1) << word_bit;
  127. dense_row_list[(j << 5) + k][i >> 5] |= (word & 1) << (i & 0x1f);
  128. word >>= 1;
  129. /* Take the kth bit of the read-in word (which
  130. is the 32*j+k'th row's entry in this col) and set
  131. it as the i'th bit of the row's bitfield...
  132. I would really appreciate if someone double
  133. checked this... */
  134. }
  135. }
  136.  
  137. fread(&word, sizeof(uint32), (size_t)1, f);
  138. d_row = n_dense_rows & 0x1f; if(d_row == 0) d_row = 32;
  139. for(k = 0; k < d_row; k++) {
  140. //uint32* row = dense_row_list[32*j + k];
  141. //uint32 row_word = i / 32; // i is the column...
  142. //uint32 word_bit = i % 32;
  143. //row[row_word] |= (word & 1) << word_bit;
  144. dense_row_list[(j << 5) + k][i >> 5] |= (word & 1) << (i & 0x1f);
  145. word >>= 1;
  146. }
  147. }
  148. fclose(f);
  149. matrix->nrows = nrows; // too lazy to redo the above code
  150. matrix->ncols = ncols;
  151. matrix->n_dense_rows = n_dense_rows;
  152. matrix->n_sparse_rows = n_sparse_rows;
  153. matrix->dense_row_length = dense_row_length;
  154. matrix->row_list = row_list;
  155. matrix->dense_row_list = dense_row_list;
  156. return matrix;
  157. }
  158.  
  159. typedef struct {
  160. uint32* coeffs; /* bit field */
  161. uint32 len;
  162. } vector_t;
  163.  
  164. typedef struct {
  165. vector_t* set;
  166. uint32 len, len_a;
  167. } set_t;
  168.  
  169. vector_t* vector_init(uint32 n, uint32 rand_fill) {
  170. vector_t* vec = (vector_t*)xcalloc(1, sizeof(vector_t));
  171. uint32 i;
  172. vec->len = (n + 31) / 32;
  173. //printf("calloc one vector (rand: %u)\n", rand_fill);
  174. vec->coeffs = (uint32*)xcalloc(vec->len, sizeof(uint32));
  175. if(rand_fill)
  176. for(i = 0; i < vec->len; i++)
  177. vec->coeffs[i] = get_rand(&seed1, &seed2);
  178. return vec;
  179. }
  180.  
  181. void vector_free(vector_t* v) {
  182. free(v->coeffs);
  183. }
  184.  
  185. set_t* set_init(uint32 N) {
  186. set_t* set = (set_t*)xcalloc(1, sizeof(set_t));
  187. set->len = 0;
  188. set->len_a = 1000;
  189. printf("calloc a set\n");
  190. set->set = (vector_t*)xcalloc(set->len_a, sizeof(vector_t));
  191. return set;
  192. }
  193.  
  194. void set_free(set_t* set) {
  195. vector_t* v;
  196. for(v = set->set; v < set->set+set->len; v++) vector_free(v);
  197. free(set->set);
  198. }
  199.  
  200. void add_vec_to_set(vector_t* v, set_t* s) {
  201. /* We're supposed to check for duplicates, however that would be an incredibly
  202. monstrous task, and given the size of these vectors, I think the chance of there
  203. being a duplicate is *incredibly* low, like N*2^(-n) with n > 1e5. */
  204. if(s->len > s->len_a) {
  205. fprintf(stderr, "Mem alloc error (adding vector to set)\n");
  206. exit(-1);
  207. } else if(s->len == s->len_a) {
  208. uint32 old = s->len_a;
  209. s->len_a += 8000;
  210. printf("Reallocating a set from %lu KB to %lu KB\n", (old*sizeof(vector_t))/1000, (s->len_a*sizeof(vector_t))/1000);
  211. s->set = (vector_t*)xrealloc(s->set, (size_t)((s->len_a) * sizeof(vector_t)));
  212. }
  213. s->set[s->len++] = *v;
  214. }
  215.  
  216. uint32 dense_satisfies(uint32* dense_row, uint32 row_length, vector_t* vec) {
  217. /* The bit parity method comes from (and is explained in) this awesome page:
  218. http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel */
  219. uint32 i; uint8 out = 0;
  220. //printf("Testing a dense row... row length: %u vec length: %u\n",
  221. // row_length, vec->len);
  222. for(i = 0; i < row_length; i++) { // dot product the two bit fields
  223. uint32 word = dense_row[i] & vec->coeffs[i];
  224. // count the 1s in the word, see comment above
  225. word ^= word >> 16;
  226. word ^= word >> 8;
  227. word ^= word >> 4;
  228. word &= 0xf;
  229. out ^= (0x6996 >> word) & 1;
  230. }
  231. return (uint32)!out;
  232. }
  233.  
  234. uint32 sparse_satisfies(sparse_row_t* row, vector_t* vec) {
  235. uint32 i; uint8 out = 0;
  236. for(i = 0; i < row->weight; i++) {
  237. uint32 bit = row->cols[i];
  238. out ^= vec->coeffs[bit >> 5] >> (bit & 0xff);
  239. }
  240. return (uint32)!out;
  241. }
  242.  
  243. set_t* recombine(set_t* T, uint32 N, uint32 n) {
  244. printf("Recombination: T.len is %u, ratio good vectors = %f\n", T->len, (double)T->len/N);
  245. uint32 i, j;
  246. vector_t* vec, *v1, *v2, *v3;
  247. set_t* S = set_init(N);
  248. for(i = 0; i < N; i++) {
  249. v1 = T->set + (get_rand(&seed1, &seed2) % T->len);
  250. v2 = T->set + (seed2 % T->len);
  251. v3 = T->set + (get_rand(&seed1, &seed2) % T->len);
  252. vec = vector_init(n, 0);
  253. for(j = 0; j < vec->len; j++) // sum the three vectors
  254. vec->coeffs[j] = v1->coeffs[j] ^ v2->coeffs[j] ^ v3->coeffs[j];
  255. add_vec_to_set(vec, S);
  256. }
  257. return S;
  258. }
  259.  
  260. set_t Raghavendra(matrix_t* mat) {
  261. /* The mem use is rather high, but... (m rows, n columns)*/
  262. matrix_t m = *mat;
  263. uint32 N = (uint32)(0.45 * m.ncols), i, j;
  264. set_t* S = set_init(N);
  265. printf("Matrix is %u x %u with %u dense rows\n", m.nrows, m.ncols, m.n_dense_rows);
  266. /* The paper chooses N = 145q^2*ln(q)*n; 145*4*ln(2)~402.025 */
  267. printf("Estimated memory for the initial set is %u MB (N is %u, words per vector is %u)\n", (unsigned int)(N/(double)1000000 * 4 * (m.ncols+31)/(double)32), N, (m.ncols+31)/32);
  268. for(i = 0; i < N; i++)
  269. add_vec_to_set(vector_init(m.ncols, 1), S);
  270. printf("Initial set constructed\n");
  271. for(i = 0; i < m.n_sparse_rows; i++) { // for each sparse row...
  272. /*if((i % 100) == 0)*/ printf("Doing the %uth sparse row...\n", i);
  273. set_t* T = set_init(N);
  274. printf("New T init'd, looping on solutions\n");
  275. for(j = 0; j < S->len; j++) {
  276. if(sparse_satisfies(m.row_list+i, &(S->set[j])))
  277. add_vec_to_set(&(S->set[j]), T);
  278. }
  279. set_free(S);
  280. S = recombine(T, N, m.ncols);
  281. set_free(T);
  282. free(m.row_list[i].cols);
  283. printf("Recomb complete; memory should have just dropped\n");
  284. }
  285.  
  286. for(i = 0; i < m.n_dense_rows; i++) { // for each dense row...
  287. /*if((i % 10) == 0)*/ printf("Doing the %uth dense row...\n", i);
  288. set_t* T = set_init(N);
  289. for(j = 0; j < S->len; j++)
  290. if(dense_satisfies(m.dense_row_list[i], m.dense_row_length,
  291. &(S->set[j])))
  292. add_vec_to_set(&(S->set[j]), T);
  293. set_free(S); //clear the old S, then recombine T into S
  294. S = recombine(T, N, m.ncols);
  295. set_free(T);
  296. free(m.dense_row_list[i]);
  297. printf("Recomb complete; memory should have just dropped\n");
  298. }
  299. free(m.dense_row_list);
  300.  
  301. printf("Found %u dependencies (writing at most 64)\n", S->len);
  302. return *S;
  303. }
  304.  
  305. void write_deps(char* file, set_t S, uint32 n) {
  306. uint64* cols = (uint64*)xcalloc(n, sizeof(uint64));
  307. uint32 i, j, k, x, y;
  308. FILE* f;
  309. if(S.len > 64) S.len = 64;
  310. for(i = 0; i < S.len; i++) { // for each dep...
  311. vector_t v = S.set[i];
  312. for(j = 0; j < v.len - 1; j++) { // for each word in the dep's bit array
  313. uint32 w = v.coeffs[j]; // (except the last)
  314. for(k = 0; k < 32; k++) { // for each bit in the word
  315. if(w & 1)
  316. cols[(j << 5) + k] |= 1 << i;
  317. w >>= 1;
  318. }
  319. }
  320. x = v.coeffs[j]; // the last word with < 32 bits
  321. y = n % 32; y = y==0?32:y;
  322. for(k = 0; k < y; k++) {
  323. if(x & 1)
  324. cols[(j << 5) + k] |= 1 << i;
  325. x >>= 1;
  326. }
  327. }
  328.  
  329. if((f = fopen(file, "wb")) == NULL) {
  330. fprintf(stderr, "Well this is awkward... the solution's all wrapped"
  331. " up but we can't deliver it...\n");
  332. exit(-1);
  333. }
  334.  
  335. fwrite(cols, sizeof(uint64), n, f);
  336. fclose(f);
  337. }
  338.  
  339. int main(int argc, char** argv) {
  340. matrix_t* mat;
  341. set_t solutions;
  342. printf("\nWelcome to derptown!\n");
  343.  
  344. if(argc < 3) {
  345. fprintf(stderr, "Usage: %s Msieve_matrix_file dep_file", argv[0]);
  346. exit(-1);
  347. }
  348. get_random_seeds(&seed1, &seed2);
  349.  
  350. mat = read_matrix(argv[1]);
  351.  
  352. solutions = Raghavendra(mat);
  353.  
  354. write_deps(argv[2], solutions, mat->ncols);
  355.  
  356. return 0;
  357. }
Advertisement
Add Comment
Please, Sign In to add comment