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