1 /* util.c */
2
3 #include "../ETree.h"
4
5 #define MYDEBUG 0
6
7 /*--------------------------------------------------------------------*/
8 /*
9 ----------------------------------------------
10 return the number of bytes taken by the object
11
12 created -- 95nov15, cca
13 ----------------------------------------------
14 */
15 int
ETree_sizeOf(ETree * etree)16 ETree_sizeOf (
17 ETree *etree
18 ) {
19 int nbytes ;
20 /*
21 ---------------
22 check the input
23 ---------------
24 */
25 if ( etree == NULL ) {
26 fprintf(stderr, "\n fatal error in ETree_sizeOf(%p)"
27 "\n bad input\n", etree) ;
28 exit(-1) ;
29 }
30 nbytes = sizeof(struct _ETree) ;
31 if ( etree->tree != NULL ) {
32 nbytes += Tree_sizeOf(etree->tree) ;
33 }
34 if ( etree->nodwghtsIV != NULL ) {
35 nbytes += IV_sizeOf(etree->nodwghtsIV) ;
36 }
37 if ( etree->nodwghtsIV != NULL ) {
38 nbytes += IV_sizeOf(etree->bndwghtsIV) ;
39 }
40 if ( etree->vtxToFrontIV != NULL ) {
41 nbytes += IV_sizeOf(etree->vtxToFrontIV) ;
42 }
43 return(nbytes) ; }
44
45 /*--------------------------------------------------------------------*/
46 /*
47 ----------------------------------------
48 return the number of factor indices
49
50 created -- 95nov15, cca
51 modified -- 96jan11, cca
52 ----------------------------------------
53 */
54 int
ETree_nFactorIndices(ETree * etree)55 ETree_nFactorIndices (
56 ETree *etree
57 ) {
58 int nb, nfront, nv, nind, nvtx, v ;
59 int *bndwghts, *nodwghts ;
60 /*
61 ---------------
62 check the input
63 ---------------
64 */
65 if ( etree == NULL
66 || (nfront = etree->nfront) <= 0
67 || (nvtx = etree->nvtx) <= 0 ) {
68 fprintf(stderr, "\n fatal error in ETree_nFactorIndices(%p)"
69 "\n bad input\n", etree) ;
70 exit(-1) ;
71 }
72 nodwghts = IV_entries(etree->nodwghtsIV) ;
73 bndwghts = IV_entries(etree->bndwghtsIV) ;
74 nind = 0 ;
75 for ( v = 0 ; v < nfront ; v++ ) {
76 nv = nodwghts[v] ;
77 nb = bndwghts[v] ;
78 nind += nv + nb ;
79 }
80 return(nind) ; }
81
82 /*--------------------------------------------------------------------*/
83 /*
84 ------------------------------------------
85 return the number of factor entries
86
87 symflag -- symmetry flag
88 0 (SPOOLES_SYMMETRIC) -- symmetric
89 1 (SPOOLES_HERMITIAN) -- hermitian
90 2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
91
92 created -- 98jun05, cca
93 ------------------------------------------
94 */
95 int
ETree_nFactorEntries(ETree * etree,int symflag)96 ETree_nFactorEntries (
97 ETree *etree,
98 int symflag
99 ) {
100 int J, nfront, nvtx, nzf ;
101 /*
102 ---------------
103 check the input
104 ---------------
105 */
106 if ( etree == NULL
107 || (nfront = etree->nfront) <= 0
108 || (nvtx = etree->nvtx) <= 0 ) {
109 fprintf(stderr, "\n fatal error in ETree_nFactorEntries(%p,%d)"
110 "\n bad input\n", etree, symflag) ;
111 exit(-1) ;
112 }
113 nzf = 0 ;
114 for ( J = 0 ; J < nfront ; J++ ) {
115 nzf += ETree_nFactorEntriesInFront(etree, symflag, J) ;
116 }
117 return(nzf) ; }
118
119 /*--------------------------------------------------------------------*/
120 /*
121 ------------------------------------------
122 return the number of factor operations
123
124 type -- type of matrix entries
125 1 (SPOOLES_REAL) -- real entries
126 2 (SPOOLES_COMPLEX) -- complex entries
127 symflag -- symmetry flag
128 0 (SPOOLES_SYMMETRIC) -- symmetric
129 1 (SPOOLES_HERMITIAN) -- hermitian
130 2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
131
132 created -- 98jun05, cca
133 ------------------------------------------
134 */
135 double
ETree_nFactorOps(ETree * etree,int type,int symflag)136 ETree_nFactorOps (
137 ETree *etree,
138 int type,
139 int symflag
140 ) {
141 double ops ;
142 int J, nfront, nvtx ;
143 /*
144 ---------------
145 check the input
146 ---------------
147 */
148 if ( etree == NULL
149 || (nfront = etree->nfront) <= 0
150 || (nvtx = etree->nvtx) <= 0 ) {
151 fprintf(stderr, "\n fatal error in ETree_nFactorOps(%p,%d,%d)"
152 "\n bad input\n", etree, type, symflag) ;
153 exit(-1) ;
154 }
155 ops = 0 ;
156 for ( J = 0 ; J < nfront ; J++ ) {
157 ops += ETree_nInternalOpsInFront(etree, type, symflag, J)
158 + ETree_nExternalOpsInFront(etree, type, symflag, J) ;
159 }
160 return(ops) ; }
161
162 /*--------------------------------------------------------------------*/
163 /*
164 ----------------------------------------
165 return the number of entries an LU front
166
167 created -- 96dec04, cca
168 ----------------------------------------
169 */
170 double
ETree_nFactorEntriesInFront(ETree * etree,int symflag,int J)171 ETree_nFactorEntriesInFront (
172 ETree *etree,
173 int symflag,
174 int J
175 ) {
176 int b, m, nent ;
177 /*
178 ---------------
179 check the input
180 ---------------
181 */
182 if ( etree == NULL
183 || etree->nfront <= 0
184 || J < 0 || J >= etree->nfront ) {
185 fprintf(stderr,
186 "\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
187 "\n bad input\n", etree, symflag, J) ;
188 exit(-1) ;
189 }
190 b = IV_entry(etree->nodwghtsIV, J) ;
191 m = IV_entry(etree->bndwghtsIV, J) ;
192 switch ( symflag ) {
193 case SPOOLES_SYMMETRIC :
194 case SPOOLES_HERMITIAN :
195 nent = (b*(b+1))/2 + b*m ;
196 break ;
197 case SPOOLES_NONSYMMETRIC :
198 nent = b*b + 2*b*m ;
199 break ;
200 default :
201 fprintf(stderr,
202 "\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
203 "\n bad symflag\n", etree, symflag, J) ;
204 break ;
205 }
206
207 return(nent) ; }
208
209 /*--------------------------------------------------------------------*/
210 /*
211 -------------------------------------------------------
212 return the number of internal LU operations for a front
213
214 created -- 96dec04, cca
215 -------------------------------------------------------
216 */
217 double
ETree_nInternalOpsInFront(ETree * etree,int type,int symflag,int J)218 ETree_nInternalOpsInFront (
219 ETree *etree,
220 int type,
221 int symflag,
222 int J
223 ) {
224 double b, m, ops ;
225 /*
226 ---------------
227 check the input
228 ---------------
229 */
230 if ( etree == NULL
231 || etree->nfront <= 0
232 || J < 0 || J >= etree->nfront ) {
233 fprintf(stderr,
234 "\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
235 "\n bad input\n", etree, type, symflag, J) ;
236 exit(-1) ;
237 }
238 b = ETree_frontSize(etree, J) ;
239 m = ETree_frontBoundarySize(etree, J) ;
240 switch ( symflag ) {
241 case SPOOLES_SYMMETRIC :
242 case SPOOLES_HERMITIAN :
243 ops = (b*(b+1)*(2*b+1))/6. + m*b*b ;
244 break ;
245 case SPOOLES_NONSYMMETRIC :
246 ops = b*(2*b*b+1)/3. + 2*m*b*b ;
247 break ;
248 default :
249 fprintf(stderr,
250 "\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
251 "\n bad symflag\n", etree, type, symflag, J) ;
252 break ;
253 }
254 switch ( type ) {
255 case SPOOLES_REAL :
256 break ;
257 case SPOOLES_COMPLEX :
258 ops = 4*ops ;
259 break ;
260 default :
261 fprintf(stderr,
262 "\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
263 "\n bad type\n", etree, type, symflag, J) ;
264 break ;
265 }
266 return(ops) ; }
267
268 /*--------------------------------------------------------------------*/
269 /*
270 -------------------------------------------------------
271 return the number of external LU operations for a front
272
273 created -- 96dec04, cca
274 -------------------------------------------------------
275 */
276 double
ETree_nExternalOpsInFront(ETree * etree,int type,int symflag,int J)277 ETree_nExternalOpsInFront (
278 ETree *etree,
279 int type,
280 int symflag,
281 int J
282 ) {
283 double b, m, ops ;
284 /*
285 ---------------
286 check the input
287 ---------------
288 */
289 if ( etree == NULL
290 || etree->nfront <= 0
291 || J < 0 || J >= etree->nfront ) {
292 fprintf(stderr,
293 "\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
294 "\n bad input\n", etree, J, type, symflag) ;
295 exit(-1) ;
296 }
297 b = IV_entry(etree->nodwghtsIV, J) ;
298 m = IV_entry(etree->bndwghtsIV, J) ;
299 switch ( symflag ) {
300 case SPOOLES_SYMMETRIC :
301 case SPOOLES_HERMITIAN :
302 ops = m*(m+1)*b ;
303 break ;
304 case SPOOLES_NONSYMMETRIC :
305 ops = 2*b*m*m ;
306 break ;
307 default :
308 break ;
309 }
310 switch ( type ) {
311 case SPOOLES_REAL :
312 break ;
313 case SPOOLES_COMPLEX :
314 ops = 4*ops ;
315 break ;
316 default :
317 fprintf(stderr,
318 "\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
319 "\n bad input\n", etree, J, type, symflag) ;
320 break ;
321 }
322 return(ops) ; }
323
324 /*--------------------------------------------------------------------*/
325 /*
326 ---------------------------------------------------------
327 return a DV object that contains the number of operations
328 for each front using a backward looking algorithm
329
330 created -- 96dec04, cca
331 ---------------------------------------------------------
332 */
333 DV *
ETree_backwardOps(ETree * etree,int type,int symflag,int * vwghts,IVL * symbfacIVL)334 ETree_backwardOps (
335 ETree *etree,
336 int type,
337 int symflag,
338 int *vwghts,
339 IVL *symbfacIVL
340 ) {
341 double extops, opsKbndK, opsKK ;
342 double *ops ;
343 DV *opsDV ;
344 int bndwghtJ, ii, J, k, K, kwght,
345 nadj, nfront, size, wghtJ, wghtK ;
346 int *counts, *indices, *list, *mark, *vtxToFront ;
347 /*
348 ---------------
349 check the input
350 ---------------
351 */
352 if ( etree == NULL || symbfacIVL == NULL ) {
353 fprintf(stderr, "\n fatal error in ETree_backwardOps(%p,%p,%p)"
354 "\n bad input\n", etree, vwghts, symbfacIVL) ;
355 exit(-1) ;
356 }
357 nfront = etree->nfront ;
358 vtxToFront = IV_entries(etree->vtxToFrontIV) ;
359 list = IVinit(nfront, -1) ;
360 mark = IVinit(nfront, -1) ;
361 counts = IVinit(nfront, 0) ;
362 /*
363 ----------------------------
364 initialize the ops DV object
365 ----------------------------
366 */
367 opsDV = DV_new() ;
368 DV_init(opsDV, nfront, NULL) ;
369 ops = DV_entries(opsDV) ;
370 DV_fill(opsDV, 0.0) ;
371 /*
372 -------------------
373 fill the ops vector
374 -------------------
375 */
376 for ( J = 0 ; J < nfront ; J++ ) {
377 ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J) ;
378 wghtJ = ETree_frontSize(etree, J) ;
379 bndwghtJ = ETree_frontBoundarySize(etree, J) ;
380 IVL_listAndSize(symbfacIVL, J, &size, &indices) ;
381 for ( ii = nadj = 0 ; ii < size ; ii++ ) {
382 k = indices[ii] ;
383 if ( (K = vtxToFront[k]) != J ) {
384 kwght = (vwghts == NULL) ? 1 : vwghts[k] ;
385 if ( mark[K] != J ) {
386 counts[K] = 0 ;
387 mark[K] = J ;
388 list[nadj++] = K ;
389 }
390 counts[K] += kwght ;
391 }
392 }
393 IVqsortUp(nadj, list) ;
394 extops = 0.0 ;
395 for ( ii = 0 ; ii < nadj ; ii++ ) {
396 K = list[ii] ;
397 wghtK = counts[K] ;
398 bndwghtJ -= wghtK ;
399 if ( type == SPOOLES_REAL ) {
400 opsKbndK = 2*wghtJ*wghtK*bndwghtJ ;
401 if ( symflag == SPOOLES_SYMMETRIC ) {
402 opsKK = wghtJ*wghtK*(wghtK+1) ;
403 } else if ( symflag == SPOOLES_NONSYMMETRIC ) {
404 opsKK = 2*wghtJ*wghtK*wghtK ;
405 }
406 } else if ( type == SPOOLES_COMPLEX ) {
407 opsKbndK = 8*wghtJ*wghtK*bndwghtJ ;
408 if ( symflag == SPOOLES_SYMMETRIC
409 || symflag == SPOOLES_HERMITIAN ) {
410 opsKK = 4*wghtJ*wghtK*(wghtK+1) ;
411 } else if ( symflag == SPOOLES_NONSYMMETRIC ) {
412 opsKK = 8*wghtJ*wghtK*wghtK ;
413 }
414 }
415 extops += opsKK + opsKbndK ;
416 ops[K] += opsKK + opsKbndK ;
417 if ( symflag == SPOOLES_NONSYMMETRIC ) {
418 extops += opsKbndK ;
419 ops[K] += opsKbndK ;
420 }
421 }
422 /*
423 fprintf(stdout,
424 "\n front %d, %.0f internal ops, %.0f external ops, %.0f extops",
425 J, ETree_nInternalOpsInFront(etree, type, symflag, J),
426 ETree_nExternalOpsInFront(etree, type, symflag, J), extops) ;
427 */
428 }
429 IVfree(list) ;
430 IVfree(mark) ;
431 IVfree(counts) ;
432
433 return(opsDV) ; }
434
435 /*--------------------------------------------------------------------*/
436 /*
437 ------------------------------------
438 return an IV object that contains
439 the number of entries for each front
440
441 created -- 98jan30, cca
442 ------------------------------------
443 */
444 IV *
ETree_factorEntriesIV(ETree * etree,int symflag)445 ETree_factorEntriesIV (
446 ETree *etree,
447 int symflag
448 ) {
449 int J, nfront ;
450 int *nzf ;
451 IV *nzfIV ;
452 /*
453 ---------------
454 check the input
455 ---------------
456 */
457 if ( etree == NULL ) {
458 fprintf(stderr, "\n fatal error in ETree_factorEntriesIV(%p,%d)"
459 "\n bad input\n", etree, symflag) ;
460 exit(-1) ;
461 }
462 nfront = ETree_nfront(etree) ;
463 /*
464 ------------------------
465 initialize the IV object
466 ------------------------
467 */
468 nzfIV = IV_new() ;
469 IV_init(nzfIV, nfront, NULL) ;
470 nzf = IV_entries(nzfIV) ;
471 IV_fill(nzfIV, 0) ;
472 /*
473 -------------------
474 fill the nzf vector
475 -------------------
476 */
477 for ( J = 0 ; J < nfront ; J++ ) {
478 nzf[J] = ETree_nFactorEntriesInFront(etree, symflag, J) ;
479 }
480 return(nzfIV) ; }
481
482 /*--------------------------------------------------------------------*/
483 /*
484 ---------------------------------------------------------
485 return a DV object that contains the number of operations
486 for each front using a forward-looking algorithm
487
488 created -- 96dec04, cca
489 ---------------------------------------------------------
490 */
491 DV *
ETree_forwardOps(ETree * etree,int type,int symflag)492 ETree_forwardOps (
493 ETree *etree,
494 int type,
495 int symflag
496 ) {
497 double *ops ;
498 DV *opsDV ;
499 int J, nfront ;
500 /*
501 ---------------
502 check the input
503 ---------------
504 */
505 if ( etree == NULL ) {
506 fprintf(stderr, "\n fatal error in ETree_forwardOps(%p)"
507 "\n bad input\n", etree) ;
508 exit(-1) ;
509 }
510 nfront = etree->nfront ;
511 opsDV = DV_new() ;
512 DV_init(opsDV, nfront, NULL) ;
513 ops = DV_entries(opsDV) ;
514 DV_fill(opsDV, 0.0) ;
515 for ( J = 0 ; J < nfront ; J++ ) {
516 ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J)
517 + ETree_nExternalOpsInFront(etree, type, symflag, J) ;
518 }
519 return(opsDV) ; }
520
521 /*--------------------------------------------------------------------*/
522 /*
523 ---------------------------------------------------------------
524 given an IV object that maps uncompressed vertices to vertices,
525 create and return an ETree object that is relative to the
526 uncompressed graph.
527
528 created -- 97feb13, cca
529 ---------------------------------------------------------------
530 */
531 ETree *
ETree_expand(ETree * etree,IV * eqmapIV)532 ETree_expand (
533 ETree *etree,
534 IV *eqmapIV
535 ) {
536 ETree *etree2 ;
537 int ii, ndof, nfront ;
538 int *map, *vtxToFront, *vtxToFront2 ;
539 /*
540 ---------------
541 check the input
542 ---------------
543 */
544 if ( etree == NULL || eqmapIV == NULL ) {
545 fprintf(stderr, "\n fatal error in ETree_expand(%p,%p)"
546 "\n bad input\n", etree, eqmapIV) ;
547 exit(-1) ;
548 }
549 nfront = etree->nfront ;
550 IV_sizeAndEntries(eqmapIV, &ndof, &map) ;
551 /*
552 ---------------------------
553 create the new ETree object
554 ---------------------------
555 */
556 etree2 = ETree_new() ;
557 ETree_init1(etree2, nfront, ndof) ;
558 IV_copy(etree2->nodwghtsIV, etree->nodwghtsIV) ;
559 IV_copy(etree2->bndwghtsIV, etree->bndwghtsIV) ;
560 etree2->tree->root = etree->tree->root ;
561 IVcopy(nfront, etree2->tree->par, etree->tree->par) ;
562 IVcopy(nfront, etree2->tree->fch, etree->tree->fch) ;
563 IVcopy(nfront, etree2->tree->sib, etree->tree->sib) ;
564 vtxToFront = IV_entries(etree->vtxToFrontIV) ;
565 vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
566 for ( ii = 0 ; ii < ndof ; ii++ ) {
567 vtxToFront2[ii] = vtxToFront[map[ii]] ;
568 }
569
570 return(etree2) ; }
571
572 /*--------------------------------------------------------------------*/
573 /*
574 --------------------------------------------------------------
575 this method is used to splice together two front trees
576 when the domain vertices and schur complement vertices
577 have been ordered separately.
578
579 etree0 -- the lower front tree is for vertices in the domains.
580 graph0 -- graph for all the vertices
581 mapIV -- IV object that maps vertices to schur complement
582 vertices, if IV_entry(mapIV, v) < 0 then v is
583 a domain vertex.
584 etree1 -- the upper front tree is for vertices in the schur
585 complement.
586
587 created -- 97feb01, cca
588 --------------------------------------------------------------
589 */
590 ETree *
ETree_spliceTwoETrees(ETree * etree0,Graph * graph0,IV * mapIV,ETree * etree1)591 ETree_spliceTwoETrees (
592 ETree *etree0,
593 Graph *graph0,
594 IV *mapIV,
595 ETree *etree1
596 ) {
597 ETree *etree2 ;
598 int *bndwghts0, *bndwghts1, *bndwghts2, *fch0, *head0, *link0,
599 *map, *mark, *nodwghts0, *nodwghts1, *nodwghts2, *par0,
600 *par1, *par2, *sib0, *vadj, *vtxToFront0, *vtxToFront1,
601 *vtxToFront2 ;
602 int ii, J, K, nfront0, nfront1, nfront2, nvtx, phi, v, vsize, w ;
603 /*
604 ---------------
605 check the input
606 ---------------
607 */
608 if ( etree0 == NULL || graph0 == NULL
609 || mapIV == NULL || etree1 == NULL ) {
610 fprintf(stderr,
611 "\n fatal error in ETree_spliceTwoETrees(%p,%p,%p,%p)"
612 "\n bad input\n",
613 etree0, graph0, mapIV, etree1) ;
614 exit(-1) ;
615 }
616 nfront0 = etree0->nfront ;
617 nvtx = etree0->nvtx ;
618 par0 = etree0->tree->par ;
619 fch0 = etree0->tree->fch ;
620 sib0 = etree0->tree->sib ;
621 nodwghts0 = IV_entries(etree0->nodwghtsIV) ;
622 bndwghts0 = IV_entries(etree0->bndwghtsIV) ;
623 vtxToFront0 = IV_entries(etree0->vtxToFrontIV) ;
624 nfront1 = etree1->nfront ;
625 par1 = etree1->tree->par ;
626 bndwghts1 = IV_entries(etree1->bndwghtsIV) ;
627 nodwghts1 = IV_entries(etree1->nodwghtsIV) ;
628 vtxToFront1 = IV_entries(etree1->vtxToFrontIV) ;
629 map = IV_entries(mapIV) ;
630 /*
631 -------------------------
632 create the new front tree
633 -------------------------
634 */
635 nfront2 = nfront0 + nfront1 ;
636 etree2 = ETree_new() ;
637 ETree_init1(etree2, nfront2, etree0->nvtx) ;
638 par2 = etree2->tree->par ;
639 nodwghts2 = IV_entries(etree2->nodwghtsIV) ;
640 bndwghts2 = IV_entries(etree2->bndwghtsIV) ;
641 vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
642 /*
643 --------------------------------------------------
644 fill the parent fields for fronts in the same tree
645 --------------------------------------------------
646 */
647 for ( J = 0 ; J < nfront0 ; J++ ) {
648 par2[J] = par0[J] ;
649 nodwghts2[J] = nodwghts0[J] ;
650 bndwghts2[J] = bndwghts0[J] ;
651 }
652 for ( J = 0 ; J < nfront1 ; J++ ) {
653 par2[J+nfront0] = nfront0 + par1[J] ;
654 nodwghts2[J+nfront0] = nodwghts1[J] ;
655 bndwghts2[J+nfront0] = bndwghts1[J] ;
656 }
657 /*
658 ---------------------------
659 set the vertex to front map
660 ---------------------------
661 */
662 for ( v = 0 ; v < nvtx ; v++ ) {
663 if ( (J = vtxToFront0[v]) >= 0 ) {
664 vtxToFront2[v] = J ;
665 } else {
666 vtxToFront2[v] = vtxToFront1[map[v]] + nfront0 ;
667 }
668 }
669 /*
670 ---------------------------------------------
671 link the vertices to fronts in the lower tree
672 ---------------------------------------------
673 */
674 head0 = IVinit(nfront0, -1) ;
675 link0 = IVinit(nvtx, -1) ;
676 for ( v = 0 ; v < nvtx ; v++ ) {
677 if ( (J = vtxToFront0[v]) >= 0 ) {
678 link0[v] = head0[J] ;
679 head0[J] = v ;
680 }
681 }
682 /*
683 -------------------------------------------------------
684 link roots of the lower tree to nodes in the upper tree
685 -------------------------------------------------------
686 */
687 mark = IVinit(nvtx, -1) ;
688 for ( J = etree0->tree->root ; J != -1 ; J = sib0[J] ) {
689 /*
690 ---------------------------------------
691 K is the parent front in the upper tree
692 ---------------------------------------
693 */
694 K = nfront1 ;
695 /*
696 ---------------------------------------
697 loop over vertices in the lower front J
698 ---------------------------------------
699 */
700 for ( v = head0[J] ; v != -1 ; v = link0[v] ) {
701 Graph_adjAndSize(graph0, v, &vsize, &vadj) ;
702 for ( ii = 0 ; ii < vsize ; ii++ ) {
703 w = vadj[ii] ;
704 if ( vtxToFront0[w] < 0 ) {
705 phi = map[w] ;
706 /*
707 ---------------------------------------------------
708 w is a vertex that belongs to phi in the upper tree
709 ---------------------------------------------------
710 */
711 if ( mark[phi] != J ) {
712 mark[phi] = J ;
713 if ( K > vtxToFront1[phi] ) {
714 /*
715 ------------------------------------
716 least numbered adjacent front so far
717 ------------------------------------
718 */
719 K = vtxToFront1[phi] ;
720 }
721 }
722 }
723 }
724 }
725 if ( K < nfront1 ) {
726 /*
727 --------------------
728 set the parent field
729 --------------------
730 */
731 par2[J] = nfront0 + K ;
732 }
733 }
734 /*
735 -----------------------------
736 set the remaining tree fields
737 -----------------------------
738 */
739 Tree_setFchSibRoot(etree2->tree) ;
740 /*
741 ------------------------
742 free the working storage
743 ------------------------
744 */
745 IVfree(head0) ;
746 IVfree(link0) ;
747 IVfree(mark) ;
748
749 return(etree2) ; }
750
751 /*--------------------------------------------------------------------*/
752