1 /*  QRutil.c  */
2 
3 #include "../FrontMtx.h"
4 #include "../../timings.h"
5 
6 /*--------------------------------------------------------------------*/
7 /*
8    --------------------------------------------------------------------
9    purpose -- to setup two data structures for a QR serial
10               or multithreaded factorization
11 
12    rowsIVL[J]    -- list of rows of A to be assembled into front J
13    firstnz[irow] -- column with location of leading nonzero of row in A
14 
15    created -- 98may29, cca
16    --------------------------------------------------------------------
17 */
18 void
FrontMtx_QR_setup(FrontMtx * frontmtx,InpMtx * mtxA,IVL ** prowsIVL,int ** pfirstnz,int msglvl,FILE * msgFile)19 FrontMtx_QR_setup (
20    FrontMtx   *frontmtx,
21    InpMtx     *mtxA,
22    IVL        **prowsIVL,
23    int        **pfirstnz,
24    int        msglvl,
25    FILE       *msgFile
26 ) {
27 int   count, irow, jcol, J, loc, neqns, nfront, nrowA, rowsize ;
28 int   *firstnz, *head, *link, *list, *rowind, *vtxToFront ;
29 IVL   *rowsIVL ;
30 /*
31    ---------------
32    check the input
33    ---------------
34 */
35 if ( frontmtx == NULL || mtxA == NULL || prowsIVL == NULL
36    || pfirstnz == NULL || (msglvl > 0 && msgFile == NULL) ) {
37    fprintf(stderr, "\n fatal error in FrontMtx_QR_setup()"
38            "\n bad input\n") ;
39    exit(-1) ;
40 }
41 neqns      = FrontMtx_neqns(frontmtx) ;
42 nfront     = FrontMtx_nfront(frontmtx) ;
43 vtxToFront = ETree_vtxToFront(frontmtx->frontETree) ;
44 /*
45    ----------------------------------------------------------------
46    create the rowsIVL object,
47    list(J) = list of rows that are assembled in front J
48    firstnz[irowA] = first column with nonzero element in A(irowA,*)
49    ----------------------------------------------------------------
50 */
51 InpMtx_changeCoordType(mtxA, INPMTX_BY_ROWS) ;
52 InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS) ;
53 nrowA = 1 + IVmax(InpMtx_nent(mtxA), InpMtx_ivec1(mtxA), &loc) ;
54 if ( msglvl > 3 ) {
55    fprintf(msgFile, "\n nrowA = %d ", nrowA) ;
56    fflush(msgFile) ;
57 }
58 firstnz = IVinit(nrowA, -1) ;
59 head    = IVinit(nfront, -1) ;
60 link    = IVinit(nrowA, -1) ;
61 for ( irow = nrowA - 1 ; irow >= 0 ; irow-- ) {
62    InpMtx_vector(mtxA, irow, &rowsize, &rowind) ;
63    if ( rowsize > 0 ) {
64       firstnz[irow] = jcol = rowind[0] ;
65       J             = vtxToFront[jcol] ;
66       link[irow]    = head[J]          ;
67       head[J]       = irow             ;
68    }
69 }
70 rowsIVL = IVL_new() ;
71 IVL_init2(rowsIVL, IVL_CHUNKED, nfront, nrowA) ;
72 list = IVinit(neqns, -1) ;
73 for ( J = 0 ; J < nfront ; J++ ) {
74    count = 0 ;
75    for ( irow = head[J] ; irow != -1 ; irow = link[irow] ) {
76       list[count++] = irow ;
77    }
78    if ( count > 0 ) {
79       IVL_setList(rowsIVL, J, count, list) ;
80    }
81 }
82 IVfree(head) ;
83 IVfree(link) ;
84 IVfree(list) ;
85 /*
86    ---------------------------
87    set the pointers for return
88    ---------------------------
89 */
90 *prowsIVL = rowsIVL ;
91 *pfirstnz = firstnz ;
92 
93 return ; }
94 
95 /*--------------------------------------------------------------------*/
96 /*
97    -----------------------------------------------
98    purpose --  visit front J during a serial
99                or multithreaded QR factorization
100 
101    cpus[1] -- initialize and load staircase matrix
102    cpus[2] -- factor the matrix
103    cpus[3] -- scale and store factor entries
104    cpus[4] -- store update entries
105 
106    created -- 98may28, cca
107    -----------------------------------------------
108 */
109 void
FrontMtx_QR_factorVisit(FrontMtx * frontmtx,int J,InpMtx * mtxA,IVL * rowsIVL,int firstnz[],ChvList * updlist,ChvManager * chvmanager,char status[],int colmap[],DV * workDV,double cpus[],double * pfacops,int msglvl,FILE * msgFile)110 FrontMtx_QR_factorVisit (
111    FrontMtx     *frontmtx,
112    int          J,
113    InpMtx       *mtxA,
114    IVL          *rowsIVL,
115    int          firstnz[],
116    ChvList      *updlist,
117    ChvManager   *chvmanager,
118    char         status[],
119    int          colmap[],
120    DV           *workDV,
121    double       cpus[],
122    double       *pfacops,
123    int          msglvl,
124    FILE         *msgFile
125 ) {
126 /*
127    ---------------
128    check the input
129    ---------------
130 */
131 if ( frontmtx == NULL || mtxA == NULL || rowsIVL == NULL
132      || firstnz == NULL || updlist == NULL || chvmanager == NULL
133      || status == NULL || colmap == NULL || workDV == NULL
134      || cpus == NULL || pfacops == NULL
135      || (msglvl > 0 && msgFile == NULL) ) {
136    fprintf(msgFile, "\n fatal error in FrontMtx_QR_factorVisit(%d)"
137            "\n bad input\n", J) ;
138    exit(-1) ;
139 }
140 /*
141    ------------------------------------------------------------
142    check to see if all incoming updates are present in the list
143    ------------------------------------------------------------
144 */
145 if ( ChvList_isCountZero(updlist, J) == 1 ) {
146    A2       *frontJ ;
147    Chv      *firstchild, *updchv ;
148    double   ops, t1, t2 ;
149    int      K ;
150 /*
151    ----------------------------------------
152    everything is ready to factor this front
153    ----------------------------------------
154 */
155    firstchild = ChvList_getList(updlist, J) ;
156 /*
157    ----------------------------------------
158    initialize and load the staircase matrix
159    ----------------------------------------
160 */
161    MARKTIME(t1) ;
162    frontJ = FrontMtx_QR_assembleFront(frontmtx, J, mtxA, rowsIVL,
163                                       firstnz, colmap, firstchild,
164                                       workDV, msglvl, msgFile) ;
165    if ( firstchild != NULL ) {
166       ChvManager_releaseListOfObjects(chvmanager, firstchild) ;
167    }
168    MARKTIME(t2) ;
169    cpus[1] += t2 - t1 ;
170    if ( msglvl > 3 ) {
171       fprintf(msgFile, "\n\n after assembling front") ;
172       A2_writeForHumanEye(frontJ, msgFile) ;
173       fflush(msgFile) ;
174    }
175 /*
176    ---------------------------
177    factor the staircase matrix
178    ---------------------------
179 */
180    MARKTIME(t1) ;
181    ops = A2_QRreduce(frontJ, workDV, msglvl, msgFile) ;
182    *pfacops += ops ;
183    MARKTIME(t2) ;
184    cpus[2] += t2 - t1 ;
185    if ( msglvl > 3 ) {
186       fprintf(msgFile, "\n\n after factoring") ;
187       A2_writeForHumanEye(frontJ, msgFile) ;
188       fflush(msgFile) ;
189    }
190 /*
191    ----------------------------------
192    scale and store the factor entries
193    ----------------------------------
194 */
195    MARKTIME(t1) ;
196    FrontMtx_QR_storeFront(frontmtx, J, frontJ, msglvl, msgFile) ;
197    MARKTIME(t2) ;
198    cpus[3] += t2 - t1 ;
199    if ( msglvl > 3 ) {
200       fprintf(msgFile, "\n\n after storing factor entries") ;
201       A2_writeForHumanEye(frontJ, msgFile) ;
202       fflush(msgFile) ;
203    }
204 /*
205    -----------------------
206    store the update matrix
207    -----------------------
208 */
209    if ( (K = frontmtx->tree->par[J]) != -1 ) {
210       MARKTIME(t1) ;
211       updchv = FrontMtx_QR_storeUpdate(frontmtx, J, frontJ, chvmanager,
212                                        msglvl, msgFile) ;
213       ChvList_addObjectToList(updlist, updchv, K) ;
214       MARKTIME(t2) ;
215       cpus[4] += t2 - t1 ;
216       if ( msglvl > 3 ) {
217          fprintf(msgFile, "\n\n after storing update entries") ;
218          A2_writeForHumanEye(frontJ, msgFile) ;
219          fflush(msgFile) ;
220       }
221    }
222 /*
223    -------------------------
224    free the staircase matrix
225    -------------------------
226 */
227    A2_free(frontJ) ;
228 /*
229    -------------------------------------
230    set the status as finished and return
231    -------------------------------------
232 */
233    status[J] = 'F' ;
234 }
235 return ; }
236 
237 /*--------------------------------------------------------------------*/
238 /*
239    --------------------------------------------------------------
240    purpose -- create and return an A2 object that contains rows
241               of A and rows from update matrices of the children.
242               the matrix may not be in staircase form
243 
244    created -- 98may25, cca
245    --------------------------------------------------------------
246 */
247 A2 *
FrontMtx_QR_assembleFront(FrontMtx * frontmtx,int J,InpMtx * mtxA,IVL * rowsIVL,int firstnz[],int colmap[],Chv * firstchild,DV * workDV,int msglvl,FILE * msgFile)248 FrontMtx_QR_assembleFront (
249    FrontMtx   *frontmtx,
250    int        J,
251    InpMtx     *mtxA,
252    IVL        *rowsIVL,
253    int        firstnz[],
254    int        colmap[],
255    Chv        *firstchild,
256    DV         *workDV,
257    int        msglvl,
258    FILE       *msgFile
259 ) {
260 A2       *frontJ ;
261 Chv      *chvI ;
262 double   *rowI, *rowJ, *rowentA ;
263 int      ii, irow, irowA, irowI, jcol, jj, jrow, ncolI, ncolJ,
264          nentA, nrowI, nrowJ, nrowFromA ;
265 int      *colindA, *colindI, *colindJ, *map, *rowids, *rowsFromA ;
266 /*
267    ---------------
268    check the input
269    ---------------
270 */
271 if ( frontmtx == NULL || mtxA == NULL || rowsIVL == NULL
272    || (msglvl > 0 && msgFile == NULL) ) {
273    fprintf(stderr, "\n fatal error in FrontMtx_QR_assembleFront()"
274            "\n bad input\n") ;
275    exit(-1) ;
276 }
277 if ( msglvl > 3 ) {
278    fprintf(msgFile, "\n\n inside FrontMtx_QR_assembleFront(%d)", J) ;
279    fflush(msgFile) ;
280 }
281 /*
282    --------------------------------------------------
283    set up the map from global to local column indices
284    --------------------------------------------------
285 */
286 FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
287 for ( jcol = 0 ; jcol < ncolJ ; jcol++ ) {
288    colmap[colindJ[jcol]] = jcol ;
289 }
290 if ( msglvl > 3 ) {
291    fprintf(msgFile, "\n front %d's column indices", J) ;
292    IVfprintf(msgFile, ncolJ, colindJ) ;
293    fflush(msgFile) ;
294 }
295 /*
296    -------------------------------------------------
297    compute the size of the front and map the global
298    indices of the update matrices into local indices
299    -------------------------------------------------
300 */
301 IVL_listAndSize(rowsIVL, J, &nrowFromA, &rowsFromA) ;
302 nrowJ = nrowFromA ;
303 if ( msglvl > 3 ) {
304    fprintf(msgFile, "\n %d rows from A", nrowFromA) ;
305    fflush(msgFile) ;
306 }
307 for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
308    nrowJ += chvI->nD ;
309    Chv_columnIndices(chvI, &ncolI, &colindI) ;
310    for ( jcol = 0 ; jcol < ncolI ; jcol++ ) {
311       colindI[jcol] = colmap[colindI[jcol]] ;
312    }
313    if ( msglvl > 3 ) {
314       fprintf(msgFile, "\n %d rows from child %d", chvI->nD, chvI->id) ;
315       fflush(msgFile) ;
316    }
317 }
318 /*
319    ----------------------------------------------------------
320    get workspace for the rowids[nrowJ] and map[nrowJ] vectors
321    ----------------------------------------------------------
322 */
323 if ( sizeof(int) == sizeof(double) ) {
324    DV_setSize(workDV, 2*nrowJ) ;
325 } else if ( 2*sizeof(int) == sizeof(double) ) {
326    DV_setSize(workDV, nrowJ) ;
327 }
328 rowids = (int *) DV_entries(workDV) ;
329 map    = rowids + nrowJ ;
330 IVramp(nrowJ, rowids, 0, 1) ;
331 IVfill(nrowJ, map, -1) ;
332 /*
333    -----------------------------------------------------------------
334    get the map from incoming rows to their place in the front matrix
335    -----------------------------------------------------------------
336 */
337 for ( irow = jrow = 0 ; irow < nrowFromA ; irow++, jrow++ ) {
338    irowA = rowsFromA[irow] ;
339    map[jrow] = colmap[firstnz[irowA]] ;
340 }
341 for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
342    nrowI = chvI->nD ;
343    Chv_columnIndices(chvI, &ncolI, &colindI) ;
344    for ( irow = 0 ; irow < nrowI ; irow++, jrow++ ) {
345       map[jrow] = colindI[irow] ;
346    }
347 }
348 IV2qsortUp(nrowJ, map, rowids) ;
349 for ( irow = 0 ; irow < nrowJ ; irow++ ) {
350    map[rowids[irow]] = irow ;
351 }
352 /*
353    ----------------------------
354    allocate the A2 front object
355    ----------------------------
356 */
357 frontJ = A2_new() ;
358 A2_init(frontJ, frontmtx->type, nrowJ, ncolJ, ncolJ, 1, NULL) ;
359 A2_zero(frontJ) ;
360 /*
361    ------------------------------------
362    load the original rows of the matrix
363    ------------------------------------
364 */
365 for ( jrow = 0 ; jrow < nrowFromA ; jrow++ ) {
366    irowA = rowsFromA[jrow] ;
367    rowJ  = A2_row(frontJ, map[jrow]) ;
368    if ( A2_IS_REAL(frontJ) ) {
369       InpMtx_realVector(mtxA, irowA, &nentA, &colindA, &rowentA) ;
370    } else if ( A2_IS_COMPLEX(frontJ) ) {
371       InpMtx_complexVector(mtxA, irowA, &nentA, &colindA, &rowentA) ;
372    }
373    if ( msglvl > 3 ) {
374       fprintf(msgFile, "\n loading row %d", irowA) ;
375       fprintf(msgFile, "\n global indices") ;
376       IVfprintf(msgFile, nentA, colindA) ;
377       fflush(msgFile) ;
378    }
379    if ( A2_IS_REAL(frontJ) ) {
380       for ( ii = 0 ; ii < nentA ; ii++ ) {
381          jj = colmap[colindA[ii]] ;
382          rowJ[jj] = rowentA[ii] ;
383       }
384    } else if ( A2_IS_COMPLEX(frontJ) ) {
385       for ( ii = 0 ; ii < nentA ; ii++ ) {
386          jj = colmap[colindA[ii]] ;
387          rowJ[2*jj]   = rowentA[2*ii]   ;
388          rowJ[2*jj+1] = rowentA[2*ii+1] ;
389       }
390    }
391 }
392 if ( msglvl > 3 ) {
393    fprintf(msgFile, "\n after assembling rows of A") ;
394    A2_writeForHumanEye(frontJ, msgFile) ;
395    fflush(msgFile) ;
396 }
397 /*
398    ----------------------------------
399    load the updates from the children
400    ----------------------------------
401 */
402 for ( chvI = firstchild ; chvI != NULL ; chvI = chvI->next ) {
403    nrowI = chvI->nD ;
404    Chv_columnIndices(chvI, &ncolI, &colindI) ;
405    if ( msglvl > 3 ) {
406       fprintf(msgFile, "\n loading child %d", chvI->id) ;
407       fprintf(msgFile, "\n child's column indices") ;
408       IVfprintf(msgFile, ncolI, colindI) ;
409       Chv_writeForHumanEye(chvI, msgFile) ;
410       fflush(msgFile) ;
411    }
412    rowI = Chv_entries(chvI) ;
413    for ( irowI = 0 ; irowI < nrowI ; irowI++, jrow++ ) {
414       rowJ = A2_row(frontJ, map[jrow]) ;
415       if ( A2_IS_REAL(frontJ) ) {
416          for ( ii = irowI ; ii < ncolI ; ii++ ) {
417             jj = colindI[ii] ;
418             rowJ[jj] = rowI[ii] ;
419          }
420          rowI += ncolI - irowI - 1 ;
421       } else if ( A2_IS_COMPLEX(frontJ) ) {
422          for ( ii = irowI ; ii < ncolI ; ii++ ) {
423             jj = colindI[ii] ;
424             rowJ[2*jj]   = rowI[2*ii]   ;
425             rowJ[2*jj+1] = rowI[2*ii+1] ;
426          }
427          rowI += 2*(ncolI - irowI - 1) ;
428       }
429    }
430    if ( msglvl > 3 ) {
431       fprintf(msgFile, "\n after assembling child %d", chvI->id) ;
432       A2_writeForHumanEye(frontJ, msgFile) ;
433       fflush(msgFile) ;
434    }
435 }
436 return(frontJ) ; }
437 
438 /*--------------------------------------------------------------------*/
439 /*
440    ----------------------------------------------------
441    store the factor entries of the reduced front matrix
442 
443    created -- 98may25, cca
444    ----------------------------------------------------
445 */
446 void
FrontMtx_QR_storeFront(FrontMtx * frontmtx,int J,A2 * frontJ,int msglvl,FILE * msgFile)447 FrontMtx_QR_storeFront (
448    FrontMtx   *frontmtx,
449    int        J,
450    A2         *frontJ,
451    int        msglvl,
452    FILE       *msgFile
453 ) {
454 A2       tempA2 ;
455 double   fac, ifac, imag, real, rfac ;
456 double   *entDJJ, *entUJJ, *entUJN, *row ;
457 int      inc1, inc2, irow, jcol, ncol, ncolJ, nD, nentD, nentUJJ,
458          nfront, nrow, nU ;
459 int      *colind, *colindJ, *firstlocs, *sizes ;
460 SubMtx   *mtx ;
461 /*
462    ---------------
463    check the input
464    ---------------
465 */
466 if (  frontmtx == NULL || frontJ == NULL
467    || (msglvl > 0 && msgFile == NULL) ) {
468    fprintf(stderr, "\n fatal error in FrontMtx_QR_storeFront()"
469            "\n bad input\n") ;
470    exit(-1) ;
471 }
472 nfront = FrontMtx_nfront(frontmtx) ;
473 FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
474 nrow   = A2_nrow(frontJ) ;
475 ncol   = A2_ncol(frontJ) ;
476 A2_setDefaultFields(&tempA2) ;
477 nD = FrontMtx_frontSize(frontmtx, J) ;
478 nU = ncol - nD ;
479 /*
480    --------------------------------------
481    scale the rows and square the diagonal
482    --------------------------------------
483 */
484 row = A2_entries(frontJ) ;
485 if ( A2_IS_REAL(frontJ) ) {
486    for ( irow = 0 ; irow < nD ; irow++ ) {
487       if ( row[irow] != 0.0 ) {
488          fac = 1./row[irow] ;
489          for ( jcol = irow + 1 ; jcol < ncol ; jcol++ ) {
490             row[jcol] *= fac ;
491          }
492          row[irow] = row[irow] * row[irow] ;
493       }
494       row += ncol ;
495    }
496 } else if ( A2_IS_COMPLEX(frontJ) ) {
497    for ( irow = 0 ; irow < nD ; irow++ ) {
498       real = row[2*irow] ; imag = row[2*irow+1] ;
499       if (  real != 0.0 || imag != 0.0 ) {
500          Zrecip(real, imag, &rfac, &ifac) ;
501          ZVscale(ncol - irow - 1, & row[2*irow+2], rfac, ifac) ;
502          row[2*irow]   = real*real + imag*imag ;
503          row[2*irow+1] = 0.0 ;
504       }
505       row += 2*ncol ;
506    }
507 }
508 if ( msglvl > 3 ) {
509    fprintf(msgFile, "\n after scaling rows of A") ;
510    A2_writeForHumanEye(frontJ, msgFile) ;
511    fflush(msgFile) ;
512 }
513 /*
514    -------------------------
515    copy the diagonal entries
516    -------------------------
517 */
518 mtx = FrontMtx_diagMtx(frontmtx, J) ;
519 SubMtx_diagonalInfo(mtx, &nentD, &entDJJ) ;
520 A2_subA2(&tempA2, frontJ, 0, nD-1, 0, nD-1) ;
521 A2_copyEntriesToVector(&tempA2, nentD, entDJJ,
522                        A2_DIAGONAL, A2_BY_ROWS) ;
523 SubMtx_columnIndices(mtx, &ncol, &colind) ;
524 IVcopy(nD, colind, colindJ) ;
525 if ( msglvl > 3 ) {
526    fprintf(msgFile, "\n diagonal factor matrix") ;
527    SubMtx_writeForHumanEye(mtx, msgFile) ;
528    fflush(msgFile) ;
529 }
530 if ( (mtx = FrontMtx_upperMtx(frontmtx, J, J)) != NULL ) {
531 /*
532    ------------------------
533    copy the U_{J,J} entries
534    ------------------------
535 */
536    SubMtx_denseSubcolumnsInfo(mtx, &nD, &nentUJJ,
537                            &firstlocs, &sizes, &entUJJ) ;
538    A2_copyEntriesToVector(&tempA2, nentUJJ, entUJJ,
539                           A2_STRICT_UPPER, A2_BY_COLUMNS) ;
540    SubMtx_columnIndices(mtx, &ncol, &colind) ;
541    IVcopy(nD, colind, colindJ) ;
542    if ( msglvl > 3 ) {
543       fprintf(msgFile, "\n UJJ factor matrix") ;
544       SubMtx_writeForHumanEye(mtx, msgFile) ;
545       fflush(msgFile) ;
546    }
547 }
548 if ( ncolJ > nD ) {
549 /*
550    -----------------------------
551    copy the U_{J,bnd{J}} entries
552    -----------------------------
553 */
554    mtx = FrontMtx_upperMtx(frontmtx, J, nfront) ;
555    SubMtx_denseInfo(mtx, &nD, &nU, &inc1, &inc2, &entUJN) ;
556    A2_subA2(&tempA2, frontJ, 0, nD-1, nD, ncolJ-1) ;
557    A2_copyEntriesToVector(&tempA2, nD*nU, entUJN,
558                           A2_ALL_ENTRIES, A2_BY_COLUMNS) ;
559    SubMtx_columnIndices(mtx, &ncol, &colind) ;
560    IVcopy(nU, colind, colindJ + nD) ;
561    if ( msglvl > 3 ) {
562       fprintf(msgFile, "\n UJN factor matrix") ;
563       SubMtx_writeForHumanEye(mtx, msgFile) ;
564       fflush(msgFile) ;
565    }
566 }
567 return ; }
568 
569 /*--------------------------------------------------------------------*/
570 /*
571    -------------------------------------------------
572    purpose -- to create and return a Chv object that
573               holds the update matrix for front J
574 
575    created -- 98may25, cca
576    -------------------------------------------------
577 */
578 Chv *
FrontMtx_QR_storeUpdate(FrontMtx * frontmtx,int J,A2 * frontJ,ChvManager * chvmanager,int msglvl,FILE * msgFile)579 FrontMtx_QR_storeUpdate (
580    FrontMtx     *frontmtx,
581    int          J,
582    A2           *frontJ,
583    ChvManager   *chvmanager,
584    int          msglvl,
585    FILE         *msgFile
586 ) {
587 A2       tempJ ;
588 Chv      *chvJ ;
589 double   *updent ;
590 int      nbytes, ncolJ, ncolupd, nD, nent, nrowJ, nrowupd ;
591 int      *colindJ, *updind ;
592 /*
593    -----------------------------------------------
594    compute the number of rows in the update matrix
595    -----------------------------------------------
596 */
597 nD = FrontMtx_frontSize(frontmtx, J) ;
598 FrontMtx_columnIndices(frontmtx, J, &ncolJ, &colindJ) ;
599 nrowJ = A2_nrow(frontJ) ;
600 nrowupd = ((nrowJ >= ncolJ) ? ncolJ : nrowJ) - nD ;
601 ncolupd = ncolJ - nD ;
602 if ( msglvl > 3 ) {
603    fprintf(msgFile, "\n\n inside FrontMtx_QR_storeUpdate(%d)", J) ;
604    fprintf(msgFile, "\n nD %d, nrowJ %d, nrowupd %d, ncolupd %d",
605            nD, nrowJ, nrowupd, ncolupd) ;
606    fflush(msgFile) ;
607 }
608 if ( nrowupd > 0 && ncolupd > 0 ) {
609    if ( FRONTMTX_IS_REAL(frontmtx) ) {
610       nbytes = Chv_nbytesNeeded(nrowupd, 0, ncolupd - nrowupd,
611                                 SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
612    } else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
613       nbytes = Chv_nbytesNeeded(nrowupd, 0, ncolupd - nrowupd,
614                                 SPOOLES_COMPLEX, SPOOLES_HERMITIAN) ;
615    }
616    chvJ = ChvManager_newObjectOfSizeNbytes(chvmanager, nbytes) ;
617    if ( FRONTMTX_IS_REAL(frontmtx) ) {
618        Chv_init(chvJ, J, nrowupd, 0, ncolupd - nrowupd,
619                 SPOOLES_REAL, SPOOLES_SYMMETRIC) ;
620    } else if ( FRONTMTX_IS_COMPLEX(frontmtx) ) {
621        Chv_init(chvJ, J, nrowupd, 0, ncolupd - nrowupd,
622                 SPOOLES_COMPLEX, SPOOLES_HERMITIAN) ;
623    }
624    Chv_columnIndices(chvJ, &ncolupd, &updind) ;
625    IVcopy(ncolupd, updind, colindJ + nD) ;
626    nent   = Chv_nent(chvJ) ;
627    updent = Chv_entries(chvJ) ;
628    A2_setDefaultFields(&tempJ) ;
629    A2_subA2(&tempJ, frontJ, nD, nrowJ - 1, nD, ncolJ - 1) ;
630    A2_copyEntriesToVector(&tempJ, nent, updent, A2_UPPER, A2_BY_ROWS) ;
631    if ( msglvl > 3 ) {
632       fprintf(msgFile, "\n update matrix %d", J) ;
633       Chv_writeForHumanEye(chvJ, msgFile) ;
634       fflush(msgFile) ;
635    }
636 } else {
637    chvJ = NULL ;
638 }
639 return(chvJ) ; }
640 
641 /*--------------------------------------------------------------------*/
642