1 /* ========================================================================== */
2 /* === UMFPACK_report_info ================================================== */
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 /*
11     User-callable.  Prints the Info array.  See umfpack_report_info.h for
12     details.
13 */
14 
15 #include "umf_internal.h"
16 
17 #define PRINT_INFO(format,x) \
18 { \
19     if (SCALAR_IS_NAN (x) || (!SCALAR_IS_LTZERO (x))) \
20     { \
21 	PRINTF ((format, x)) ; \
22     } \
23 }
24 
25 /* RATIO macro uses a double relop, but ignore NaN case: */
26 #define RATIO(a,b,c) (((b) == 0) ? (c) : (((double) a)/((double) b)))
27 
28 /* ========================================================================== */
29 /* === print_ratio ========================================================== */
30 /* ========================================================================== */
31 
print_ratio(char * what,char * format,double estimate,double actual)32 PRIVATE void print_ratio
33 (
34     char *what,
35     char *format,
36     double estimate,
37     double actual
38 )
39 {
40     if (estimate < 0 && actual < 0)	/* double relop, but ignore Nan case */
41     {
42 	return ;
43     }
44     PRINTF (("    %-27s", what)) ;
45     if (estimate >= 0)			/* double relop, but ignore Nan case */
46     {
47 	PRINTF ((format, estimate)) ;
48     }
49     else
50     {
51 	PRINTF (("                    -")) ;
52     }
53     if (actual >= 0)			/* double relop, but ignore Nan case */
54     {
55 	PRINTF ((format, actual)) ;
56     }
57     else
58     {
59 	PRINTF (("                    -")) ;
60     }
61     if (estimate >= 0 && actual >= 0)	/* double relop, but ignore Nan case */
62     {
63 	PRINTF ((" %5.0f%%\n", 100 * RATIO (actual, estimate, 1))) ;
64     }
65     else
66     {
67 	PRINTF (("      -\n")) ;
68     }
69 }
70 
71 /* ========================================================================== */
72 /* === UMFPACK_report_info ================================================== */
73 /* ========================================================================== */
74 
UMFPACK_report_info(const double Control[UMFPACK_CONTROL],const double Info[UMFPACK_INFO])75 GLOBAL void UMFPACK_report_info
76 (
77     const double Control [UMFPACK_CONTROL],
78     const double Info [UMFPACK_INFO]
79 )
80 {
81 
82     double lnz_est, unz_est, lunz_est, lnz, unz, lunz, tsym, tnum, fnum, tsolve,
83 	fsolve, ftot, twsym, twnum, twsolve, twtot, n2 ;
84     Int n_row, n_col, n_inner, prl, is_sym, strategy ;
85 
86     /* ---------------------------------------------------------------------- */
87     /* get control settings and status to determine what to print */
88     /* ---------------------------------------------------------------------- */
89 
90     prl = GET_CONTROL (UMFPACK_PRL, UMFPACK_DEFAULT_PRL) ;
91 
92     if (!Info || prl < 2)
93     {
94 	/* no output generated if Info is (double *) NULL */
95 	/* or if prl is less than 2 */
96 	return ;
97     }
98 
99     /* ---------------------------------------------------------------------- */
100     /* print umfpack version */
101     /* ---------------------------------------------------------------------- */
102 
103     PRINTF  (("UMFPACK V%d.%d.%d (%s), Info:\n", UMFPACK_MAIN_VERSION,
104 	UMFPACK_SUB_VERSION, UMFPACK_SUBSUB_VERSION, UMFPACK_DATE)) ;
105 
106 #ifndef NDEBUG
107     PRINTF ((
108 "**** Debugging enabled (UMFPACK will be exceedingly slow!) *****************\n"
109     )) ;
110 #endif
111 
112     /* ---------------------------------------------------------------------- */
113     /* print run-time options */
114     /* ---------------------------------------------------------------------- */
115 
116 #ifdef DINT
117     PRINTF (("    matrix entry defined as:          double\n")) ;
118     PRINTF (("    Int (generic integer) defined as: int\n")) ;
119 #endif
120 #ifdef DLONG
121     PRINTF (("    matrix entry defined as:          double\n")) ;
122     PRINTF (("    Int (generic integer) defined as: SuiteSparse_long\n")) ;
123 #endif
124 #ifdef ZINT
125     PRINTF (("    matrix entry defined as:          double complex\n")) ;
126     PRINTF (("    Int (generic integer) defined as: int\n")) ;
127 #endif
128 #ifdef ZLONG
129     PRINTF (("    matrix entry defined as:          double complex\n")) ;
130     PRINTF (("    Int (generic integer) defined as: SuiteSparse_long\n")) ;
131 #endif
132 
133     /* ---------------------------------------------------------------------- */
134     /* print compile-time options */
135     /* ---------------------------------------------------------------------- */
136 
137     PRINTF (("    BLAS library used: ")) ;
138 
139 #ifdef NBLAS
140     PRINTF (("none.  UMFPACK will be slow.\n")) ;
141 #else
142     PRINTF (("Fortran BLAS.  size of BLAS integer: "ID"\n",
143 	(Int) (sizeof (BLAS_INT)))) ;
144 #endif
145 
146     PRINTF (("    MATLAB:                           ")) ;
147 #ifdef MATLAB_MEX_FILE
148     PRINTF (("yes.\n")) ;
149 #else
150 #ifdef MATHWORKS
151     PRINTF (("yes.\n")) ;
152 #else
153     PRINTF (("no.\n")) ;
154 #endif
155 #endif
156 
157     PRINTF (("    CPU timer:                        ")) ;
158 #ifdef SUITESPARSE_TIMER_ENABLED
159     PRINTF (("POSIX C clock_getttime ( ) routine.\n")) ;
160 #else
161     PRINTF (("none.\n")) ;
162 #endif
163 
164     /* ---------------------------------------------------------------------- */
165     /* print n and nz */
166     /* ---------------------------------------------------------------------- */
167 
168     n_row = (Int) Info [UMFPACK_NROW] ;
169     n_col = (Int) Info [UMFPACK_NCOL] ;
170     n_inner = MIN (n_row, n_col) ;
171 
172     PRINT_INFO ("    number of rows in matrix A:       "ID"\n", n_row) ;
173     PRINT_INFO ("    number of columns in matrix A:    "ID"\n", n_col) ;
174     PRINT_INFO ("    entries in matrix A:              "ID"\n",
175 	(Int) Info [UMFPACK_NZ]) ;
176     PRINT_INFO ("    memory usage reported in:         "ID"-byte Units\n",
177 	(Int) Info [UMFPACK_SIZE_OF_UNIT]) ;
178 
179     PRINT_INFO ("    size of int:                      "ID" bytes\n",
180 	(Int) Info [UMFPACK_SIZE_OF_INT]) ;
181     PRINT_INFO ("    size of SuiteSparse_long:         "ID" bytes\n",
182 	(Int) Info [UMFPACK_SIZE_OF_LONG]) ;
183     PRINT_INFO ("    size of pointer:                  "ID" bytes\n",
184 	(Int) Info [UMFPACK_SIZE_OF_POINTER]) ;
185     PRINT_INFO ("    size of numerical entry:          "ID" bytes\n",
186 	(Int) Info [UMFPACK_SIZE_OF_ENTRY]) ;
187 
188     /* ---------------------------------------------------------------------- */
189     /* symbolic parameters */
190     /* ---------------------------------------------------------------------- */
191 
192     strategy = Info [UMFPACK_STRATEGY_USED] ;
193     if (strategy == UMFPACK_STRATEGY_SYMMETRIC)
194     {
195 	PRINTF (("\n    strategy used:                    symmetric\n")) ;
196         if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_AMD)
197         {
198             PRINTF (("    ordering used:                    amd on A+A'\n")) ;
199         }
200         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_GIVEN)
201         {
202             PRINTF (("    ordering used:                    user perm.\n")) ;
203         }
204         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_USER)
205         {
206             PRINTF (("    ordering used:                    user function\n")) ;
207         }
208         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_NONE)
209         {
210             PRINTF (("    ordering used:                    none\n")) ;
211         }
212         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_METIS)
213         {
214             PRINTF (("    ordering used:                    metis on A+A'\n")) ;
215         }
216         else
217         {
218             PRINTF (("    ordering used:                    not computed\n")) ;
219         }
220     }
221     else
222     {
223 	PRINTF (("\n    strategy used:                    unsymmetric\n")) ;
224         if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_AMD)
225         {
226             PRINTF (("    ordering used:                    colamd on A\n")) ;
227         }
228         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_GIVEN)
229         {
230             PRINTF (("    ordering used:                    user perm.\n")) ;
231         }
232         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_USER)
233         {
234             PRINTF (("    ordering used:                    user function\n")) ;
235         }
236         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_NONE)
237         {
238             PRINTF (("    ordering used:                    none\n")) ;
239         }
240         else if (Info [UMFPACK_ORDERING_USED] == UMFPACK_ORDERING_METIS)
241         {
242             PRINTF (("    ordering used:                    metis on A'A\n")) ;
243         }
244         else
245         {
246             PRINTF (("    ordering used:                    not computed\n")) ;
247         }
248     }
249 
250     if (Info [UMFPACK_QFIXED] == 1)
251     {
252 	PRINTF (("    modify Q during factorization:    no\n")) ;
253     }
254     else if (Info [UMFPACK_QFIXED] == 0)
255     {
256 	PRINTF (("    modify Q during factorization:    yes\n")) ;
257     }
258 
259     if (Info [UMFPACK_DIAG_PREFERRED] == 0)
260     {
261 	PRINTF (("    prefer diagonal pivoting:         no\n")) ;
262     }
263     else if (Info [UMFPACK_DIAG_PREFERRED] == 1)
264     {
265 	PRINTF (("    prefer diagonal pivoting:         yes\n")) ;
266     }
267 
268     /* ---------------------------------------------------------------------- */
269     /* singleton statistics */
270     /* ---------------------------------------------------------------------- */
271 
272     PRINT_INFO ("    pivots with zero Markowitz cost:               %0.f\n",
273 	Info [UMFPACK_COL_SINGLETONS] + Info [UMFPACK_ROW_SINGLETONS]) ;
274     PRINT_INFO ("    submatrix S after removing zero-cost pivots:\n"
275 		"        number of \"dense\" rows:                    %.0f\n",
276 	Info [UMFPACK_NDENSE_ROW]) ;
277     PRINT_INFO ("        number of \"dense\" columns:                 %.0f\n",
278 	Info [UMFPACK_NDENSE_COL]) ;
279     PRINT_INFO ("        number of empty rows:                      %.0f\n",
280 	Info [UMFPACK_NEMPTY_ROW]) ;
281     PRINT_INFO ("        number of empty columns                    %.0f\n",
282 	Info [UMFPACK_NEMPTY_COL]) ;
283     is_sym = Info [UMFPACK_S_SYMMETRIC] ;
284     if (is_sym > 0)
285     {
286 	PRINTF (("        submatrix S square and diagonal preserved\n")) ;
287     }
288     else if (is_sym == 0)
289     {
290 	PRINTF (("        submatrix S not square or diagonal not preserved\n"));
291     }
292 
293     /* ---------------------------------------------------------------------- */
294     /* statistics from amd_aat */
295     /* ---------------------------------------------------------------------- */
296 
297     n2 = Info [UMFPACK_N2] ;
298     if (n2 >= 0)
299     {
300 	PRINTF (("    pattern of square submatrix S:\n")) ;
301     }
302     PRINT_INFO ("        number rows and columns                    %.0f\n",
303 	n2) ;
304     PRINT_INFO ("        symmetry of nonzero pattern:               %.6f\n",
305 	Info [UMFPACK_PATTERN_SYMMETRY]) ;
306     PRINT_INFO ("        nz in S+S' (excl. diagonal):               %.0f\n",
307 	Info [UMFPACK_NZ_A_PLUS_AT]) ;
308     PRINT_INFO ("        nz on diagonal of matrix S:                %.0f\n",
309 	Info [UMFPACK_NZDIAG]) ;
310     if (Info [UMFPACK_NZDIAG] >= 0 && n2 > 0)
311     {
312 	PRINTF (("        fraction of nz on diagonal:                %.6f\n",
313 	Info [UMFPACK_NZDIAG] / n2)) ;
314     }
315 
316     /* ---------------------------------------------------------------------- */
317     /* statistics from AMD */
318     /* ---------------------------------------------------------------------- */
319 
320     if (strategy == UMFPACK_STRATEGY_SYMMETRIC &&
321         Info [UMFPACK_ORDERING_USED] != UMFPACK_ORDERING_GIVEN)
322     {
323 	double dmax = Info [UMFPACK_SYMMETRIC_DMAX] ;
324 	PRINTF (("    AMD statistics, for strict diagonal pivoting:\n")) ;
325 	PRINT_INFO ("        est. flops for LU factorization:           %.5e\n",
326 	    Info [UMFPACK_SYMMETRIC_FLOPS]) ;
327 	PRINT_INFO ("        est. nz in L+U (incl. diagonal):           %.0f\n",
328 	    Info [UMFPACK_SYMMETRIC_LUNZ]) ;
329         if (dmax > 0)
330         {
331             PRINT_INFO
332             ("        est. largest front (# entries):            %.0f\n",
333 	    dmax*dmax) ;
334         }
335 	PRINT_INFO ("        est. max nz in any column of L:            %.0f\n",
336 	    dmax) ;
337 	PRINT_INFO (
338 	    "        number of \"dense\" rows/columns in S+S':    %.0f\n",
339 	    Info [UMFPACK_SYMMETRIC_NDENSE]) ;
340     }
341 
342     /* ---------------------------------------------------------------------- */
343     /* symbolic factorization */
344     /* ---------------------------------------------------------------------- */
345 
346     tsym = Info [UMFPACK_SYMBOLIC_TIME] ;
347     twsym = Info [UMFPACK_SYMBOLIC_WALLTIME] ;
348 
349     PRINT_INFO ("    symbolic factorization defragmentations:       %.0f\n",
350 	Info [UMFPACK_SYMBOLIC_DEFRAG]) ;
351     PRINT_INFO ("    symbolic memory usage (Units):                 %.0f\n",
352 	Info [UMFPACK_SYMBOLIC_PEAK_MEMORY]) ;
353     PRINT_INFO ("    symbolic memory usage (MBytes):                %.1f\n",
354 	MBYTES (Info [UMFPACK_SYMBOLIC_PEAK_MEMORY])) ;
355     PRINT_INFO ("    Symbolic size (Units):                         %.0f\n",
356 	Info [UMFPACK_SYMBOLIC_SIZE]) ;
357     PRINT_INFO ("    Symbolic size (MBytes):                        %.0f\n",
358 	MBYTES (Info [UMFPACK_SYMBOLIC_SIZE])) ;
359     PRINT_INFO ("    symbolic factorization wallclock time(sec):    %.2f\n",
360 	twsym) ;
361 
362     /* ---------------------------------------------------------------------- */
363     /* scaling, from numerical factorization */
364     /* ---------------------------------------------------------------------- */
365 
366     if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_NONE)
367     {
368 	PRINTF (("\n    matrix scaled: no\n")) ;
369     }
370     else if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_SUM)
371     {
372 	PRINTF (("\n    matrix scaled: yes ")) ;
373 	PRINTF (("(divided each row by sum of abs values in each row)\n")) ;
374 	PRINTF (("    minimum sum (abs (rows of A)):              %.5e\n",
375 	    Info [UMFPACK_RSMIN])) ;
376 	PRINTF (("    maximum sum (abs (rows of A)):              %.5e\n",
377 	    Info [UMFPACK_RSMAX])) ;
378     }
379     else if (Info [UMFPACK_WAS_SCALED] == UMFPACK_SCALE_MAX)
380     {
381 	PRINTF (("\n    matrix scaled: yes ")) ;
382 	PRINTF (("(divided each row by max abs value in each row)\n")) ;
383 	PRINTF (("    minimum max (abs (rows of A)):              %.5e\n",
384 	    Info [UMFPACK_RSMIN])) ;
385 	PRINTF (("    maximum max (abs (rows of A)):              %.5e\n",
386 	    Info [UMFPACK_RSMAX])) ;
387     }
388 
389     /* ---------------------------------------------------------------------- */
390     /* estimate/actual in symbolic/numeric factorization */
391     /* ---------------------------------------------------------------------- */
392 
393     /* double relop, but ignore NaN case: */
394     if (Info [UMFPACK_SYMBOLIC_DEFRAG] >= 0	/* UMFPACK_*symbolic called */
395     ||  Info [UMFPACK_NUMERIC_DEFRAG] >= 0)	/* UMFPACK_numeric called */
396     {
397 	PRINTF (("\n    symbolic/numeric factorization:      upper bound")) ;
398 	PRINTF (("               actual      %%\n")) ;
399 	PRINTF (("    variable-sized part of Numeric object:\n")) ;
400     }
401     print_ratio ("    initial size (Units)", " %20.0f",
402 	Info [UMFPACK_VARIABLE_INIT_ESTIMATE], Info [UMFPACK_VARIABLE_INIT]) ;
403     print_ratio ("    peak size (Units)", " %20.0f",
404 	Info [UMFPACK_VARIABLE_PEAK_ESTIMATE], Info [UMFPACK_VARIABLE_PEAK]) ;
405     print_ratio ("    final size (Units)", " %20.0f",
406 	Info [UMFPACK_VARIABLE_FINAL_ESTIMATE], Info [UMFPACK_VARIABLE_FINAL]) ;
407     print_ratio ("Numeric final size (Units)", " %20.0f",
408 	Info [UMFPACK_NUMERIC_SIZE_ESTIMATE], Info [UMFPACK_NUMERIC_SIZE]) ;
409     print_ratio ("Numeric final size (MBytes)", " %20.1f",
410 	MBYTES (Info [UMFPACK_NUMERIC_SIZE_ESTIMATE]),
411 	MBYTES (Info [UMFPACK_NUMERIC_SIZE])) ;
412     print_ratio ("peak memory usage (Units)", " %20.0f",
413 	Info [UMFPACK_PEAK_MEMORY_ESTIMATE], Info [UMFPACK_PEAK_MEMORY]) ;
414     print_ratio ("peak memory usage (MBytes)", " %20.1f",
415 	MBYTES (Info [UMFPACK_PEAK_MEMORY_ESTIMATE]),
416 	MBYTES (Info [UMFPACK_PEAK_MEMORY])) ;
417     print_ratio ("numeric factorization flops", " %20.5e",
418 	Info [UMFPACK_FLOPS_ESTIMATE], Info [UMFPACK_FLOPS]) ;
419 
420     lnz_est = Info [UMFPACK_LNZ_ESTIMATE] ;
421     unz_est = Info [UMFPACK_UNZ_ESTIMATE] ;
422     if (lnz_est >= 0 && unz_est >= 0)	/* double relop, but ignore NaN case */
423     {
424 	lunz_est = lnz_est + unz_est - n_inner ;
425     }
426     else
427     {
428 	lunz_est = EMPTY ;
429     }
430     lnz = Info [UMFPACK_LNZ] ;
431     unz = Info [UMFPACK_UNZ] ;
432     if (lnz >= 0 && unz >= 0)		/* double relop, but ignore NaN case */
433     {
434 	lunz = lnz + unz - n_inner ;
435     }
436     else
437     {
438 	lunz = EMPTY ;
439     }
440     print_ratio ("nz in L (incl diagonal)", " %20.0f", lnz_est, lnz) ;
441     print_ratio ("nz in U (incl diagonal)", " %20.0f", unz_est, unz) ;
442     print_ratio ("nz in L+U (incl diagonal)", " %20.0f", lunz_est, lunz) ;
443 
444     print_ratio ("largest front (# entries)", " %20.0f",
445 	Info [UMFPACK_MAX_FRONT_SIZE_ESTIMATE], Info [UMFPACK_MAX_FRONT_SIZE]) ;
446     print_ratio ("largest # rows in front", " %20.0f",
447 	Info [UMFPACK_MAX_FRONT_NROWS_ESTIMATE],
448 	Info [UMFPACK_MAX_FRONT_NROWS]) ;
449     print_ratio ("largest # columns in front", " %20.0f",
450 	Info [UMFPACK_MAX_FRONT_NCOLS_ESTIMATE],
451 	Info [UMFPACK_MAX_FRONT_NCOLS]) ;
452 
453     /* ---------------------------------------------------------------------- */
454     /* numeric factorization */
455     /* ---------------------------------------------------------------------- */
456 
457     tnum = Info [UMFPACK_NUMERIC_TIME] ;
458     twnum = Info [UMFPACK_NUMERIC_WALLTIME] ;
459     fnum = Info [UMFPACK_FLOPS] ;
460 
461     PRINT_INFO ("\n    initial allocation ratio used:                 %0.3g\n",
462 	Info [UMFPACK_ALLOC_INIT_USED]) ;
463     PRINT_INFO ("    # of forced updates due to frontal growth:     %.0f\n",
464 	Info [UMFPACK_FORCED_UPDATES]) ;
465     PRINT_INFO ("    number of off-diagonal pivots:                 %.0f\n",
466 	Info [UMFPACK_NOFF_DIAG]) ;
467     PRINT_INFO ("    nz in L (incl diagonal), if none dropped       %.0f\n",
468 	Info [UMFPACK_ALL_LNZ]) ;
469     PRINT_INFO ("    nz in U (incl diagonal), if none dropped       %.0f\n",
470 	Info [UMFPACK_ALL_UNZ]) ;
471     PRINT_INFO ("    number of small entries dropped                %.0f\n",
472 	Info [UMFPACK_NZDROPPED]) ;
473     PRINT_INFO ("    nonzeros on diagonal of U:                     %.0f\n",
474 	Info [UMFPACK_UDIAG_NZ]) ;
475     PRINT_INFO ("    min abs. value on diagonal of U:               %.2e\n",
476 	Info [UMFPACK_UMIN]) ;
477     PRINT_INFO ("    max abs. value on diagonal of U:               %.2e\n",
478 	Info [UMFPACK_UMAX]) ;
479     PRINT_INFO ("    estimate of reciprocal of condition number:    %.2e\n",
480 	Info [UMFPACK_RCOND]) ;
481     PRINT_INFO ("    indices in compressed pattern:                 %.0f\n",
482 	Info [UMFPACK_COMPRESSED_PATTERN]) ;
483     PRINT_INFO ("    numerical values stored in Numeric object:     %.0f\n",
484 	Info [UMFPACK_LU_ENTRIES]) ;
485     PRINT_INFO ("    numeric factorization defragmentations:        %.0f\n",
486 	Info [UMFPACK_NUMERIC_DEFRAG]) ;
487     PRINT_INFO ("    numeric factorization reallocations:           %.0f\n",
488 	Info [UMFPACK_NUMERIC_REALLOC]) ;
489     PRINT_INFO ("    costly numeric factorization reallocations:    %.0f\n",
490 	Info [UMFPACK_NUMERIC_COSTLY_REALLOC]) ;
491     PRINT_INFO ("    numeric factorization wallclock time (sec):    %.2f\n",
492 	twnum) ;
493 
494 #define TMIN 0.001
495 
496     if (twnum > TMIN && fnum > 0)
497     {
498 	PRINT_INFO (
499 	   "    numeric factorization mflops (wallclock):      %.2f\n",
500 	   1e-6 * fnum / twnum) ;
501     }
502 
503     ftot = fnum ;
504 
505     twtot = EMPTY ;
506     if (twsym >= TMIN && twnum >= TMIN)
507     {
508 	twtot = twsym + twnum ;
509 	PRINT_INFO ("    symbolic + numeric wall clock time (sec):      %.2f\n",
510 	    twtot) ;
511 	if (ftot > 0 && twtot > TMIN)
512 	{
513 	    PRINT_INFO (
514 		"    symbolic + numeric mflops (wall clock):        %.2f\n",
515 		1e-6 * ftot / twtot) ;
516 	}
517     }
518 
519     /* ---------------------------------------------------------------------- */
520     /* solve */
521     /* ---------------------------------------------------------------------- */
522 
523     tsolve = Info [UMFPACK_SOLVE_TIME] ;
524     twsolve = Info [UMFPACK_SOLVE_WALLTIME] ;
525     fsolve = Info [UMFPACK_SOLVE_FLOPS] ;
526 
527     PRINT_INFO ("\n    solve flops:                                   %.5e\n",
528 	fsolve) ;
529     PRINT_INFO ("    iterative refinement steps taken:              %.0f\n",
530 	Info [UMFPACK_IR_TAKEN]) ;
531     PRINT_INFO ("    iterative refinement steps attempted:          %.0f\n",
532 	Info [UMFPACK_IR_ATTEMPTED]) ;
533     PRINT_INFO ("    sparse backward error omega1:                  %.2e\n",
534 	Info [UMFPACK_OMEGA1]) ;
535     PRINT_INFO ("    sparse backward error omega2:                  %.2e\n",
536 	Info [UMFPACK_OMEGA2]) ;
537     PRINT_INFO ("    solve wall clock time (sec):                   %.2f\n",
538 	twsolve) ;
539     if (fsolve > 0 && twsolve > TMIN)
540     {
541 	PRINT_INFO (
542 	    "    solve mflops (wall clock time):                %.2f\n",
543 	    1e-6 * fsolve / twsolve) ;
544     }
545 
546     if (ftot >= 0 && fsolve >= 0)
547     {
548 	ftot += fsolve ;
549 	PRINT_INFO (
550 	"\n    total symbolic + numeric + solve flops:        %.5e\n", ftot) ;
551     }
552 
553     if (twsolve >= TMIN)
554     {
555 	if (twtot >= TMIN && ftot >= 0)
556 	{
557 	    twtot += tsolve ;
558 	    PRINT_INFO (
559 		"    total symbolic+numeric+solve wall clock time:  %.2f\n",
560 		twtot) ;
561 	    if (ftot > 0 && twtot > TMIN)
562 	    {
563 		PRINT_INFO (
564 		"    total symbolic+numeric+solve mflops(wallclock) %.2f\n",
565 		1e-6 * ftot / twtot) ;
566 	    }
567 	}
568     }
569     PRINTF (("\n")) ;
570 }
571