1 /* Copyright 2004,2007,2008,2010 ENSEIRB, 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 : graph_io_scot.c **/
35 /** **/
36 /** AUTHORS : Francois PELLEGRINI **/
37 /** **/
38 /** FUNCTION : This module contains the I/O routines **/
39 /** for handling the Scotch graph format. **/
40 /** **/
41 /** DATES : # Version 3.2 : from : 06 nov 1997 **/
42 /** to 26 may 1998 **/
43 /** # Version 3.3 : from : 13 dec 1998 **/
44 /** to 21 dec 1998 **/
45 /** # Version 4.0 : from : 18 dec 2001 **/
46 /** to 22 dec 2005 **/
47 /** # Version 5.0 : from : 13 sep 2006 **/
48 /** to 27 feb 2008 **/
49 /** # Version 5.1 : from : 11 aug 2010 **/
50 /** to 11 aug 2010 **/
51 /** **/
52 /************************************************************/
53
54 /*
55 ** The defines and includes.
56 */
57
58 #define GRAPH_IO_SCOT
59
60 #include "module.h"
61 #include "common.h"
62 #include "geom.h"
63 #include "graph.h"
64 #include "graph_io_scot.h"
65
66 /* This routine loads the geometrical graph
67 ** in the Scotch graph format, and allocates
68 ** the proper structures.
69 ** - 0 : on success.
70 ** - !0 : on error.
71 */
72
73 int
graphGeomLoadScot(Graph * restrict const grafptr,Geom * restrict const geomptr,FILE * const filesrcptr,FILE * const filegeoptr,const char * const dataptr)74 graphGeomLoadScot (
75 Graph * restrict const grafptr, /* Graph to load */
76 Geom * restrict const geomptr, /* Geometry to load */
77 FILE * const filesrcptr, /* Topological data */
78 FILE * const filegeoptr, /* No use */
79 const char * const dataptr) /* No use */
80 {
81 void * coorfileptr; /* Temporary pointer to comply with C99 rules */
82 double * restrict coorfiletab; /* Pointer to geometric data read from file */
83 GraphGeomScotSort * restrict coorsorttab; /* Pointer to geometric data sorting array */
84 int coorsortflag; /* Flag set if geometric data sorted by label */
85 Gnum coornbr; /* Number of geometric coordinates in file */
86 Gnum coornum; /* Number of current coordinate */
87 GraphGeomScotSort * restrict vertsorttab; /* Pointer to graph sorting array */
88 int vertsortflag; /* Flag set if graph data sorted by label */
89 Gnum vertnum; /* Current graph vertex */
90 Gnum dimnnbr; /* Dimension of geometry file */
91 int o;
92
93 if (filesrcptr != NULL) {
94 if (graphLoad (grafptr, filesrcptr, -1, 0) != 0)
95 return (1);
96 }
97
98 if (filegeoptr == NULL)
99 return (0);
100
101 if ((intLoad (filegeoptr, &dimnnbr) != 1) || /* Read type and number of geometry items */
102 (intLoad (filegeoptr, &coornbr) != 1) ||
103 (dimnnbr < 1) ||
104 (dimnnbr > 3)) {
105 errorPrint ("graphGeomLoadScot: bad input (1)");
106 return (1);
107 }
108 if ((filesrcptr != NULL) && (grafptr->vertnbr != coornbr)) {
109 errorPrint ("graphGeomLoadScot: inconsistent number of vertices");
110 return (1);
111 }
112
113 if (grafptr->vertnbr == 0)
114 return (0);
115
116 if ((geomptr->geomtab == NULL) && /* Allocate geometry if necessary */
117 ((geomptr->geomtab = (double *) memAlloc (grafptr->vertnbr * dimnnbr * sizeof (double))) == NULL)) {
118 errorPrint ("graphGeomLoadScot: out of memory (1)");
119 return (1);
120 }
121
122 if (memAllocGroup ((void **)
123 &coorfileptr, (size_t) (coornbr * dimnnbr * sizeof (double)),
124 &coorsorttab, (size_t) (coornbr * sizeof (GraphGeomScotSort)),
125 &vertsorttab, (size_t) (grafptr->vertnbr * sizeof (GraphGeomScotSort)), NULL) == NULL) {
126 errorPrint ("graphGeomLoadScot: out of memory (2)");
127 return (1);
128 }
129 coorfiletab = coorfileptr;
130
131 o = 0;
132 coorsortflag = 1; /* Assume geometry data sorted */
133 for (coornum = 0; (o == 0) && (coornum < coornbr); coornum ++) {
134 Gnum vlblnum;
135
136 o = 1 - intLoad (filegeoptr, &vlblnum);
137 coorsorttab[coornum].labl = vlblnum;
138 coorsorttab[coornum].num = coornum;
139 if ((coornum > 0) && /* Check if geometry data sorted */
140 (coorsorttab[coornum].labl < coorsorttab[coornum - 1].labl))
141 coorsortflag = 0; /* Geometry data not sorted */
142
143 o |= 1 - fscanf (filegeoptr, "%lf", /* Read X coordinate */
144 &coorfiletab[coornum * dimnnbr]);
145 if (dimnnbr > 1) {
146 o |= 1 - fscanf (filegeoptr, "%lf", /* Read Y coordinate */
147 &coorfiletab[(coornum * dimnnbr) + 1]);
148 if (dimnnbr > 2)
149 o |= 1 - fscanf (filegeoptr, "%lf", /* Read Z coordinate */
150 &coorfiletab[(coornum * dimnnbr) + 2]);
151 }
152 }
153 if (o != 0) {
154 errorPrint ("graphGeomLoadScot: bad input (2)");
155 memFree (coorfiletab); /* Free group leader */
156 return (1);
157 }
158
159 if (coorsortflag != 1) /* If geometry data not sorted */
160 intSort2asc1 (coorsorttab, coornbr); /* Sort sort area by ascending labels */
161
162 for (coornum = 1; coornum < coornbr; coornum ++) { /* Check geometric data integrity */
163 if (coorsorttab[coornum].labl == coorsorttab[coornum - 1].labl) {
164 errorPrint ("graphGeomLoadScot: duplicate vertex label");
165 memFree (coorfiletab); /* Free group leader */
166 return (1);
167 }
168 }
169
170 if (grafptr->vlbltax != NULL) { /* If graph has vertex labels */
171 vertsortflag = 1; /* Assume graph data sorted */
172 for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) {
173 vertsorttab[vertnum].labl = grafptr->vlbltax[vertnum + grafptr->baseval];
174 vertsorttab[vertnum].num = vertnum;
175 if ((vertnum > 0) && /* Check if graph data sorted */
176 (vertsorttab[vertnum].labl < vertsorttab[vertnum - 1].labl))
177 vertsortflag = 0; /* Graph data not sorted */
178 }
179 if (vertsortflag != 1) /* If graph data not sorted */
180 intSort2asc1 (vertsorttab, grafptr->vertnbr); /* Sort sort area by ascending labels */
181 }
182 else { /* Graph does not have vertex labels */
183 for (vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++)
184 vertsorttab[vertnum].labl =
185 vertsorttab[vertnum].num = vertnum;
186 }
187
188 for (coornum = vertnum = 0; vertnum < grafptr->vertnbr; vertnum ++) { /* For all vertices in graph */
189 while ((coornum < coornbr) && (coorsorttab[coornum].labl < vertsorttab[vertnum].labl))
190 coornum ++; /* Search geometry vertex with same label */
191 if ((coornum >= coornbr) || (coorsorttab[coornum].labl > vertsorttab[vertnum].labl)) { /* If label does not exist */
192 errorPrint ("graphGeomLoadScot: vertex geometry data not found (%d)",
193 vertsorttab[vertnum].labl);
194 memFree (coorfiletab); /* Free group leader */
195 return (1);
196 }
197 memCpy (&geomptr->geomtab[vertsorttab[vertnum].num * dimnnbr], &coorfiletab[coorsorttab[coornum ++].num * dimnnbr], dimnnbr * sizeof (double));
198 }
199
200 memFree (coorfiletab); /* Free group leader */
201
202 return (0);
203 }
204
205 /* This routine saves the source process graph
206 ** in the Scotch source and geometry formats.
207 ** It returns:
208 ** - 0 : on success.
209 ** - !0 : on error.
210 */
211
212 int
graphGeomSaveScot(const Graph * restrict const grafptr,const Geom * restrict const geomptr,FILE * const filesrcptr,FILE * const filegeoptr,const char * const dataptr)213 graphGeomSaveScot (
214 const Graph * restrict const grafptr, /* Graph to save */
215 const Geom * restrict const geomptr, /* Geometry to save */
216 FILE * const filesrcptr, /* Topological data */
217 FILE * const filegeoptr, /* No use */
218 const char * const dataptr) /* No use */
219 {
220 Gnum vertnum;
221 int dimnnbr;
222 int o;
223
224 if (filesrcptr != NULL) {
225 if (graphSave (grafptr, filesrcptr) != 0) /* Save graph structural data */
226 return (1);
227 }
228
229 dimnnbr = geomptr->dimnnbr;
230
231 o = 0;
232 if (geomptr->geomtab != NULL) { /* If geometrical data present */
233 o = (fprintf (filegeoptr, GNUMSTRING "\n" GNUMSTRING "\n", /* Output file header */
234 (Gnum) geomptr->dimnnbr,
235 (Gnum) grafptr->vertnbr) == EOF);
236
237 switch (dimnnbr) { /* Output geometry data */
238 case 1 :
239 for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++)
240 o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\n",
241 (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum),
242 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr]) == EOF);
243 break;
244 case 2 :
245 for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++)
246 o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\n",
247 (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum),
248 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr],
249 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1]) == EOF);
250 break;
251 case 3 :
252 for (vertnum = grafptr->baseval; (o == 0) && (vertnum < grafptr->vertnnd); vertnum ++)
253 o |= (fprintf (filegeoptr, GNUMSTRING "\t%lf\t%lf\t%lf\n",
254 (Gnum) ((grafptr->vlbltax != NULL) ? grafptr->vlbltax[vertnum] : vertnum),
255 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr],
256 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 1],
257 (double) geomptr->geomtab[(vertnum - grafptr->baseval) * dimnnbr + 2]) == EOF);
258 break;
259 #ifdef SCOTCH_DEBUG_GRAPH2
260 default :
261 errorPrint ("graphGeomSaveScot: invalid geometry type");
262 return (1);
263 #endif /* SCOTCH_DEBUG_GRAPH2 */
264 }
265
266 if (o != 0) {
267 errorPrint ("graphGeomSaveScot: bad output");
268 }
269 }
270
271 return (o);
272 }
273