1 /* ========================================================================== */
2 /* === UMF_assemble ========================================================= */
3 /* ========================================================================== */
4
5 /* -------------------------------------------------------------------------- */
6 /* Copyright (c) 2005-2012 by Timothy A. Davis, http://www.suitesparse.com. */
7 /* All Rights Reserved. See ../Doc/License.txt for License. */
8 /* -------------------------------------------------------------------------- */
9
10 /* Degree update and numerical assembly. This is compiled twice (with and
11 * without FIXQ) for each real/complex int/SuiteSparse_long version, for a
12 * total of 8 versions.*/
13
14 #include "umf_internal.h"
15 #include "umf_assemble.h"
16 #include "umf_mem_free_tail_block.h"
17
18 /* ========================================================================== */
19 /* === row_assemble ========================================================= */
20 /* ========================================================================== */
21
row_assemble(Int row,NumericType * Numeric,WorkType * Work)22 PRIVATE void row_assemble
23 (
24 Int row,
25 NumericType *Numeric,
26 WorkType *Work
27 )
28 {
29
30 Entry *S, *Fcblock, *Frow ;
31 Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Row_tuples, *Row_tlen, rdeg0,
32 f, nrows, ncols, *Rows, *Cols, col, ncolsleft, j ;
33 Tuple *tp, *tp1, *tp2, *tpend ;
34 Unit *Memory, *p ;
35 Element *ep ;
36
37 #ifndef FIXQ
38 Int *Col_degree ;
39 Col_degree = Numeric->Cperm ;
40 #endif
41
42 Row_tuples = Numeric->Uip ;
43 tpi = Row_tuples [row] ;
44 if (!tpi) return ;
45
46 Memory = Numeric->Memory ;
47 E = Work->E ;
48 Fcpos = Work->Fcpos ;
49 Frpos = Work->Frpos ;
50 Row_degree = Numeric->Rperm ;
51 Row_tlen = Numeric->Uilen ;
52 E = Work->E ;
53 Memory = Numeric->Memory ;
54 rdeg0 = Work->rdeg0 ;
55 Fcblock = Work->Fcblock ;
56
57 #ifndef NDEBUG
58 DEBUG6 (("SCAN2-row: "ID"\n", row)) ;
59 UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
60 #endif
61
62 ASSERT (NON_PIVOTAL_ROW (row)) ;
63
64 tp = (Tuple *) (Memory + tpi) ;
65 tp1 = tp ;
66 tp2 = tp ;
67 tpend = tp + Row_tlen [row] ;
68 for ( ; tp < tpend ; tp++)
69 {
70 e = tp->e ;
71 ASSERT (e > 0 && e <= Work->nel) ;
72 if (!E [e]) continue ; /* element already deallocated */
73 f = tp->f ;
74 p = Memory + E [e] ;
75 ep = (Element *) p ;
76 p += UNITS (Element, 1) ;
77 Cols = (Int *) p ;
78 Rows = Cols + ep->ncols ;
79 if (Rows [f] == EMPTY) continue ; /* row already assembled */
80 ASSERT (row == Rows [f] && row >= 0 && row < Work->n_row) ;
81
82 if (ep->rdeg == rdeg0)
83 {
84 /* ------------------------------------------------------ */
85 /* this is an old Lson - assemble just one row */
86 /* ------------------------------------------------------ */
87
88 /* flag the row as assembled from the Lson */
89 Rows [f] = EMPTY ;
90
91 nrows = ep->nrows ;
92 ncols = ep->ncols ;
93
94 p += UNITS (Int, ncols + nrows) ;
95 S = ((Entry *) p) + f ;
96
97 DEBUG6 (("Old LSON: "ID"\n", e)) ;
98 #ifndef NDEBUG
99 UMF_dump_element (Numeric, Work, e, FALSE) ;
100 #endif
101
102 ncolsleft = ep->ncolsleft ;
103
104 Frow = Fcblock + Frpos [row] ;
105 DEBUG6 (("LSON found (in scan2-row): "ID"\n", e)) ;
106
107 Row_degree [row] -= ncolsleft ;
108
109 if (ncols == ncolsleft)
110 {
111 /* -------------------------------------------------- */
112 /* no columns assembled out this Lson yet */
113 /* -------------------------------------------------- */
114
115 #pragma ivdep
116 for (j = 0 ; j < ncols ; j++)
117 {
118 col = Cols [j] ;
119 ASSERT (col >= 0 && col < Work->n_col) ;
120 #ifndef FIXQ
121 Col_degree [col] -- ;
122 #endif
123 /* Frow [Fcpos [col]] += *S ; */
124 ASSEMBLE (Frow [Fcpos [col]], *S) ;
125 S += nrows ;
126 }
127
128 }
129 else
130 {
131 /* -------------------------------------------------- */
132 /* some columns have been assembled out of this Lson */
133 /* -------------------------------------------------- */
134
135 #pragma ivdep
136 for (j = 0 ; j < ncols ; j++)
137 {
138 col = Cols [j] ;
139 if (col >= 0)
140 {
141 ASSERT (col < Work->n_col) ;
142 #ifndef FIXQ
143 Col_degree [col] -- ;
144 #endif
145 /* Frow [Fcpos [col]] += *S ; */
146 ASSEMBLE (Frow [Fcpos [col]], *S) ;
147 }
148 S += nrows ;
149 }
150
151 }
152 ep->nrowsleft-- ;
153 ASSERT (ep->nrowsleft > 0) ;
154 }
155 else
156 {
157 *tp2++ = *tp ; /* leave the tuple in the list */
158 }
159 }
160 Row_tlen [row] = tp2 - tp1 ;
161
162 #ifndef NDEBUG
163 DEBUG7 (("row assembled in scan2-row: "ID"\n", row)) ;
164 UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
165 DEBUG7 (("Current frontal matrix: (scan 1b)\n")) ;
166 UMF_dump_current_front (Numeric, Work, TRUE) ;
167 #endif
168 }
169
170 /* ========================================================================== */
171 /* === col_assemble ========================================================= */
172 /* ========================================================================== */
173
col_assemble(Int col,NumericType * Numeric,WorkType * Work)174 PRIVATE void col_assemble
175 (
176 Int col,
177 NumericType *Numeric,
178 WorkType *Work
179 )
180 {
181
182 Entry *S, *Fcblock, *Fcol ;
183 Int tpi, e, *E, *Fcpos, *Frpos, *Row_degree, *Col_tuples, *Col_tlen, cdeg0,
184 f, nrows, ncols, *Rows, *Cols, row, nrowsleft, i ;
185 Tuple *tp, *tp1, *tp2, *tpend ;
186 Unit *Memory, *p ;
187 Element *ep ;
188
189 #if !defined (FIXQ) || !defined (NDEBUG)
190 Int *Col_degree ;
191 Col_degree = Numeric->Cperm ;
192 #endif
193
194 Col_tuples = Numeric->Lip ;
195 tpi = Col_tuples [col] ;
196 if (!tpi) return ;
197
198 Memory = Numeric->Memory ;
199 E = Work->E ;
200 Fcpos = Work->Fcpos ;
201 Frpos = Work->Frpos ;
202 Row_degree = Numeric->Rperm ;
203 Col_tlen = Numeric->Lilen ;
204 E = Work->E ;
205 Memory = Numeric->Memory ;
206 cdeg0 = Work->cdeg0 ;
207 Fcblock = Work->Fcblock ;
208
209 DEBUG6 (("SCAN2-col: "ID"\n", col)) ;
210 #ifndef NDEBUG
211 UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
212 #endif
213
214 ASSERT (NON_PIVOTAL_COL (col)) ;
215 tp = (Tuple *) (Memory + tpi) ;
216 tp1 = tp ;
217 tp2 = tp ;
218 tpend = tp + Col_tlen [col] ;
219 for ( ; tp < tpend ; tp++)
220 {
221 e = tp->e ;
222 ASSERT (e > 0 && e <= Work->nel) ;
223 if (!E [e]) continue ; /* element already deallocated */
224 f = tp->f ;
225 p = Memory + E [e] ;
226 ep = (Element *) p ;
227 p += UNITS (Element, 1) ;
228 Cols = (Int *) p ;
229
230 if (Cols [f] == EMPTY) continue ; /* col already assembled */
231 ASSERT (col == Cols [f] && col >= 0 && col < Work->n_col) ;
232
233 if (ep->cdeg == cdeg0)
234 {
235 /* ------------------------------------------------------ */
236 /* this is an old Uson - assemble just one col */
237 /* ------------------------------------------------------ */
238
239 /* flag the col as assembled from the Uson */
240 Cols [f] = EMPTY ;
241
242 nrows = ep->nrows ;
243 ncols = ep->ncols ;
244 Rows = Cols + ncols ;
245 p += UNITS (Int, ncols + nrows) ;
246 S = ((Entry *) p) + f * nrows ;
247
248 DEBUG6 (("Old USON: "ID"\n", e)) ;
249 #ifndef NDEBUG
250 UMF_dump_element (Numeric, Work, e, FALSE) ;
251 #endif
252
253 nrowsleft = ep->nrowsleft ;
254
255 Fcol = Fcblock + Fcpos [col] ;
256 DEBUG6 (("USON found (in scan2-col): "ID"\n", e)) ;
257 #ifndef FIXQ
258 Col_degree [col] -= nrowsleft ;
259 #endif
260 if (nrows == nrowsleft)
261 {
262 /* -------------------------------------------------- */
263 /* no rows assembled out of this Uson yet */
264 /* -------------------------------------------------- */
265
266 #pragma ivdep
267 for (i = 0 ; i < nrows ; i++)
268 {
269 row = Rows [i] ;
270 ASSERT (row >= 0 && row < Work->n_row) ;
271 Row_degree [row]-- ;
272 /* Fcol [Frpos [row]] += S [i] ; */
273 ASSEMBLE (Fcol [Frpos [row]], S [i]) ;
274 }
275 }
276 else
277 {
278 /* -------------------------------------------------- */
279 /* some rows have been assembled out of this Uson */
280 /* -------------------------------------------------- */
281
282 #pragma ivdep
283 for (i = 0 ; i < nrows ; i++)
284 {
285 row = Rows [i] ;
286 if (row >= 0)
287 {
288 ASSERT (row < Work->n_row) ;
289 Row_degree [row]-- ;
290 /* Fcol [Frpos [row]] += S [i] ; */
291 ASSEMBLE (Fcol [Frpos [row]], S [i]) ;
292 }
293 }
294 }
295 ep->ncolsleft-- ;
296 ASSERT (ep->ncolsleft > 0) ;
297 }
298 else
299 {
300 *tp2++ = *tp ; /* leave the tuple in the list */
301 }
302 }
303 Col_tlen [col] = tp2 - tp1 ;
304
305 #ifndef NDEBUG
306 DEBUG7 (("Column assembled in scan2-col: "ID"\n", col)) ;
307 UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
308 DEBUG7 (("Current frontal matrix: after scan2-col\n")) ;
309 UMF_dump_current_front (Numeric, Work, TRUE) ;
310 #endif
311
312 }
313
314
315 /* ========================================================================== */
316 /* === UMF_assemble / UMF_assemble_fixq ===================================== */
317 /* ========================================================================== */
318
319 #ifndef FIXQ
UMF_assemble(NumericType * Numeric,WorkType * Work)320 GLOBAL void UMF_assemble
321 #else
322 GLOBAL void UMF_assemble_fixq
323 #endif
324 (
325 NumericType *Numeric,
326 WorkType *Work
327 )
328 {
329 /* ---------------------------------------------------------------------- */
330 /* local variables */
331 /* ---------------------------------------------------------------------- */
332
333 Int e, i, row, col, i2, nrows, ncols, f, tpi, extcdeg, extrdeg, rdeg0,
334 cdeg0, son_list, next, nrows_to_assemble,
335 ncols_to_assemble, ngetrows, j, j2,
336 nrowsleft, /* number of rows remaining in S */
337 ncolsleft, /* number of columns remaining in S */
338 prior_Lson, prior_Uson, *E, *Cols, *Rows, *Wm, *Woo,
339 *Row_tuples, *Row_degree, *Row_tlen,
340 *Col_tuples, *Col_tlen ;
341 Unit *Memory, *p ;
342 Element *ep ;
343 Tuple *tp, *tp1, *tp2, *tpend ;
344 Entry
345 *S, /* a pointer into the contribution block of a son */
346 *Fcblock, /* current contribution block */
347 *Fcol ; /* a column of FC */
348 Int *Frpos,
349 *Fcpos,
350 fnrows, /* number of rows in contribution block in F */
351 fncols ; /* number of columns in contribution block in F */
352
353 #if !defined (FIXQ) || !defined (NDEBUG)
354 Int *Col_degree ;
355 #endif
356
357 #ifndef NDEBUG
358 Int n_row, n_col ;
359 n_row = Work->n_row ;
360 n_col = Work->n_col ;
361 DEBUG3 (("::Assemble SCANS 1-4\n")) ;
362 UMF_dump_current_front (Numeric, Work, TRUE) ;
363 #endif
364
365 #if !defined (FIXQ) || !defined (NDEBUG)
366 Col_degree = Numeric->Cperm ; /* not updated if FIXQ is true */
367 #endif
368
369 /* ---------------------------------------------------------------------- */
370 /* get parameters */
371 /* ---------------------------------------------------------------------- */
372
373 fncols = Work->fncols ;
374 fnrows = Work->fnrows ;
375 Fcpos = Work->Fcpos ;
376 Frpos = Work->Frpos ;
377 Row_degree = Numeric->Rperm ;
378 Row_tuples = Numeric->Uip ;
379 Row_tlen = Numeric->Uilen ;
380 Col_tuples = Numeric->Lip ;
381 Col_tlen = Numeric->Lilen ;
382 E = Work->E ;
383 Memory = Numeric->Memory ;
384 Wm = Work->Wm ;
385 Woo = Work->Woo ;
386 rdeg0 = Work->rdeg0 ;
387 cdeg0 = Work->cdeg0 ;
388
389 #ifndef NDEBUG
390 DEBUG6 (("============================================\n")) ;
391 DEBUG6 (("Degree update, assembly.\n")) ;
392 DEBUG6 (("pivot row pattern: fncols="ID"\n", fncols)) ;
393 for (j = 0 ; j < fncols ; j++)
394 {
395 col = Work->Fcols [j] ;
396 DEBUG6 ((ID" ", col)) ;
397 ASSERT (Fcpos [col] == j * Work->fnr_curr) ;
398 ASSERT (NON_PIVOTAL_COL (col)) ;
399 }
400 ASSERT (Fcpos [Work->pivcol] >= 0) ;
401 DEBUG6 (("pivcol: "ID" pos "ID" fnr_curr "ID" fncols "ID"\n",
402 Work->pivcol, Fcpos [Work->pivcol], Work->fnr_curr, fncols)) ;
403 ASSERT (Fcpos [Work->pivcol] < fncols * Work->fnr_curr) ;
404 DEBUG6 (("\npivot col pattern: fnrows="ID"\n", fnrows)) ;
405 for (i = 0 ; i < fnrows ; i++)
406 {
407 row = Work->Frows [i] ;
408 DEBUG6 ((ID" ", row)) ;
409 ASSERT (Frpos [row] == i) ;
410 ASSERT (NON_PIVOTAL_ROW (row)) ;
411 }
412 DEBUG6 (("\n")) ;
413 ASSERT (Frpos [Work->pivrow] >= 0) ;
414 ASSERT (Frpos [Work->pivrow] < fnrows) ;
415 ASSERT (Work->Flublock == (Entry *) (Numeric->Memory + E [0])) ;
416 ASSERT (Work->Fcblock == Work->Flublock + Work->nb *
417 (Work->nb + Work->fnr_curr + Work->fnc_curr)) ;
418 #endif
419
420 Fcblock = Work->Fcblock ;
421
422 /* ---------------------------------------------------------------------- */
423 /* determine the largest actual frontal matrix size (for Info only) */
424 /* ---------------------------------------------------------------------- */
425
426 ASSERT (fnrows == Work->fnrows_new + 1) ;
427 ASSERT (fncols == Work->fncols_new + 1) ;
428
429 Numeric->maxnrows = MAX (Numeric->maxnrows, fnrows) ;
430 Numeric->maxncols = MAX (Numeric->maxncols, fncols) ;
431
432 /* this is safe from integer overflow, since the current frontal matrix
433 * is already allocated. */
434 Numeric->maxfrsize = MAX (Numeric->maxfrsize, fnrows * fncols) ;
435
436 /* ---------------------------------------------------------------------- */
437 /* assemble from prior elements into the current frontal matrix */
438 /* ---------------------------------------------------------------------- */
439
440 DEBUG2 (("New assemble start [prior_element:"ID"\n", Work->prior_element)) ;
441
442 /* Currently no rows or columns are marked. No elements are scanned, */
443 /* that is, (ep->next == EMPTY) is true for all elements */
444
445 son_list = 0 ; /* start creating son_list [ */
446
447 /* ---------------------------------------------------------------------- */
448 /* determine if most recent element is Lson or Uson of current front */
449 /* ---------------------------------------------------------------------- */
450
451 if (!Work->do_extend)
452 {
453 prior_Uson = ( Work->pivcol_in_front && !Work->pivrow_in_front) ;
454 prior_Lson = (!Work->pivcol_in_front && Work->pivrow_in_front) ;
455 if (prior_Uson || prior_Lson)
456 {
457 e = Work->prior_element ;
458 if (e != EMPTY)
459 {
460 ASSERT (E [e]) ;
461 p = Memory + E [e] ;
462 ep = (Element *) p ;
463 ep->next = son_list ;
464 son_list = e ;
465 #ifndef NDEBUG
466 DEBUG2 (("e "ID" is Prior son "ID" "ID"\n",
467 e, prior_Uson, prior_Lson)) ;
468 UMF_dump_element (Numeric, Work, e, FALSE) ;
469 #endif
470 ASSERT (E [e]) ;
471 }
472 }
473 }
474 Work->prior_element = EMPTY ;
475
476 /* ---------------------------------------------------------------------- */
477 /* SCAN1-row: scan the element lists of each new row in the pivot col */
478 /* and compute the external column degree for each frontal */
479 /* ---------------------------------------------------------------------- */
480
481 for (i2 = Work->fscan_row ; i2 < fnrows ; i2++)
482 {
483 /* Get a row */
484 row = Work->NewRows [i2] ;
485 if (row < 0) row = FLIP (row) ;
486 ASSERT (row >= 0 && row < n_row) ;
487
488 DEBUG6 (("SCAN1-row: "ID"\n", row)) ;
489 #ifndef NDEBUG
490 UMF_dump_rowcol (0, Numeric, Work, row, FALSE) ;
491 #endif
492
493 ASSERT (NON_PIVOTAL_ROW (row)) ;
494 tpi = Row_tuples [row] ;
495 if (!tpi) continue ;
496 tp = (Tuple *) (Memory + tpi) ;
497 tp1 = tp ;
498 tp2 = tp ;
499 tpend = tp + Row_tlen [row] ;
500 for ( ; tp < tpend ; tp++)
501 {
502 e = tp->e ;
503 ASSERT (e > 0 && e <= Work->nel) ;
504 if (!E [e]) continue ; /* element already deallocated */
505 f = tp->f ;
506 p = Memory + E [e] ;
507 ep = (Element *) p ;
508 p += UNITS (Element, 1) ;
509 Rows = ((Int *) p) + ep->ncols ;
510 if (Rows [f] == EMPTY) continue ; /* row already assembled */
511 ASSERT (row == Rows [f]) ;
512
513 if (ep->cdeg < cdeg0)
514 {
515 /* first time seen in scan1-row */
516 ep->cdeg = ep->nrowsleft + cdeg0 ;
517 DEBUG6 (("e "ID" First seen: cdeg: "ID" ", e, ep->cdeg-cdeg0)) ;
518 ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ;
519 }
520
521 ep->cdeg-- ; /* decrement external column degree */
522 DEBUG6 (("e "ID" New ext col deg: "ID"\n", e, ep->cdeg - cdeg0)) ;
523
524 /* this element is not yet in the new son list */
525 if (ep->cdeg == cdeg0 && ep->next == EMPTY)
526 {
527 /* A new LUson or Uson has been found */
528 ep->next = son_list ;
529 son_list = e ;
530 }
531
532 ASSERT (ep->cdeg >= cdeg0) ;
533 *tp2++ = *tp ; /* leave the tuple in the list */
534 }
535 Row_tlen [row] = tp2 - tp1 ;
536 }
537
538 /* ---------------------------------------------------------------------- */
539 /* SCAN1-col: scan the element lists of each new col in the pivot row */
540 /* and compute the external row degree for each frontal */
541 /* ---------------------------------------------------------------------- */
542
543 for (j2 = Work->fscan_col ; j2 < fncols ; j2++)
544 {
545 /* Get a column */
546 col = Work->NewCols [j2] ;
547 if (col < 0) col = FLIP (col) ;
548 ASSERT (col >= 0 && col < n_col) ;
549
550 DEBUG6 (("SCAN 1-col: "ID"\n", col)) ;
551 #ifndef NDEBUG
552 UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
553 #endif
554
555 ASSERT (NON_PIVOTAL_COL (col)) ;
556 tpi = Col_tuples [col] ;
557 if (!tpi) continue ;
558 tp = (Tuple *) (Memory + tpi) ;
559 tp1 = tp ;
560 tp2 = tp ;
561 tpend = tp + Col_tlen [col] ;
562 for ( ; tp < tpend ; tp++)
563 {
564 e = tp->e ;
565 ASSERT (e > 0 && e <= Work->nel) ;
566 if (!E [e]) continue ; /* element already deallocated */
567 f = tp->f ;
568 p = Memory + E [e] ;
569 ep = (Element *) p ;
570 p += UNITS (Element, 1) ;
571 Cols = (Int *) p ;
572 if (Cols [f] == EMPTY) continue ; /* column already assembled */
573 ASSERT (col == Cols [f]) ;
574
575 if (ep->rdeg < rdeg0)
576 {
577 /* first time seen in scan1-col */
578 ep->rdeg = ep->ncolsleft + rdeg0 ;
579 DEBUG6 (("e "ID" First seen: rdeg: "ID" ", e, ep->rdeg-rdeg0)) ;
580 ASSERT (ep->ncolsleft > 0 && ep->nrowsleft > 0) ;
581 }
582
583 ep->rdeg-- ; /* decrement external row degree */
584 DEBUG6 (("e "ID" New ext row degree: "ID"\n", e, ep->rdeg-rdeg0)) ;
585
586 if (ep->rdeg == rdeg0 && ep->next == EMPTY)
587 {
588 /* A new LUson or Lson has been found */
589 ep->next = son_list ;
590 son_list = e ;
591 }
592
593 ASSERT (ep->rdeg >= rdeg0) ;
594 *tp2++ = *tp ; /* leave the tuple in the list */
595 }
596 Col_tlen [col] = tp2 - tp1 ;
597 }
598
599 /* ---------------------------------------------------------------------- */
600 /* assemble new sons via full scans */
601 /* ---------------------------------------------------------------------- */
602
603 next = EMPTY ;
604
605 for (e = son_list ; e > 0 ; e = next)
606 {
607 ASSERT (e > 0 && e <= Work->nel && E [e]) ;
608 p = Memory + E [e] ;
609 DEBUG2 (("New son: "ID"\n", e)) ;
610 #ifndef NDEBUG
611 UMF_dump_element (Numeric, Work, e, FALSE) ;
612 #endif
613 GET_ELEMENT (ep, p, Cols, Rows, ncols, nrows, S) ;
614 nrowsleft = ep->nrowsleft ;
615 ncolsleft = ep->ncolsleft ;
616 next = ep->next ;
617 ep->next = EMPTY ;
618
619 extrdeg = (ep->rdeg < rdeg0) ? ncolsleft : (ep->rdeg - rdeg0) ;
620 extcdeg = (ep->cdeg < cdeg0) ? nrowsleft : (ep->cdeg - cdeg0) ;
621 ncols_to_assemble = ncolsleft - extrdeg ;
622 nrows_to_assemble = nrowsleft - extcdeg ;
623 DEBUG2 (("extrdeg "ID" extcdeg "ID"\n", extrdeg, extcdeg)) ;
624
625 if (extrdeg == 0 && extcdeg == 0)
626 {
627
628 /* -------------------------------------------------------------- */
629 /* this is an LUson - assemble an entire contribution block */
630 /* -------------------------------------------------------------- */
631
632 DEBUG6 (("LUson found: "ID"\n", e)) ;
633
634 if (nrows == nrowsleft)
635 {
636 /* ---------------------------------------------------------- */
637 /* no rows assembled out of this LUson yet */
638 /* ---------------------------------------------------------- */
639
640 /* compute the compressed column offset vector*/
641 /* [ use Wm [0..nrows-1] for offsets */
642 #pragma ivdep
643 for (i = 0 ; i < nrows ; i++)
644 {
645 row = Rows [i] ;
646 Row_degree [row] -= ncolsleft ;
647 Wm [i] = Frpos [row] ;
648 }
649
650 if (ncols == ncolsleft)
651 {
652 /* ------------------------------------------------------ */
653 /* no rows or cols assembled out of LUson yet */
654 /* ------------------------------------------------------ */
655
656 for (j = 0 ; j < ncols ; j++)
657 {
658 col = Cols [j] ;
659 #ifndef FIXQ
660 Col_degree [col] -= nrowsleft ;
661 #endif
662 Fcol = Fcblock + Fcpos [col] ;
663 #pragma ivdep
664 for (i = 0 ; i < nrows ; i++)
665 {
666 /* Fcol [Wm [i]] += S [i] ; */
667 ASSEMBLE (Fcol [Wm [i]], S [i]) ;
668 }
669 S += nrows ;
670 }
671
672
673 }
674 else
675 {
676 /* ------------------------------------------------------ */
677 /* only cols have been assembled out of LUson */
678 /* ------------------------------------------------------ */
679
680 for (j = 0 ; j < ncols ; j++)
681 {
682 col = Cols [j] ;
683 if (col >= 0)
684 {
685 #ifndef FIXQ
686 Col_degree [col] -= nrowsleft ;
687 #endif
688 Fcol = Fcblock + Fcpos [col] ;
689 #pragma ivdep
690 for (i = 0 ; i < nrows ; i++)
691 {
692 /* Fcol [Wm [i]] += S [i] ; */
693 ASSEMBLE (Fcol [Wm [i]], S [i]) ;
694 }
695 }
696 S += nrows ;
697 }
698
699 }
700 /* ] done using Wm [0..nrows-1] for offsets */
701 }
702 else
703 {
704 /* ---------------------------------------------------------- */
705 /* some rows have been assembled out of this LUson */
706 /* ---------------------------------------------------------- */
707
708 /* compute the compressed column offset vector*/
709 /* [ use Woo,Wm [0..nrowsleft-1] for offsets */
710 ngetrows = 0 ;
711 for (i = 0 ; i < nrows ; i++)
712 {
713 row = Rows [i] ;
714 if (row >= 0)
715 {
716 Row_degree [row] -= ncolsleft ;
717 Woo [ngetrows] = i ;
718 Wm [ngetrows++] = Frpos [row] ;
719 }
720 }
721 ASSERT (ngetrows == nrowsleft) ;
722
723 if (ncols == ncolsleft)
724 {
725 /* ------------------------------------------------------ */
726 /* only rows have been assembled out of this LUson */
727 /* ------------------------------------------------------ */
728
729 for (j = 0 ; j < ncols ; j++)
730 {
731 col = Cols [j] ;
732 #ifndef FIXQ
733 Col_degree [col] -= nrowsleft ;
734 #endif
735 Fcol = Fcblock + Fcpos [col] ;
736 #pragma ivdep
737 for (i = 0 ; i < nrowsleft ; i++)
738 {
739 /* Fcol [Wm [i]] += S [Woo [i]] ; */
740 ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
741 }
742 S += nrows ;
743 }
744
745 }
746 else
747 {
748 /* ------------------------------------------------------ */
749 /* both rows and columns have been assembled out of LUson */
750 /* ------------------------------------------------------ */
751
752 for (j = 0 ; j < ncols ; j++)
753 {
754 col = Cols [j] ;
755 if (col >= 0)
756 {
757 #ifndef FIXQ
758 Col_degree [col] -= nrowsleft ;
759 #endif
760 Fcol = Fcblock + Fcpos [col] ;
761 #pragma ivdep
762 for (i = 0 ; i < nrowsleft ; i++)
763 {
764 /* Fcol [Wm [i]] += S [Woo [i]] ; */
765 ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
766 }
767 }
768 S += nrows ;
769 }
770
771 }
772 /* ] done using Woo,Wm [0..nrowsleft-1] */
773 }
774
775 /* deallocate the element: remove from ordered list */
776 UMF_mem_free_tail_block (Numeric, E [e]) ;
777 E [e] = 0 ;
778
779 }
780 else if (extcdeg == 0)
781 {
782
783 /* -------------------------------------------------------------- */
784 /* this is a Uson - assemble all possible columns */
785 /* -------------------------------------------------------------- */
786
787 DEBUG6 (("New USON: "ID"\n", e)) ;
788 ASSERT (extrdeg > 0) ;
789
790 DEBUG6 (("New uson "ID" cols to do "ID"\n", e, ncols_to_assemble)) ;
791
792 if (ncols_to_assemble > 0)
793 {
794
795 Int skip = FALSE ;
796 if (ncols_to_assemble * 16 < ncols && nrows == 1)
797 {
798 /* this is a tall and thin frontal matrix consisting of
799 * only one column (most likely an original column). Do
800 * not assemble it. It cannot be the pivot column, since
801 * the pivot column element would be an LU son, not an Lson,
802 * of the current frontal matrix. */
803 ASSERT (nrowsleft == 1) ;
804 ASSERT (Rows [0] >= 0 && Rows [0] < Work->n_row) ;
805 skip = TRUE ;
806 Work->any_skip = TRUE ;
807 }
808
809 if (!skip)
810 {
811
812 if (nrows == nrowsleft)
813 {
814 /* -------------------------------------------------- */
815 /* no rows have been assembled out of this Uson yet */
816 /* -------------------------------------------------- */
817
818 /* compute the compressed column offset vector */
819 /* [ use Wm [0..nrows-1] for offsets */
820 #pragma ivdep
821 for (i = 0 ; i < nrows ; i++)
822 {
823 row = Rows [i] ;
824 ASSERT (row >= 0 && row < n_row) ;
825 Row_degree [row] -= ncols_to_assemble ;
826 Wm [i] = Frpos [row] ;
827 }
828
829 for (j = 0 ; j < ncols ; j++)
830 {
831 col = Cols [j] ;
832 if ((col >= 0) && (Fcpos [col] >= 0))
833 {
834 #ifndef FIXQ
835 Col_degree [col] -= nrowsleft ;
836 #endif
837 Fcol = Fcblock + Fcpos [col] ;
838 #pragma ivdep
839 for (i = 0 ; i < nrows ; i++)
840 {
841 /* Fcol [Wm [i]] += S [i] ; */
842 ASSEMBLE (Fcol [Wm [i]], S [i]) ;
843 }
844 /* flag the column as assembled from Uson */
845 Cols [j] = EMPTY ;
846 }
847 S += nrows ;
848 }
849
850
851 /* ] done using Wm [0..nrows-1] for offsets */
852 }
853 else
854 {
855 /* -------------------------------------------------- */
856 /* some rows have been assembled out of this Uson */
857 /* -------------------------------------------------- */
858
859 /* compute the compressed column offset vector*/
860 /* [ use Woo,Wm [0..nrows-1] for offsets */
861 ngetrows = 0 ;
862 for (i = 0 ; i < nrows ; i++)
863 {
864 row = Rows [i] ;
865 if (row >= 0)
866 {
867 Row_degree [row] -= ncols_to_assemble ;
868 ASSERT (row < n_row && Frpos [row] >= 0) ;
869 Woo [ngetrows] = i ;
870 Wm [ngetrows++] = Frpos [row] ;
871 }
872 }
873 ASSERT (ngetrows == nrowsleft) ;
874
875 for (j = 0 ; j < ncols ; j++)
876 {
877 col = Cols [j] ;
878 if ((col >= 0) && (Fcpos [col] >= 0))
879 {
880 #ifndef FIXQ
881 Col_degree [col] -= nrowsleft ;
882 #endif
883 Fcol = Fcblock + Fcpos [col] ;
884 #pragma ivdep
885 for (i = 0 ; i < nrowsleft ; i++)
886 {
887 /* Fcol [Wm [i]] += S [Woo [i]] ; */
888 ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
889 }
890 /* flag the column as assembled from Uson */
891 Cols [j] = EMPTY ;
892 }
893 S += nrows ;
894 }
895
896 /* ] done using Woo,Wm */
897 }
898 ep->ncolsleft = extrdeg ;
899 }
900 }
901
902 }
903 else
904 {
905
906 /* -------------------------------------------------------------- */
907 /* this is an Lson - assemble all possible rows */
908 /* -------------------------------------------------------------- */
909
910 DEBUG6 (("New LSON: "ID"\n", e)) ;
911 ASSERT (extrdeg == 0 && extcdeg > 0) ;
912
913 DEBUG6 (("New lson "ID" rows to do "ID"\n", e, nrows_to_assemble)) ;
914
915 if (nrows_to_assemble > 0)
916 {
917
918 Int skip = FALSE ;
919 if (nrows_to_assemble * 16 < nrows && ncols == 1)
920 {
921 /* this is a tall and thin frontal matrix consisting of
922 * only one column (most likely an original column). Do
923 * not assemble it. It cannot be the pivot column, since
924 * the pivot column element would be an LU son, not an Lson,
925 * of the current frontal matrix. */
926 ASSERT (ncolsleft == 1) ;
927 ASSERT (Cols [0] >= 0 && Cols [0] < Work->n_col) ;
928 Work->any_skip = TRUE ;
929 skip = TRUE ;
930 }
931
932 if (!skip)
933 {
934
935 /* compute the compressed column offset vector */
936 /* [ use Woo,Wm [0..nrows-1] for offsets */
937 ngetrows = 0 ;
938 for (i = 0 ; i < nrows ; i++)
939 {
940 row = Rows [i] ;
941 if ((row >= 0) && (Frpos [row] >= 0))
942 {
943 ASSERT (row < n_row) ;
944 Row_degree [row] -= ncolsleft ;
945 Woo [ngetrows] = i ;
946 Wm [ngetrows++] = Frpos [row] ;
947 /* flag the row as assembled from the Lson */
948 Rows [i] = EMPTY ;
949 }
950 }
951 ASSERT (nrowsleft - ngetrows == extcdeg) ;
952 ASSERT (ngetrows == nrows_to_assemble) ;
953
954 if (ncols == ncolsleft)
955 {
956 /* -------------------------------------------------- */
957 /* no columns assembled out this Lson yet */
958 /* -------------------------------------------------- */
959
960 for (j = 0 ; j < ncols ; j++)
961 {
962 col = Cols [j] ;
963 ASSERT (col >= 0 && col < n_col) ;
964 #ifndef FIXQ
965 Col_degree [col] -= nrows_to_assemble ;
966 #endif
967 Fcol = Fcblock + Fcpos [col] ;
968 #pragma ivdep
969 for (i = 0 ; i < nrows_to_assemble ; i++)
970 {
971 /* Fcol [Wm [i]] += S [Woo [i]] ; */
972 ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
973 }
974 S += nrows ;
975 }
976
977
978 }
979 else
980 {
981 /* -------------------------------------------------- */
982 /* some columns have been assembled out of this Lson */
983 /* -------------------------------------------------- */
984
985 for (j = 0 ; j < ncols ; j++)
986 {
987 col = Cols [j] ;
988 ASSERT (col < n_col) ;
989 if (col >= 0)
990 {
991 #ifndef FIXQ
992 Col_degree [col] -= nrows_to_assemble ;
993 #endif
994 Fcol = Fcblock + Fcpos [col] ;
995 #pragma ivdep
996 for (i = 0 ; i < nrows_to_assemble ; i++)
997 {
998 /* Fcol [Wm [i]] += S [Woo [i]] ; */
999 ASSEMBLE (Fcol [Wm [i]], S [Woo [i]]) ;
1000 }
1001 }
1002 S += nrows ;
1003 }
1004
1005 }
1006
1007 /* ] done using Woo,Wm */
1008
1009 ep->nrowsleft = extcdeg ;
1010 }
1011 }
1012 }
1013 }
1014
1015 /* Note that garbage collection, and build tuples */
1016 /* both destroy the son list. */
1017
1018 /* ] son_list now empty */
1019
1020 /* ---------------------------------------------------------------------- */
1021 /* If frontal matrix extended, assemble old L/Usons from new rows/cols */
1022 /* ---------------------------------------------------------------------- */
1023
1024 /* ---------------------------------------------------------------------- */
1025 /* SCAN2-row: assemble rows of old Lsons from the new rows */
1026 /* ---------------------------------------------------------------------- */
1027
1028 #ifndef NDEBUG
1029 DEBUG7 (("Current frontal matrix: (prior to scan2-row)\n")) ;
1030 UMF_dump_current_front (Numeric, Work, TRUE) ;
1031 #endif
1032
1033 /* rescan the pivot row */
1034 if (Work->any_skip)
1035 {
1036 row_assemble (Work->pivrow, Numeric, Work) ;
1037 }
1038
1039 if (Work->do_scan2row)
1040 {
1041 for (i2 = Work->fscan_row ; i2 < fnrows ; i2++)
1042 {
1043 /* Get a row */
1044 row = Work->NewRows [i2] ;
1045 if (row < 0) row = FLIP (row) ;
1046 ASSERT (row >= 0 && row < n_row) ;
1047 if (!(row == Work->pivrow && Work->any_skip))
1048 {
1049 /* assemble it */
1050 row_assemble (row, Numeric, Work) ;
1051 }
1052 }
1053 }
1054
1055 /* ---------------------------------------------------------------------- */
1056 /* SCAN2-col: assemble columns of old Usons from the new columns */
1057 /* ---------------------------------------------------------------------- */
1058
1059 #ifndef NDEBUG
1060 DEBUG7 (("Current frontal matrix: (prior to scan2-col)\n")) ;
1061 UMF_dump_current_front (Numeric, Work, TRUE) ;
1062 #endif
1063
1064 /* rescan the pivot col */
1065 if (Work->any_skip)
1066 {
1067 col_assemble (Work->pivcol, Numeric, Work) ;
1068 }
1069
1070 if (Work->do_scan2col)
1071 {
1072
1073 for (j2 = Work->fscan_col ; j2 < fncols ; j2++)
1074 {
1075 /* Get a column */
1076 col = Work->NewCols [j2] ;
1077 if (col < 0) col = FLIP (col) ;
1078 ASSERT (col >= 0 && col < n_col) ;
1079 if (!(col == Work->pivcol && Work->any_skip))
1080 {
1081 /* assemble it */
1082 col_assemble (col, Numeric, Work) ;
1083 }
1084 }
1085 }
1086
1087 /* ---------------------------------------------------------------------- */
1088 /* done. the remainder of this routine is used only when in debug mode */
1089 /* ---------------------------------------------------------------------- */
1090
1091 #ifndef NDEBUG
1092
1093 /* ---------------------------------------------------------------------- */
1094 /* when debugging: make sure the assembly did everything that it could */
1095 /* ---------------------------------------------------------------------- */
1096
1097 DEBUG3 (("::Assemble done\n")) ;
1098
1099 for (i2 = 0 ; i2 < fnrows ; i2++)
1100 {
1101 /* Get a row */
1102 row = Work->Frows [i2] ;
1103 ASSERT (row >= 0 && row < n_row) ;
1104
1105 DEBUG6 (("DEBUG SCAN 1: "ID"\n", row)) ;
1106 UMF_dump_rowcol (0, Numeric, Work, row, TRUE) ;
1107
1108 ASSERT (NON_PIVOTAL_ROW (row)) ;
1109 tpi = Row_tuples [row] ;
1110 if (!tpi) continue ;
1111 tp = (Tuple *) (Memory + tpi) ;
1112 tpend = tp + Row_tlen [row] ;
1113 for ( ; tp < tpend ; tp++)
1114 {
1115 e = tp->e ;
1116 ASSERT (e > 0 && e <= Work->nel) ;
1117 if (!E [e]) continue ; /* element already deallocated */
1118 f = tp->f ;
1119 p = Memory + E [e] ;
1120 ep = (Element *) p ;
1121 p += UNITS (Element, 1) ;
1122 Cols = (Int *) p ;
1123 Rows = ((Int *) p) + ep->ncols ;
1124 if (Rows [f] == EMPTY) continue ; /* row already assembled */
1125 ASSERT (row == Rows [f]) ;
1126 extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ;
1127 extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ;
1128 DEBUG6 ((
1129 "e "ID" After assembly ext row deg: "ID" ext col degree "ID"\n",
1130 e, extrdeg, extcdeg)) ;
1131
1132 if (Work->any_skip)
1133 {
1134 /* no Lsons in any row, except for very tall and thin ones */
1135 ASSERT (extrdeg >= 0) ;
1136 if (extrdeg == 0)
1137 {
1138 /* this is an unassemble Lson */
1139 ASSERT (ep->ncols == 1) ;
1140 ASSERT (ep->ncolsleft == 1) ;
1141 col = Cols [0] ;
1142 ASSERT (col != Work->pivcol) ;
1143 }
1144 }
1145 else
1146 {
1147 /* no Lsons in any row */
1148 ASSERT (extrdeg > 0) ;
1149 /* Uson external row degree is = number of cols left */
1150 ASSERT (IMPLIES (extcdeg == 0, extrdeg == ep->ncolsleft)) ;
1151 }
1152 }
1153 }
1154
1155 /* ---------------------------------------------------------------------- */
1156
1157 for (j2 = 0 ; j2 < fncols ; j2++)
1158 {
1159 /* Get a column */
1160 col = Work->Fcols [j2] ;
1161 ASSERT (col >= 0 && col < n_col) ;
1162
1163 DEBUG6 (("DEBUG SCAN 2: "ID"\n", col)) ;
1164 #ifndef FIXQ
1165 UMF_dump_rowcol (1, Numeric, Work, col, TRUE) ;
1166 #else
1167 UMF_dump_rowcol (1, Numeric, Work, col, FALSE) ;
1168 #endif
1169
1170 ASSERT (NON_PIVOTAL_COL (col)) ;
1171 tpi = Col_tuples [col] ;
1172 if (!tpi) continue ;
1173 tp = (Tuple *) (Memory + tpi) ;
1174 tpend = tp + Col_tlen [col] ;
1175 for ( ; tp < tpend ; tp++)
1176 {
1177 e = tp->e ;
1178 ASSERT (e > 0 && e <= Work->nel) ;
1179 if (!E [e]) continue ; /* element already deallocated */
1180 f = tp->f ;
1181 p = Memory + E [e] ;
1182 ep = (Element *) p ;
1183 p += UNITS (Element, 1) ;
1184 Cols = (Int *) p ;
1185 Rows = ((Int *) p) + ep->ncols ;
1186 if (Cols [f] == EMPTY) continue ; /* column already assembled */
1187 ASSERT (col == Cols [f]) ;
1188 extrdeg = (ep->rdeg < rdeg0) ? ep->ncolsleft : (ep->rdeg - rdeg0) ;
1189 extcdeg = (ep->cdeg < cdeg0) ? ep->nrowsleft : (ep->cdeg - cdeg0) ;
1190 DEBUG6 (("e "ID" After assembly ext col deg: "ID"\n", e, extcdeg)) ;
1191
1192 if (Work->any_skip)
1193 {
1194 /* no Usons in any column, except for very tall and thin ones */
1195 ASSERT (extcdeg >= 0) ;
1196 if (extcdeg == 0)
1197 {
1198 /* this is an unassemble Uson */
1199 ASSERT (ep->nrows == 1) ;
1200 ASSERT (ep->nrowsleft == 1) ;
1201 row = Rows [0] ;
1202 ASSERT (row != Work->pivrow) ;
1203 }
1204 }
1205 else
1206 {
1207 /* no Usons in any column */
1208 ASSERT (extcdeg > 0) ;
1209 /* Lson external column degree is = number of rows left */
1210 ASSERT (IMPLIES (extrdeg == 0, extcdeg == ep->nrowsleft)) ;
1211 }
1212 }
1213 }
1214 #endif /* NDEBUG */
1215 }
1216