1 #include "cado.h" // IWYU pragma: keep
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <gmp.h>
5 #include <string.h>
6 #include "macros.h"
7 
8 static void
printVec(int * vec,int ncols)9 printVec (int *vec, int ncols)
10 {
11     int i;
12 
13     fprintf(stderr, "vec=");
14     for(i = 0; i < ncols; i++)
15 	fprintf(stderr, "%d", vec[i] & 1);
16     fprintf(stderr, "\n");
17 }
18 
19 static int
checkSparse(FILE * matfile,FILE * kerfile,int ncols,int nlimbs,int * vec,int compact,int verbose)20 checkSparse (FILE *matfile, FILE *kerfile, int ncols, int nlimbs, int *vec,
21              int compact, int verbose)
22 {
23     long a;
24     unsigned long w, b;
25     int i, j, ret = 0, nc, cc, jj;
26 
27     memset(vec, 0, ncols * sizeof(int));
28     // get next dependence relation
29     rewind(matfile);
30     ret = fscanf(matfile, "%d %d", &i, &j);
31     ASSERT_ALWAYS(ret == 2);
32     for(int c ; c = getc(matfile), c != EOF && c != 'n' ; );
33     for(i = 0; i < nlimbs; ++i){
34 	ret = fscanf(kerfile, "%lx", &w);
35 	if(ret == -1)
36 	    break;
37 	ASSERT_ALWAYS (ret == 1);
38 	if(verbose)
39 	    fprintf(stderr, "w=%lx\n", w);
40 	for(j = 0; j < GMP_NUMB_BITS; ++j){
41 	    if(w & 1UL){
42 		if(verbose)
43 		    fprintf(stderr, "+R_%d\n", (i * GMP_NUMB_BITS)+j);
44 		if(compact == 0) {
45 		    ret = fscanf(matfile, "%ld %lu %d", &a, &b, &nc);
46                     ASSERT_ALWAYS(ret == 3);
47                 } else {
48 		    ret = fscanf(matfile, "%d", &nc);
49                     ASSERT_ALWAYS(ret == 1);
50                 }
51 		for(jj = 0; jj < nc; jj++){
52 		    ret = fscanf(matfile, "%d", &cc);
53                     ASSERT_ALWAYS(ret == 1);
54 		    if(verbose >= 2)
55 			fprintf(stderr, "vec[%d]++\n", cc);
56 		    if(cc >= ncols){
57 			fprintf(stderr, "GASP: cc=%d > ncols=%d", cc, ncols);
58 			fprintf(stderr, " at line %d\n", (i*GMP_NUMB_BITS)+j);
59 		    }
60 		    vec[cc]++;
61 		}
62 		if(verbose >= 2)
63 		    printVec(vec, ncols);
64                 for(int c ; c = getc(matfile), c != EOF && c != 'n' ; );
65             }
66             else{
67                 for(int c ; c = getc(matfile), c != EOF && c != 'n' ; );
68             }
69             w >>= 1;
70         }
71     }
72     return ret;
73 }
74 
75 static void
checkVector(int * vec,int ncols,int skip)76 checkVector (int *vec, int ncols, int skip)
77 {
78     int ok, i;
79 
80     ok = 1;
81     for(i = skip; i < ncols; i++)
82 	if(vec[i] & 1){
83 	    ok = 0;
84 	    break;
85 	}
86     if(ok)
87 	fprintf(stderr, "y");
88     else
89 	fprintf(stderr, "[n (%d)]", i);
90 }
91 
92 static void
checkSparseAll(char * matname,char * kername,int compact,int skip,int verbose)93 checkSparseAll (char *matname, char *kername, int compact, int skip, int verbose)
94 {
95     FILE *matfile, *kerfile;
96     int nrows, ncols, nlimbs, *vec, ndep, ret;
97 
98     matfile = fopen(matname, "r");
99     kerfile = fopen(kername, "r");
100     ret = fscanf(matfile, "%d %d", &nrows, &ncols);
101     ASSERT_ALWAYS(ret == 2);
102     nlimbs = (nrows / GMP_NUMB_BITS) + 1;
103     vec = (int *)malloc(ncols * sizeof(int));
104     ndep = 0;
105     while(1){
106 	if(verbose)
107 	    fprintf(stderr, "Checking dep %d\n", ndep++);
108         ret = checkSparse(matfile,kerfile,ncols,nlimbs,vec,compact,verbose);
109 	if(ret == -1)
110 	    break;
111 	if(verbose >= 2)
112 	    printVec(vec, ncols);
113 	checkVector(vec, ncols, skip);
114     }
115     fprintf(stderr, "\n");
116     free(vec);
117     fclose(matfile);
118     fclose(kerfile);
119 }
120 
121 static int
checkWithIndex(FILE * purgedfile,FILE * indexfile,FILE * kerfile,int verbose,int nrows,int ncols,int small_nrows,int * vec)122 checkWithIndex (FILE *purgedfile, FILE *indexfile, FILE *kerfile, int verbose,
123                 int nrows, int ncols, int small_nrows, int *vec)
124 {
125     unsigned long w;
126     int i, j, k, ret, nlimbs, ind, nrel, r, nc;
127     char *small_row_used, *rel_used;
128 
129     nlimbs = (small_nrows / GMP_NUMB_BITS) + 1;
130     // first read used rows in the sparse matrix
131     small_row_used = (char *)malloc(small_nrows * sizeof(char));
132     memset(small_row_used, 0, small_nrows * sizeof(char));
133     for(i = 0; i < nlimbs; ++i){
134         ret = fscanf(kerfile, "%lx", &w);
135         if(ret == -1){
136             free(small_row_used);
137             return ret;
138         }
139         ASSERT_ALWAYS (ret == 1);
140         if(verbose)
141             fprintf(stderr, "w=%lx\n", w);
142         for(j = 0; j < GMP_NUMB_BITS; ++j){
143             if(w & 1UL){
144                 ind = (i * GMP_NUMB_BITS)+j;
145                 if(verbose)
146                     fprintf(stderr, "+R_%d\n", ind);
147                 small_row_used[ind] = 1;
148             }
149             w >>= 1;
150         }
151     }
152     // now map to the rels of the big matrix
153     rel_used = (char *)malloc(nrows * sizeof(char));
154     memset(rel_used, 0, nrows * sizeof(char));
155     rewind(indexfile);
156     ret = fscanf(indexfile, "%d %d", &i, &j); // skip first line
157     ASSERT_ALWAYS(ret == 2);
158     for(i = 0; i < small_nrows; i++){
159         ret = fscanf(indexfile, "%d", &nrel);
160         ASSERT_ALWAYS(ret == 1);
161         for(j = 0; j < nrel; j++){
162             ret = fscanf(indexfile, "%d", &r);
163             ASSERT_ALWAYS(ret == 2);
164             if(small_row_used[i])
165                 rel_used[r] ^= 1;
166         }
167     }
168     // now really read the big matrix in
169     rewind(purgedfile);
170     ret = fscanf(purgedfile, "%d %d", &i, &j);
171     ASSERT_ALWAYS(ret == 2);
172     memset(vec, 0, ncols * sizeof(int));
173     for(i = 0; i < nrows; i++){
174         ret = fscanf(purgedfile, "%d %d", &j, &nc);
175         ASSERT_ALWAYS(ret == 2);
176         for(j = 0; j < nc; j++){
177             ret = fscanf(purgedfile, "%d", &k);
178             ASSERT_ALWAYS(ret == 1);
179             if(rel_used[i])
180 		vec[k]++;
181 	}
182     }
183     free(small_row_used);
184     free(rel_used);
185     return 1;
186 }
187 
188 static void
checkWithIndexAll(char * purgedname,char * indexname,char * kername,int skip,int verbose)189 checkWithIndexAll (char *purgedname, char *indexname, char *kername,
190 		   int skip, int verbose)
191 {
192     FILE *purgedfile = fopen(purgedname, "r");
193     FILE *indexfile = fopen(indexname, "r");
194     FILE *kerfile = fopen(kername, "r");
195     int nrows, ncols, *vec, small_nrows, small_ncols, ret, ndep;
196 
197     ret = fscanf(purgedfile, "%d %d", &nrows, &ncols);
198     ASSERT_ALWAYS(ret == 2);
199     ret = fscanf(indexfile, "%d %d", &small_nrows, &small_ncols);
200     ASSERT_ALWAYS(ret == 2);
201     vec = (int *)malloc(ncols * sizeof(int));
202     ndep = 0;
203     while(1){
204         if(verbose)
205             fprintf(stderr, "Checking dep %d\n", ndep++);
206         ret = checkWithIndex(purgedfile,indexfile,kerfile,verbose,nrows,ncols,small_nrows, vec);
207 	if(ret == -1)
208 	    break;
209 	checkVector(vec, ncols, skip);
210     }
211     fprintf(stderr, "\n");
212     free(vec);
213     fclose(kerfile);
214     fclose(purgedfile);
215     fclose(indexfile);
216 }
217 
218 static void
usage(void)219 usage (void)
220 {
221   fprintf (stderr, "Usage: checkdep [-verbose] [-skip n] -purged file -index file -ker file\n");
222   fprintf (stderr, "       checkdep [-verbose] [-compact] [-skip n] -mat file -ker file\n");
223   exit (1);
224 }
225 
226 int
main(int argc,char * argv[])227 main (int argc, char *argv[])
228 {
229     char *matname = NULL, *indexname = NULL, *purgedname = NULL;
230     char *kername = NULL;
231     int verbose = 0, compact = 0, skip = 0;
232 
233     while(argc > 1 && argv[1][0] == '-'){
234         if(argc > 2 && strcmp (argv[1], "-mat") == 0){
235 	    matname = argv[2];
236             argc -= 2;
237             argv += 2;
238         }
239         else if(argc > 2 && strcmp (argv[1], "-ker") == 0){
240 	    kername = argv[2];
241             argc -= 2;
242             argv += 2;
243         }
244         else if(argc > 2 && strcmp (argv[1], "-index") == 0){
245 	    indexname = argv[2];
246             argc -= 2;
247             argv += 2;
248         }
249         else if(argc > 2 && strcmp (argv[1], "-purged") == 0){
250 	    purgedname = argv[2];
251             argc -= 2;
252             argv += 2;
253         }
254         else if(argc > 2 && strcmp (argv[1], "-skip") == 0){
255 	    skip = atoi(argv[2]);
256             argc -= 2;
257             argv += 2;
258         }
259 	else if(argc > 1 && strcmp (argv[1], "-compact") == 0){
260 	    compact = 1;
261 	    argc -= 1;
262 	    argv += 1;
263 	}
264 	else if(argc > 1 && strcmp (argv[1], "-verbose") == 0){
265 	    verbose = 1;
266 	    argc -= 1;
267 	    argv += 1;
268 	}
269     }
270 
271     if (indexname != NULL)
272       {
273         if (purgedname == NULL || kername == NULL)
274           usage ();
275 	checkWithIndexAll (purgedname, indexname, kername, skip, verbose);
276       }
277     else
278       {
279         if (matname == NULL || kername == NULL)
280           usage ();
281 	checkSparseAll (matname, kername, compact, skip, verbose);
282       }
283     return 0;
284 }
285