1 /* Copyright 2009-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS
2 **
3 ** This file is part of the Scotch software package for static mapping,
4 ** graph partitioning and sparse matrix ordering.
5 **
6 ** This software is governed by the CeCILL-C license under French law
7 ** and abiding by the rules of distribution of free software. You can
8 ** use, modify and/or redistribute the software under the terms of the
9 ** CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
10 ** URL: "http://www.cecill.info".
11 **
12 ** As a counterpart to the access to the source code and rights to copy,
13 ** modify and redistribute granted by the license, users are provided
14 ** only with a limited warranty and the software's author, the holder of
15 ** the economic rights, and the successive licensors have only limited
16 ** liability.
17 **
18 ** In this respect, the user's attention is drawn to the risks associated
19 ** with loading, using, modifying and/or developing or reproducing the
20 ** software by the user in light of its specific status of free software,
21 ** that may mean that it is complicated to manipulate, and that also
22 ** therefore means that it is reserved for developers and experienced
23 ** professionals having in-depth computer knowledge. Users are therefore
24 ** encouraged to load and test the software's suitability as regards
25 ** their requirements in conditions enabling the security of their
26 ** systems and/or data to be ensured and, more generally, to use and
27 ** operate it in the same conditions as regards security.
28 **
29 ** The fact that you are presently reading this means that you have had
30 ** knowledge of the CeCILL-C license and that you accept its terms.
31 */
32 /************************************************************/
33 /**                                                        **/
34 /**   NAME       : gscat.c                                 **/
35 /**                                                        **/
36 /**   AUTHOR     : Francois PELLEGRINI                     **/
37 /**                                                        **/
38 /**   FUNCTION   : This program writes a centralized       **/
39 /**                source graph file in the form of a      **/
40 /**                distributed source graph.               **/
41 /**                                                        **/
42 /**   DATES      : # Version 5.1  : from : 26 apr 2009     **/
43 /**                                 to   : 14 feb 2011     **/
44 /**                # Version 6.0  : from : 01 jan 2012     **/
45 /**                                 to   : 12 nov 2014     **/
46 /**                                                        **/
47 /************************************************************/
48 
49 /*
50 **  The defines and includes.
51 */
52 
53 #define GSCAT
54 
55 #include "module.h"
56 #include "common.h"
57 #include "scotch.h"
58 #include "gscat.h"
59 
60 /*
61 **  The static variables.
62 */
63 
64 static int                  C_paraNum = 0;        /* Number of parameters       */
65 static int                  C_fileNum = 0;        /* Number of file in arg list */
66 static File                 C_fileTab[C_FILENBR] = { /* File array              */
67                               { "r" },
68                               { "w" } };
69 
70 static const char *         C_usageList[] = {     /* Usage */
71   "gscat <nparts> <input source file> <output target file pattern> <options>",
72   "  -h  : Display this help",
73   "  -V  : Print program version and copyright",
74   NULL };
75 
76 /******************************/
77 /*                            */
78 /* This is the main function. */
79 /*                            */
80 /******************************/
81 
82 int
main(int argc,char * argv[])83 main (
84 int                         argc,
85 char *                      argv[])
86 {
87   SCOTCH_Num          p[1] = { 1 };               /* Number of parts */
88   int                 i;
89 
90   errorProg ("gscat");
91 
92   if ((argc >= 2) && (argv[1][0] == '?')) {       /* If need for help */
93     usagePrint (stdout, C_usageList);
94     return     (0);
95   }
96 
97   fileBlockInit (C_fileTab, C_FILENBR);           /* Set default stream pointers */
98 
99   for (i = 1; i < argc; i ++) {                   /* Loop for all option codes                        */
100     if ((argv[i][0] != '-') || (argv[i][1] == '\0') || (argv[i][1] == '.')) { /* If found a file name */
101       if (C_paraNum < 1) {                        /* If number of parameters not reached              */
102         if ((p[C_paraNum ++] = atoi (argv[i])) < 1) { /* Get number of parts                          */
103           errorPrint ("main: invalid number of parts '%s'", argv[i]);
104           return     (1);
105         }
106         continue;                                 /* Process the other parameters */
107       }
108       if (C_fileNum < C_FILEARGNBR)               /* A file name has been given */
109         fileBlockName (C_fileTab, C_fileNum ++) = argv[i];
110       else {
111         errorPrint ("main: too many file names given");
112         return     (1);
113       }
114     }
115     else {                                        /* If found an option name */
116       switch (argv[i][1]) {
117         case 'H' :                                /* Give the usage message */
118         case 'h' :
119           usagePrint (stdout, C_usageList);
120           return     (0);
121         case 'V' :
122           fprintf (stderr, "gscat, version " SCOTCH_VERSION_STRING "\n");
123           fprintf (stderr, "Copyright 2009-2012,2014 IPB, Universite de Bordeaux, INRIA & CNRS, France\n");
124           fprintf (stderr, "This software is libre/free software under CeCILL-C -- see the user's manual for more information\n");
125           return  (0);
126         default :
127           errorPrint ("main: unprocessed option '%s'", argv[i]);
128           return     (1);
129       }
130     }
131   }
132 
133   fileBlockOpen (C_fileTab, 1);                   /* Open input graph file */
134 
135   C_graphScat (C_filepntrsrcinp, p[0], C_filenamesrcout);
136 
137   fileBlockClose (C_fileTab, 1);                  /* Always close explicitely to end eventual (un)compression tasks */
138 
139 #ifdef COMMON_PTHREAD
140   pthread_exit ((void *) 0);                      /* Allow potential (un)compression tasks to complete */
141 #endif /* COMMON_PTHREAD */
142   return (0);
143 }
144 
145 static
146 int
C_graphScat(FILE * const stream,SCOTCH_Num procnbr,char * const nameptr)147 C_graphScat (
148 FILE * const                stream,
149 SCOTCH_Num                  procnbr,
150 char * const                nameptr)
151 {
152   SCOTCH_Num          versval;
153   SCOTCH_Num          propval;
154   char                proptab[4];
155   int                 flagtab[3];
156   SCOTCH_Num          baseval;
157   SCOTCH_Num          vertglbnbr;
158   SCOTCH_Num          edgeglbnbr;
159   SCOTCH_Num          procnum;
160 
161   if (intLoad (stream, &versval) != 1) {          /* Read version number */
162     errorPrint ("C_graphScat: bad input (1)");
163     return     (1);
164   }
165   if (versval != 0) {                             /* If version not zero */
166     errorPrint ("C_graphScat: only centralized graphs supported");
167     return     (1);
168   }
169 
170   if ((intLoad (stream, &vertglbnbr) != 1) ||     /* Read rest of header */
171       (intLoad (stream, &edgeglbnbr) != 1) ||
172       (intLoad (stream, &baseval)    != 1) ||
173       (intLoad (stream, &propval)    != 1) ||
174       (propval < 0)                        ||
175       (propval > 111)) {
176     errorPrint ("C_graphScat: bad input (2)");
177     return     (1);
178   }
179   sprintf (proptab, "%3.3d", (int) propval);      /* Compute file properties */
180   flagtab[0] = proptab[0] - '0';                  /* Vertex labels flag      */
181   flagtab[1] = proptab[1] - '0';                  /* Edge weights flag       */
182   flagtab[2] = proptab[2] - '0';                  /* Vertex loads flag       */
183 
184   for (procnum = 0; procnum < procnbr; procnum ++) {
185     char *              nametmp;
186     FILE *              ostream;
187     SCOTCH_Num          vertlocnbr;
188     SCOTCH_Num          vertlocnum;
189     SCOTCH_Num          edgelocnbr;
190 
191     nametmp = nameptr;
192     ostream = NULL;
193     if (fileNameDistExpand (&nametmp, procnbr, procnum, -1) == 0) {
194       ostream = fopen (nametmp, "w+");
195       memFree (nametmp);                            /* Expanded name no longer needed anyway */
196     }
197     if (ostream == NULL) {
198       errorPrint ("C_graphScat: cannot open file");
199       return     (1);
200     }
201 
202     vertlocnbr = DATASIZE (vertglbnbr, procnbr, procnum);
203 
204     if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015d\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */
205                  (SCOTCH_Num) procnbr,
206                  (SCOTCH_Num) procnum,
207                  (SCOTCH_Num) vertglbnbr,
208                  (SCOTCH_Num) edgeglbnbr,
209                  (SCOTCH_Num) vertlocnbr,
210                  0,                               /* Number of edges not yet known */
211                  (SCOTCH_Num) baseval,
212                  proptab) == EOF) {
213       errorPrint ("C_graphScat: bad output (1)");
214       return     (1);
215     }
216 
217     for (vertlocnum = edgelocnbr = 0; vertlocnum < vertlocnbr; vertlocnum ++) {
218       SCOTCH_Num          degrval;
219 
220       if (flagtab[0] != 0) {                      /* If must read label               */
221         SCOTCH_Num          vlblval;              /* Value where to read vertex label */
222 
223         if (intLoad (stream, &vlblval) != 1) {    /* Read label data */
224           errorPrint ("C_graphScat: bad input (3)");
225           return     (1);
226         }
227         intSave (ostream, vlblval);
228         putc ('\t', ostream);
229       }
230       if (flagtab[2] != 0) {                      /* If must read vertex load        */
231         SCOTCH_Num          veloval;              /* Value where to read vertex load */
232 
233         if (intLoad (stream, &veloval) != 1) {    /* Read vertex load data    */
234           errorPrint ("C_graphScat: bad input (4)");
235           return     (1);
236         }
237         intSave (ostream, veloval);
238         putc ('\t', ostream);
239       }
240       if (intLoad (stream, &degrval) != 1) {      /* Read vertex degree */
241         errorPrint ("C_graphScat: bad input (5)");
242         return     (1);
243       }
244       intSave (ostream, degrval);
245 
246       edgelocnbr += degrval;
247 
248       for ( ; degrval > 0; degrval --) {
249         SCOTCH_Num          edgeval;              /* Value where to read edge end */
250 
251         if (flagtab[1] != 0) {                    /* If must read edge load        */
252           SCOTCH_Num          edloval;            /* Value where to read edge load */
253 
254           if (intLoad (stream, &edloval) != 1) {  /* Read edge load data    */
255             errorPrint ("C_graphScat: bad input (6)");
256             return     (1);
257           }
258           putc ('\t', ostream);
259           intSave (ostream, edloval);
260         }
261 
262         if (intLoad (stream, &edgeval) != 1) {    /* Read edge data */
263           errorPrint ("C_graphScat: bad input (7)");
264           return     (1);
265         }
266         putc ('\t', ostream);
267         intSave (ostream, edgeval);
268       }
269       putc ('\n', ostream);
270     }
271 
272     rewind (ostream);
273 
274     if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015lld\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */
275                  (SCOTCH_Num) procnbr,
276                  (SCOTCH_Num) procnum,
277                  (SCOTCH_Num) vertglbnbr,
278                  (SCOTCH_Num) edgeglbnbr,
279                  (SCOTCH_Num) vertlocnbr,
280                  (long long)  edgelocnbr,         /* Now we know the exact number of edges */
281                  (SCOTCH_Num) baseval,
282                  proptab) == EOF) {
283       errorPrint ("C_graphScat: bad output (2)");
284       return     (1);
285     }
286 
287     fclose (ostream);
288   }
289 
290   return (0);
291 }
292