Line data Source code
1 : /*
2 : Copyright (c) 2003, The Regents of the University of California, through
3 : Lawrence Berkeley National Laboratory (subject to receipt of any required
4 : approvals from U.S. Dept. of Energy)
5 :
6 : All rights reserved.
7 :
8 : The source code is distributed under BSD license, see the file License.txt
9 : at the top-level directory.
10 : */
11 : /*
12 : * -- SuperLU routine (version 4.1) --
13 : * Univ. of California Berkeley, Xerox Palo Alto Research Center,
14 : * and Lawrence Berkeley National Lab.
15 : * November, 2010
16 : *
17 : * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
18 : *
19 : * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
20 : * EXPRESSED OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
21 : *
22 : * Permission is hereby granted to use or copy this program for any
23 : * purpose, provided the above notices are retained on all copies.
24 : * Permission to modify the code and to distribute modified code is
25 : * granted, provided the above notices are retained, and a notice that
26 : * the code was modified is included with the above copyright notice.
27 : */
28 : /*! \file
29 : * \brief Utility functions
30 : *
31 : * \ingroup Common
32 : */
33 :
34 : #include <math.h>
35 : #include "slu_ddefs.h"
36 :
37 : /*! \brief Print message to error stream and exit program
38 : *
39 : * \param[in] mgs Message that is printed to error stream.
40 : */
41 0 : void superlu_abort_and_exit(const char* msg)
42 : {
43 0 : fprintf(stderr, "%s", msg);
44 0 : exit (-1);
45 : }
46 :
47 : /*! \brief Set the default values for the options argument.
48 : *
49 : * \param[in,out] options Options struct that is filled with default values.
50 : */
51 0 : void set_default_options(superlu_options_t *options)
52 : {
53 0 : options->Fact = DOFACT;
54 0 : options->Equil = YES;
55 0 : options->ColPerm = COLAMD;
56 0 : options->Trans = NOTRANS;
57 0 : options->IterRefine = NOREFINE;
58 0 : options->DiagPivotThresh = 1.0;
59 0 : options->SymmetricMode = NO;
60 0 : options->PivotGrowth = NO;
61 0 : options->ConditionNumber = NO;
62 0 : options->PrintStat = YES;
63 0 : }
64 :
65 : /*! \brief Set the default values for the options argument for ILU.
66 : *
67 : * \param[out] options Options struct that is filled with default values.
68 : */
69 0 : void ilu_set_default_options(superlu_options_t *options)
70 : {
71 0 : set_default_options(options);
72 :
73 : /* further options for incomplete factorization */
74 0 : options->DiagPivotThresh = 0.1;
75 0 : options->RowPerm = LargeDiag_MC64;
76 0 : options->ILU_DropRule = DROP_BASIC | DROP_AREA;
77 0 : options->ILU_DropTol = 1e-4;
78 0 : options->ILU_FillFactor = 10.0;
79 0 : options->ILU_Norm = INF_NORM;
80 0 : options->ILU_MILU = SILU;
81 0 : options->ILU_MILU_Dim = 3.0; /* -log(n)/log(h) is perfect */
82 0 : options->ILU_FillTol = 1e-2;
83 0 : }
84 :
85 : /*! \brief Print the options setting.
86 : *
87 : * \param[in] options Options struct that is printed.
88 : */
89 0 : void print_options(const superlu_options_t *options)
90 : {
91 : printf(".. options:\n");
92 0 : printf("\tFact\t %8d\n", options->Fact);
93 0 : printf("\tEquil\t %8d\n", options->Equil);
94 0 : printf("\tColPerm\t %8d\n", options->ColPerm);
95 0 : printf("\tDiagPivotThresh %8.4f\n", options->DiagPivotThresh);
96 0 : printf("\tTrans\t %8d\n", options->Trans);
97 0 : printf("\tIterRefine\t%4d\n", options->IterRefine);
98 0 : printf("\tSymmetricMode\t%4d\n", options->SymmetricMode);
99 0 : printf("\tPivotGrowth\t%4d\n", options->PivotGrowth);
100 0 : printf("\tConditionNumber\t%4d\n", options->ConditionNumber);
101 : printf("..\n");
102 0 : }
103 :
104 : /*! \brief Print the options setting.
105 : *
106 : * \param[in] options Options struct that is printed.
107 : */
108 0 : void print_ilu_options(const superlu_options_t *options)
109 : {
110 : printf(".. ILU options:\n");
111 0 : printf("\tDiagPivotThresh\t%6.2e\n", options->DiagPivotThresh);
112 0 : printf("\ttau\t%6.2e\n", options->ILU_DropTol);
113 0 : printf("\tgamma\t%6.2f\n", options->ILU_FillFactor);
114 0 : printf("\tDropRule\t%0x\n", options->ILU_DropRule);
115 0 : printf("\tMILU\t%d\n", options->ILU_MILU);
116 : printf("\tMILU_ALPHA\t%6.2e\n", MILU_ALPHA);
117 0 : printf("\tDiagFillTol\t%6.2e\n", options->ILU_FillTol);
118 : printf("..\n");
119 0 : }
120 :
121 : /*! \brief Deallocate SuperMatrix
122 : *
123 : * Deallocate the structure pointing to the actual storage of the matrix.
124 : *
125 : * \param[in,out] A Deallocate all memory of this SuperMatrix.
126 : */
127 : void
128 0 : Destroy_SuperMatrix_Store(SuperMatrix *A)
129 : {
130 0 : SUPERLU_FREE ( A->Store );
131 0 : }
132 :
133 : /*! \brief Deallocate SuperMatrix of type NC
134 : *
135 : * Deallocate the structure pointing to the actual storage of the matrix.
136 : *
137 : * \param[in,out] A Deallocate all memory of this SuperMatrix of type NC.
138 : */
139 : void
140 0 : Destroy_CompCol_Matrix(SuperMatrix *A)
141 : {
142 0 : SUPERLU_FREE( ((NCformat *)A->Store)->rowind );
143 0 : SUPERLU_FREE( ((NCformat *)A->Store)->colptr );
144 0 : SUPERLU_FREE( ((NCformat *)A->Store)->nzval );
145 0 : SUPERLU_FREE( A->Store );
146 0 : }
147 :
148 : /*! \brief Deallocate SuperMatrix of type NR
149 : *
150 : * Deallocate the structure pointing to the actual storage of the matrix.
151 : *
152 : * \param[in,out] A Deallocate all memory of this SuperMatrix of type NR.
153 : */
154 : void
155 0 : Destroy_CompRow_Matrix(SuperMatrix *A)
156 : {
157 0 : SUPERLU_FREE( ((NRformat *)A->Store)->colind );
158 0 : SUPERLU_FREE( ((NRformat *)A->Store)->rowptr );
159 0 : SUPERLU_FREE( ((NRformat *)A->Store)->nzval );
160 0 : SUPERLU_FREE( A->Store );
161 0 : }
162 :
163 : /*! \brief Deallocate SuperMatrix of type SC
164 : *
165 : * Deallocate the structure pointing to the actual storage of the matrix.
166 : *
167 : * \param[in,out] A Deallocate all memory of this SuperMatrix of type SC.
168 : */
169 : void
170 0 : Destroy_SuperNode_Matrix(SuperMatrix *A)
171 : {
172 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->rowind );
173 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->rowind_colptr );
174 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->nzval );
175 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->nzval_colptr );
176 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->col_to_sup );
177 0 : SUPERLU_FREE ( ((SCformat *)A->Store)->sup_to_col );
178 0 : SUPERLU_FREE ( A->Store );
179 0 : }
180 :
181 : /*! \brief Deallocate SuperMatrix of type NCP
182 : *
183 : * Deallocate the structure pointing to the actual storage of the matrix.
184 : *
185 : * \param[in,out] A Deallocate all memory of this SuperMatrix of type NCP.
186 : */
187 : void
188 0 : Destroy_CompCol_Permuted(SuperMatrix *A)
189 : {
190 0 : SUPERLU_FREE ( ((NCPformat *)A->Store)->colbeg );
191 0 : SUPERLU_FREE ( ((NCPformat *)A->Store)->colend );
192 0 : SUPERLU_FREE ( A->Store );
193 0 : }
194 :
195 : /*! \brief Deallocate SuperMatrix of type DN
196 : *
197 : * Deallocate the structure pointing to the actual storage of the matrix.
198 : *
199 : * \param[in,out] A Deallocate all memory of this SuperMatrix of type DN.
200 : */
201 : void
202 0 : Destroy_Dense_Matrix(SuperMatrix *A)
203 : {
204 0 : DNformat* Astore = A->Store;
205 0 : SUPERLU_FREE (Astore->nzval);
206 0 : SUPERLU_FREE ( A->Store );
207 0 : }
208 :
209 : /*! \brief Reset repfnz[] for the current column
210 : */
211 : void
212 0 : resetrep_col (const int nseg, const int *segrep, int *repfnz)
213 : {
214 : int_t i, irep;
215 :
216 0 : for (i = 0; i < nseg; i++) {
217 0 : irep = segrep[i];
218 0 : repfnz[irep] = SLU_EMPTY;
219 : }
220 0 : }
221 :
222 : /*! \brief Count the total number of nonzeros in factors L and U, and in the symmetrically reduced L.
223 : */
224 : void
225 0 : countnz(const int n, int_t *xprune, int_t *nnzL, int_t *nnzU, GlobalLU_t *Glu)
226 : {
227 : int nsuper, fsupc, i, j;
228 : int_t jlen;
229 : #if ( DEBUGlevel>=1 )
230 : int_t irep = 0, nnzL0 = 0;
231 : #endif
232 : int *xsup;
233 : int_t *xlsub;
234 :
235 0 : xsup = Glu->xsup;
236 0 : xlsub = Glu->xlsub;
237 0 : *nnzL = 0;
238 0 : *nnzU = (Glu->xusub)[n];
239 0 : nsuper = (Glu->supno)[n];
240 :
241 0 : if ( n <= 0 ) return;
242 :
243 : /*
244 : * For each supernode
245 : */
246 0 : for (i = 0; i <= nsuper; i++) {
247 0 : fsupc = xsup[i];
248 0 : jlen = xlsub[fsupc+1] - xlsub[fsupc];
249 :
250 0 : for (j = fsupc; j < xsup[i+1]; j++) {
251 0 : *nnzL += jlen;
252 0 : *nnzU += j - fsupc + 1;
253 0 : jlen--;
254 : }
255 : #if ( DEBUGlevel>=1 )
256 : irep = xsup[i+1] - 1;
257 : nnzL0 += xprune[irep] - xlsub[irep];
258 : #endif
259 : }
260 :
261 : #if ( DEBUGlevel>=1 )
262 : printf("\tNo of nonzeros in symm-reduced L = %lld\n", (long long) nnzL0); fflush(stdout);
263 : #endif
264 : }
265 :
266 : /*! \brief Count the total number of nonzeros in factors L and U.
267 : */
268 : void
269 0 : ilu_countnz(const int n, int_t *nnzL, int_t *nnzU, GlobalLU_t *Glu)
270 : {
271 : int nsuper, fsupc, i, j;
272 : int jlen;
273 : int *xsup;
274 : int_t *xlsub;
275 :
276 0 : xsup = Glu->xsup;
277 0 : xlsub = Glu->xlsub;
278 0 : *nnzL = 0;
279 0 : *nnzU = (Glu->xusub)[n];
280 0 : nsuper = (Glu->supno)[n];
281 :
282 0 : if ( n <= 0 ) return;
283 :
284 : /*
285 : * For each supernode
286 : */
287 0 : for (i = 0; i <= nsuper; i++) {
288 0 : fsupc = xsup[i];
289 0 : jlen = xlsub[fsupc+1] - xlsub[fsupc];
290 :
291 0 : for (j = fsupc; j < xsup[i+1]; j++) {
292 0 : *nnzL += jlen;
293 0 : *nnzU += j - fsupc + 1;
294 0 : jlen--;
295 : }
296 : //irep = xsup[i+1] - 1;
297 : }
298 : }
299 :
300 : /*! \brief Fix up the data storage lsub for L-subscripts.
301 : *
302 : * It removes the subscript sets for structural pruning,
303 : * and applies permutation to the remaining subscripts.
304 : */
305 : void
306 0 : fixupL(const int n, const int *perm_r, GlobalLU_t *Glu)
307 : {
308 : int nsuper, fsupc, i, k;
309 : int_t nextl, j, jstrt;
310 : int *xsup;
311 : int_t *lsub, *xlsub;
312 :
313 0 : if ( n <= 1 ) return;
314 :
315 0 : xsup = Glu->xsup;
316 0 : lsub = Glu->lsub;
317 0 : xlsub = Glu->xlsub;
318 : nextl = 0;
319 0 : nsuper = (Glu->supno)[n];
320 :
321 : /*
322 : * For each supernode ...
323 : */
324 0 : for (i = 0; i <= nsuper; i++) {
325 0 : fsupc = xsup[i];
326 0 : jstrt = xlsub[fsupc];
327 0 : xlsub[fsupc] = nextl;
328 0 : for (j = jstrt; j < xlsub[fsupc+1]; j++) {
329 0 : lsub[nextl] = perm_r[lsub[j]]; /* Now indexed into P*A */
330 0 : nextl++;
331 : }
332 0 : for (k = fsupc+1; k < xsup[i+1]; k++)
333 0 : xlsub[k] = nextl; /* Other columns in supernode i */
334 :
335 : }
336 :
337 0 : xlsub[n] = nextl;
338 : }
339 :
340 : /*! \brief Diagnostic print of segment info after panel_dfs().
341 : */
342 0 : void print_panel_seg(int n, int w, int jcol, int nseg,
343 : const int *segrep, const int *repfnz)
344 : {
345 : int j, k;
346 :
347 0 : for (j = jcol; j < jcol+w; j++) {
348 : printf("\tcol %d:\n", j);
349 0 : for (k = 0; k < nseg; k++)
350 0 : printf("\t\tseg %d, segrep %d, repfnz %d\n", k,
351 0 : segrep[k], repfnz[(j-jcol)*n + segrep[k]]);
352 : }
353 :
354 0 : }
355 :
356 : /*! \brief Initialize SuperLU stat
357 : *
358 : * \param[in,out] stat SuperLU stat that is initialized.
359 : */
360 : void
361 0 : StatInit(SuperLUStat_t *stat)
362 : {
363 : register int i, w, panel_size, relax;
364 :
365 0 : panel_size = sp_ienv(1);
366 0 : relax = sp_ienv(2);
367 0 : w = SUPERLU_MAX(panel_size, relax);
368 0 : stat->panel_histo = int32Calloc(w+1);
369 0 : stat->utime = (double *) SUPERLU_MALLOC(NPHASES * sizeof(double));
370 0 : if (!stat->utime) ABORT("SUPERLU_MALLOC fails for stat->utime");
371 0 : stat->ops = (flops_t *) SUPERLU_MALLOC(NPHASES * sizeof(flops_t));
372 0 : if (!stat->ops) ABORT("SUPERLU_MALLOC fails for stat->ops");
373 0 : for (i = 0; i < NPHASES; ++i) {
374 0 : stat->utime[i] = 0.;
375 0 : stat->ops[i] = 0.;
376 : }
377 0 : stat->TinyPivots = 0;
378 0 : stat->RefineSteps = 0;
379 0 : stat->expansions = 0;
380 : #if ( PRNTlevel >= 1 )
381 : printf(".. parameters in sp_ienv():\n");
382 : printf("\t 1: panel size \t %4d \n"
383 : "\t 2: relax \t %4d \n"
384 : "\t 3: max. super \t %4d \n"
385 : "\t 4: row-dim 2D \t %4d \n"
386 : "\t 5: col-dim 2D \t %4d \n"
387 : "\t 6: fill ratio \t %4d \n",
388 : sp_ienv(1), sp_ienv(2), sp_ienv(3),
389 : sp_ienv(4), sp_ienv(5), sp_ienv(6));
390 : #endif
391 0 : }
392 :
393 : /*! \brief Display SuperLU stat
394 : *
395 : * Print content of SuperLU stat to output.
396 : *
397 : * \param[in] stat Display this SuperLU stat
398 : */
399 : void
400 0 : StatPrint(SuperLUStat_t *stat)
401 : {
402 : double *utime;
403 : flops_t *ops;
404 :
405 0 : utime = stat->utime;
406 0 : ops = stat->ops;
407 0 : printf("Factor time = %8.5f\n", utime[FACT]);
408 0 : if ( utime[FACT] != 0.0 )
409 0 : printf("Factor flops = %e\tMflops = %8.2f\n", ops[FACT],
410 0 : ops[FACT]*1e-6/utime[FACT]);
411 :
412 0 : printf("Solve time = %8.4f\n", utime[SOLVE]);
413 0 : if ( utime[SOLVE] != 0.0 )
414 0 : printf("Solve flops = %e\tMflops = %8.2f\n", ops[SOLVE],
415 0 : ops[SOLVE]*1e-6/utime[SOLVE]);
416 :
417 0 : printf("Number of memory expansions: %d\n", stat->expansions);
418 :
419 0 : }
420 :
421 : /*! \brief Deallocate SuperLU stat
422 : *
423 : * Deallocate the structure pointing to the actual storage of SuperLU stat.
424 : *
425 : * \param[in,out] stat Deallocate all memory of this SuperLU stat
426 : */
427 : void
428 0 : StatFree(SuperLUStat_t *stat)
429 : {
430 0 : SUPERLU_FREE(stat->panel_histo);
431 0 : SUPERLU_FREE(stat->utime);
432 0 : SUPERLU_FREE(stat->ops);
433 0 : }
434 :
435 : /*! \brief Get operations for LU factorization
436 : *
437 : * Read out number of operations (ops) needed for LU factorization.
438 : *
439 : * \param[in] stat SuperLU stat used to read out the opts.
440 : *
441 : * \return Number of operations needed for LU factorization.
442 : */
443 : flops_t
444 0 : LUFactFlops(SuperLUStat_t *stat)
445 : {
446 0 : return (stat->ops[FACT]);
447 : }
448 :
449 : /*! \brief Get operations for LU solve
450 : *
451 : * Read out number of operations (ops) needed for LU solve.
452 : *
453 : * \param[in] stat SuperLU stat used to read out the opts.
454 : *
455 : * \return Number of operations needed for LU solve.
456 : */
457 : flops_t
458 0 : LUSolveFlops(SuperLUStat_t *stat)
459 : {
460 0 : return (stat->ops[SOLVE]);
461 : }
462 :
463 : /*! \brief Fills an integer array with a given value.
464 : *
465 : * \param[in,out] a Integer array that is filled.
466 : * \param[in] alen Length of integer array \a a.
467 : * \param[in] ival Value to be filled in every element of \a a.
468 : */
469 0 : void ifill(int *a, int alen, int ival)
470 : {
471 : register int i;
472 0 : for (i = 0; i < alen; i++) a[i] = ival;
473 0 : }
474 :
475 : /*! \brief Get the statistics of the supernodes
476 : */
477 : #define NBUCKS 10
478 :
479 0 : void super_stats(int nsuper, const int *xsup)
480 : {
481 : register int nsup1 = 0;
482 : int i, isize, whichb, bl, bh;
483 : int bucket[NBUCKS];
484 : int max_sup_size = 0;
485 :
486 0 : for (i = 0; i <= nsuper; i++) {
487 0 : isize = xsup[i+1] - xsup[i];
488 0 : if ( isize == 1 ) nsup1++;
489 0 : if ( max_sup_size < isize ) max_sup_size = isize;
490 : }
491 :
492 0 : printf(" Supernode statistics:\n\tno of super = %d\n", nsuper+1);
493 : printf("\tmax supernode size = %d\n", max_sup_size);
494 : printf("\tno of size 1 supernodes = %d\n", nsup1);
495 :
496 : /* Histogram of the supernode sizes */
497 0 : ifill (bucket, NBUCKS, 0);
498 :
499 0 : for (i = 0; i <= nsuper; i++) {
500 0 : isize = xsup[i+1] - xsup[i];
501 0 : whichb = (float) isize / max_sup_size * NBUCKS;
502 0 : if (whichb >= NBUCKS) whichb = NBUCKS - 1;
503 0 : bucket[whichb]++;
504 : }
505 :
506 : printf("\tHistogram of supernode sizes:\n");
507 0 : for (i = 0; i < NBUCKS; i++) {
508 0 : bl = (float) i * max_sup_size / NBUCKS;
509 0 : bh = (float) (i+1) * max_sup_size / NBUCKS;
510 0 : printf("\tsnode: %d-%d\t\t%d\n", bl+1, bh, bucket[i]);
511 : }
512 :
513 0 : }
514 :
515 0 : float SpaSize(int n, int np, float sum_npw)
516 : {
517 0 : return (sum_npw*8 + np*8 + n*4)/1024.;
518 : }
519 :
520 0 : float DenseSize(int n, float sum_nw)
521 : {
522 0 : return (sum_nw*8 + n*8)/1024.;
523 : }
524 :
525 : /*! \brief Check whether repfnz[] == SLU_EMPTY after reset.
526 : */
527 0 : void check_repfnz(int n, int w, int jcol, const int *repfnz)
528 : {
529 : int jj, k;
530 :
531 0 : for (jj = jcol; jj < jcol+w; jj++)
532 0 : for (k = 0; k < n; k++)
533 0 : if ( repfnz[(jj-jcol)*n + k] != SLU_EMPTY ) {
534 0 : fprintf(stderr, "col %d, repfnz_col[%d] = %d\n", jj,
535 : k, repfnz[(jj-jcol)*n + k]);
536 0 : ABORT("check_repfnz");
537 : }
538 0 : }
539 :
540 : /*! \brief Print a summary of the testing results.
541 : *
542 : * \param[in] type Array with three chars indicating the type for that the tests were run like "CGE" or "DGE".
543 : * \param[in] nfail Number of failed tests.
544 : * \param[in] nrun Number of tests run.
545 : * \param[in] nerrs Number of error messages recorded.
546 : */
547 : void
548 0 : PrintSumm(const char *type, int nfail, int nrun, int nerrs)
549 : {
550 0 : if ( nfail > 0 )
551 : printf("%3s driver: %d out of %d tests failed to pass the threshold\n",
552 : type, nfail, nrun);
553 : else
554 : printf("All tests for %3s driver passed the threshold (%6d tests run)\n", type, nrun);
555 :
556 0 : if ( nerrs > 0 )
557 : printf("%6d error messages recorded\n", nerrs);
558 0 : }
559 :
560 : /*! \brief Print content of int array
561 : *
562 : * \param[in] what Vector name that is printed first.
563 : * \param[in] n Number of elements in array.
564 : * \param[in] vec Array of ints to be printed
565 : */
566 0 : void print_int_vec(const char *what, int n, const int *vec)
567 : {
568 : int i;
569 : printf("%s\n", what);
570 0 : for (i = 0; i < n; ++i) printf("%d\t%d\n", i, vec[i]);
571 0 : }
572 :
573 : /*! \brief Print content of int array with index numbers after every tenth row
574 : *
575 : * Print all elements of an int array. After ten rows the index is printed to
576 : * make it more readable for humans.
577 : *
578 : * \param[in] name Vector name that is printed first.
579 : * \param[in] len Number of elements in array.
580 : * \param[in] x Array of ints to be printed.
581 : */
582 0 : void slu_PrintInt10(const char *name, int len, const int *x)
583 : {
584 : register int i;
585 :
586 : printf("%10s:", name);
587 0 : for (i = 0; i < len; ++i)
588 : {
589 0 : if ( i % 10 == 0 ) printf("\n\t[%2d-%2d]", i, i + 9);
590 0 : printf("%6d", x[i]);
591 : }
592 : printf("\n");
593 0 : }
594 :
595 : /*! \brief Validity check of a permutation
596 : *
597 : * \param[in] what String to be printed as part of displayed text for success or error.
598 : * \param[in] n Number of elements in permutation \a perm.
599 : * \param[in] perm Array describing the permutation.
600 : */
601 0 : void check_perm(const char *what, int n, const int *perm)
602 : {
603 : register int i;
604 : int *marker;
605 : /*marker = (int *) calloc(n, sizeof(int));*/
606 0 : marker = int32Malloc(n);
607 0 : for (i = 0; i < n; ++i) marker[i] = 0;
608 :
609 0 : for (i = 0; i < n; ++i) {
610 0 : if ( marker[perm[i]] == 1 || perm[i] >= n ) {
611 : printf("%s: Not a valid PERM[%d] = %d\n", what, i, perm[i]);
612 0 : ABORT("check_perm");
613 : } else {
614 0 : marker[perm[i]] = 1;
615 : }
616 : }
617 :
618 0 : SUPERLU_FREE(marker);
619 : printf("check_perm: %s: n %d\n", what, n);
620 0 : }
|