1function spqr_rank_stats (stats, print_opts)
2%SPQR_RANK_STATS prints the statistics from spqr_rank functions
3%
4% For a detailed description of the meaning of the basic statistic for
5% spqr_basic, spqr_null, spqr_pinv or spqr_cod, just type
6% 'spqr_rank_stats' with no inputs.  Type spqr_rank_stats('ssi') or
7% spqr_rank_stats('ssp') for a description of the basic statistics for
8% sqpr_ssi or spqr_ssp, respectively. spqr_rank_stats(1) also prints a
9% detailed description of all statistics calculated by any spqr_function
10% when opts.get_details is 1.  To print a summary of the stats struct
11% returned by a spqr_rank function, use spqr_rank_stats(stats) or
12% spqr_rank_stats(stats,1).
13%
14% Examples
15%
16% spqr_rank_stats ;          % prints a description of basic statistics
17%                            % from spqr_basic, spqr_null, spqr_pinv, spqr_cod
18% spqr_rank_stats('ssi') ;   % description of basic statistics from spqr_ssi
19% spqr_rank_stats('ssp') ;   % description of basic statistics from spqr_ssp
20% spqr_rank_stats ( 1 ) ;    % prints a verbose description of all statistics
21% spqr_rank_stats (stats) ;  % prints a short summary of the stats struct
22% spqr_rank_stats (stats,1); % prints options used, when opts.get_details is 1
23%
24% See also spqr_basic, spqr_cod, spqr_pinv, spqr_ssi, spqr_ssp
25
26% Copyright 2012, Leslie Foster and Timothy A Davis
27
28if (nargin == 0)
29    stats = 0 ;
30    get_details = 0 ;
31    method = 1 ;   % spqr_basic, spqr_null, spqr_cod, spqr_pinv
32end
33
34if ( nargin == 1 )
35    if ischar(stats)
36        get_details = 0 ;
37        if ( strcmp(stats,'spqr_ssi') || strcmp(stats,'ssi') )
38            method = 2 ;   % spqr_ssp
39        elseif ( strcmp(stats,'spqr_ssp') || strcmp(stats,'ssp') )
40            method = 3 ;   % spqr_ssi
41        else
42            method = 1;    % spqr_basic, spqr_null, spqr_cod, spqr_pinv
43        end
44    elseif isreal(stats)
45        get_details = stats;
46        method = 4;    % any method
47    end
48    print_opts = 0 ;
49end
50
51if (isstruct (stats))
52
53    %---------------------------------------------------------------------------
54    % print the stats returned by the spqr_* function
55    %---------------------------------------------------------------------------
56
57    %---------------------------------------------------------------------------
58    % flag
59    %---------------------------------------------------------------------------
60
61    flag = -1 ;
62    if (isfield (stats, 'flag'))
63        flag = stats.flag ;
64    end
65
66    if ~isfield( stats, 'est_svals')
67        % description of flag for calls except for call to spqr_ssp
68        if (flag == 0)
69            fprintf ('\n  flag : %g : ', flag) ;
70            fprintf ('ok.  stats.rank very likely to be correct.\n') ;
71        elseif (flag <= 2)
72            fprintf ('\n  flag : %g : ', flag) ;
73            fprintf ('stats.rank may be correct for tolerance stats.tol,\n') ;
74            fprintf ('      but error bounds are too high to confirm this.\n') ;
75            if (flag == 1)
76                fprintf (['      However, stats.rank appears to be correct' ...
77                    ' for tolerance stats.tol_alt.\n']) ;
78            end
79        elseif (flag == 3)
80            fprintf ('\n  flag : %g : ', flag) ;
81            fprintf ('poor results.  stats.rank is likely too high.\n') ;
82        elseif (flag == 4)
83            fprintf ('\n  flag : %g : ', flag) ;
84            fprintf ('failure.  Overflow during inverse power method.\n') ;
85%       elseif (flag == 5)
86%           % this code is disabled because stats.flag=5 is removed.
87%           fprintf ('\n  flag : %g : ', flag) ;
88%           fprintf ('failure.  Inconsistent rank estimates.\n') ;
89        else
90            error ('spqr_rank:invalid', 'invalid stats') ;
91        end
92    else
93        % description of flag for calls to spqr_ssp
94        fprintf ('\n  flag : %g : ', flag) ;
95        if (flag == 0)
96            fprintf (['ok. spqr_ssp converged with est. relative error ' ...
97                '<= opts_ssp.convergence_factor.\n']) ;
98        else
99            fprintf (['spqr_ssp did not converge with est. relative error ' ...
100                '<= opts_ssp.convergence_factor.\n']) ;
101        end
102    end
103
104    %---------------------------------------------------------------------------
105    % rank
106    %---------------------------------------------------------------------------
107
108    if (isfield (stats, 'rank'))
109        fprintf ('  rank : %g : estimate of numerical rank.\n', stats.rank) ;
110    end
111
112    %---------------------------------------------------------------------------
113    % rank_spqr
114    %---------------------------------------------------------------------------
115
116    if (isfield (stats, 'rank_spqr'))
117        fprintf ('  rank_spqr : %g : ', stats.rank_spqr) ;
118        fprintf ('estimate of numerical rank from spqr.\n') ;
119        fprintf ('      This is normally an upper bound on the true rank.\n') ;
120    end
121
122    %---------------------------------------------------------------------------
123    % tol
124    %---------------------------------------------------------------------------
125
126    if (isfield (stats, 'tol'))
127        fprintf ('  tol : %g : numerical tolerance used.\n', stats.tol) ;
128    end
129
130    %---------------------------------------------------------------------------
131    % tol_alt
132    %---------------------------------------------------------------------------
133
134    if (isfield (stats, 'tol_alt'))
135        fprintf ('  tol_alt : %g : alternate numerical tolerance used.\n', ...
136            stats.tol_alt) ;
137    end
138
139    %---------------------------------------------------------------------------
140    % normest_A
141    %---------------------------------------------------------------------------
142
143    if (isfield (stats, 'normest_A'))
144        fprintf ('  normest_A : %g : estimate of Euclidean norm of A.\n', ...
145            stats.normest_A) ;
146    end
147
148    %---------------------------------------------------------------------------
149    % normest_R
150    %---------------------------------------------------------------------------
151
152    if (isfield (stats, 'normest_R'))
153        fprintf (['  normest_R : %g : estimate of Euclidean norm of R ' ...
154            '(calculated for spqr_ssi).\n'], ...
155            stats.normest_R) ;
156    end
157
158    %---------------------------------------------------------------------------
159    % est_svals_upper_bounds
160    %---------------------------------------------------------------------------
161
162    if (isfield (stats, 'est_sval_upper_bounds'))
163        fprintf ('  est_sval_upper_bounds : ') ;
164        print_vector (stats.est_sval_upper_bounds) ;
165        fprintf ('      : estimated upper bounds on singular value(s).\n') ;
166    end
167
168    %---------------------------------------------------------------------------
169    % est_svals_lower_bounds
170    %---------------------------------------------------------------------------
171
172    if (isfield (stats, 'est_sval_lower_bounds'))
173        fprintf ('  est_sval_lower_bounds : ') ;
174        print_vector (stats.est_sval_lower_bounds) ;
175        fprintf ('      : estimated lower bounds on singular value(s).\n') ;
176    end
177
178    %---------------------------------------------------------------------------
179    % est_svals_of_R
180    %---------------------------------------------------------------------------
181
182    if (isfield (stats, 'est_svals_of_R'))
183        fprintf ('  est_svals_of_R : ') ;
184        print_vector (stats.est_svals_of_R) ;
185        fprintf (['      : estimated singular value(s) of triangular ' ...
186            'matrix R.\n']) ;
187    end
188
189    %---------------------------------------------------------------------------
190    % est_svals
191    %---------------------------------------------------------------------------
192
193    if (isfield (stats, 'est_svals'))
194        fprintf ('  est_svals : ') ;
195        print_vector (stats.est_svals) ;
196        fprintf (['      : estimated singular value(s) of A*N or A''*NT, ' ...
197            'from spqr_ssp.\n']) ;
198    end
199
200    %---------------------------------------------------------------------------
201    % est_error_bounds
202    %---------------------------------------------------------------------------
203
204    if (isfield (stats, 'est_error_bounds'))
205        fprintf ('  est_error_bounds : ') ;
206        print_vector (stats.est_error_bounds) ;
207        fprintf ('      : error bounds for each singular value.\n') ;
208    end
209
210    %---------------------------------------------------------------------------
211    % sval_numbers_for_bounds
212    %---------------------------------------------------------------------------
213
214    if (isfield (stats, 'sval_numbers_for_bounds'))
215        fprintf ('  sval_numbers_for_bounds : ') ;
216        print_vector (stats.sval_numbers_for_bounds) ;
217        fprintf ('      : index of singular value(s), for bounds.\n') ;
218    end
219
220    %---------------------------------------------------------------------------
221    % est_norm_A_times_N
222    %---------------------------------------------------------------------------
223
224    if (isfield (stats, 'est_norm_A_times_N'))
225        fprintf (['  est_norm_A_times_N : %g : estimated' ...
226            ' norm(A*N).\n'], stats.est_norm_A_times_N) ;
227    end
228
229    %---------------------------------------------------------------------------
230    % est_err_bound_norm_A_times_N
231    %---------------------------------------------------------------------------
232
233    if (isfield (stats, 'est_err_bound_norm_A_times_N'))
234        fprintf (['  est_err_bound_norm_A_times_N : %g : estimated error ' ...
235            'bound for norm(A*N).\n'], stats.est_err_bound_norm_A_times_N) ;
236    end
237
238    %---------------------------------------------------------------------------
239    % est_norm_A_transpose_times_NT
240    %---------------------------------------------------------------------------
241
242    if (isfield (stats, 'est_norm_A_transpose_times_NT'))
243        fprintf (['  est_norm_A_transpose_times_NT : %g : estimated' ...
244            ' norm(A''*NT).\n'], stats.est_norm_A_transpose_times_NT) ;
245    end
246
247    %---------------------------------------------------------------------------
248    % est_err_bound_norm_A_transpose_times_NT
249    %---------------------------------------------------------------------------
250
251    if (isfield (stats, 'est_err_bound_norm_A_transpose_times_NT'))
252        fprintf (['  est_err_bound_norm_A_transpose_times_NT : %g : ' ...
253            ' estimated error bound for norm(A''*NT).\n'], ...
254            stats.est_err_bound_norm_A_transpose_times_NT) ;
255    end
256
257    %---------------------------------------------------------------------------
258    % norm_R_times_N
259    %---------------------------------------------------------------------------
260
261    if (isfield (stats, 'norm_R_times_N'))
262        fprintf (['  norm_R_times_N : %g : norm of (R*N), from ' ...
263            'spqr_ssi.\n'], stats.norm_R_times_N) ;
264    end
265
266    %---------------------------------------------------------------------------
267    % norm_R_transpose_times_NT
268    %---------------------------------------------------------------------------
269
270    if (isfield (stats, 'norm_R_transpose_times_NT'))
271        fprintf (['  norm_R_transpose_times_NT : %g : norm of (R''*NT), '...
272            'from spqr_ssi.\n'], stats.norm_R_transpose_times_NT) ;
273    end
274
275    %---------------------------------------------------------------------------
276    % iters
277    %---------------------------------------------------------------------------
278
279    if (isfield (stats, 'iters'))
280        fprintf ('  iters : %g : iterations in spqr_ssi or spqr_ssp.\n', ...
281            stats.iters) ;
282    end
283
284    %---------------------------------------------------------------------------
285    % nsvals_large_found
286    %---------------------------------------------------------------------------
287
288    if (isfield (stats, 'nsvals_large_found'))
289        fprintf (['  nsvals_large_found : %d : number of large singular ' ...
290            'values found.\n'], stats.nsvals_large_found) ;
291    end
292
293    %---------------------------------------------------------------------------
294    % final_blocksize
295    %---------------------------------------------------------------------------
296
297    if (isfield (stats, 'final_blocksize'))
298        fprintf ('  final_blocksize : %d : final block size in spqr_ssi.\n', ...
299            stats.final_blocksize) ;
300    end
301
302    %---------------------------------------------------------------------------
303    % ssi_max_block_used
304    %---------------------------------------------------------------------------
305
306    if (isfield (stats, 'ssi_max_block_used'))
307        fprintf (['  ssi_max_block_used : %d : max block size for ' ...
308            'spqr_ssi.\n'], stats.ssi_max_block_used) ;
309    end
310
311    %---------------------------------------------------------------------------
312    % ssi_min_block_used
313    %---------------------------------------------------------------------------
314
315    if (isfield (stats, 'ssi_min_block_used'))
316        fprintf (['  ssi_min_block_used : %d : initial block size for ' ...
317            'spqr_ssi.\n'], stats.ssi_min_block_used) ;
318    end
319
320    %---------------------------------------------------------------------------
321    % time
322    %---------------------------------------------------------------------------
323
324    if (isfield (stats, 'time'))
325        fprintf (['  time : %g : total time taken ' ...
326            '(includes all timings below).\n'], stats.time) ;
327    end
328
329    %---------------------------------------------------------------------------
330    % time_initialize
331    %---------------------------------------------------------------------------
332
333    if (isfield (stats, 'time_initialize'))
334        fprintf ('  time_initialize : %g : time to initialize',...
335            stats.time_initialize) ;
336        if isfield (stats, 'normest_A') || isfield (stats, 'normest_R')
337            fprintf (' including estimating the norm of A or R.\n')
338        else
339            fprintf('.\n')
340        end
341    end
342
343    %---------------------------------------------------------------------------
344    % time_svd
345    %---------------------------------------------------------------------------
346
347    if (isfield (stats, 'time_svd'))
348        fprintf ('  time_svd : %g : total time taken by svd.\n', ...
349            stats.time_svd) ;
350    end
351
352    %---------------------------------------------------------------------------
353    % time_basis
354    %---------------------------------------------------------------------------
355
356    if (isfield (stats, 'time_basis'))
357        fprintf ('  time_basis : %g : time to compute basis.\n', ...
358            stats.time_basis) ;
359    end
360
361    %---------------------------------------------------------------------------
362    % time_iters
363    %---------------------------------------------------------------------------
364
365    if (isfield (stats, 'time_iters'))
366        fprintf ('  time_iters : %g : time for spqr_ssi iterations.\n', ...
367            stats.time_iters) ;
368    end
369
370    %---------------------------------------------------------------------------
371    % time_est_error_bounds
372    %---------------------------------------------------------------------------
373
374    if (isfield (stats, 'time_est_error_bounds'))
375        fprintf (['  time_est_error_bounds : %g : time taken to estimate '...
376            'error bounds in spqr_ssi.\n'], stats.time_est_error_bounds) ;
377    end
378
379    %---------------------------------------------------------------------------
380    % opts_used
381    %---------------------------------------------------------------------------
382
383    if (print_opts && isfield (stats, 'opts_used'))
384        fprintf ('\nopts_used : ') ;
385        spqr_rank_opts (stats.opts_used) ;
386    end
387
388    %---------------------------------------------------------------------------
389    % info_spqr1
390    %---------------------------------------------------------------------------
391
392    if (isfield (stats, 'info_spqr1'))
393        fprintf ('\ninfo_spqr1 : statistics from first QR factorization.\n\n') ;
394        disp (stats.info_spqr1) ;
395    end
396
397    %---------------------------------------------------------------------------
398    % info_spqr2
399    %---------------------------------------------------------------------------
400
401    if (isfield (stats, 'info_spqr2'))
402        fprintf ('\ninfo_spqr2 : statistics from second QR factorization.\n\n');
403        disp (stats.info_spqr2) ;
404    end
405
406    %---------------------------------------------------------------------------
407    % stats_ssi
408    %---------------------------------------------------------------------------
409
410    if (isfield (stats, 'stats_ssi'))
411        % all opts used by spqr_ssp are the same stats.opts_used
412        fprintf ('\nstats_ssi : statistics from spqr_ssi.\n') ;
413        spqr_rank_stats (stats.stats_ssi, 0) ;
414    end
415
416    %---------------------------------------------------------------------------
417    % stats_ssp_N
418    %---------------------------------------------------------------------------
419
420    if (isfield (stats, 'stats_ssp_N'))
421
422        fprintf ('\nstats_ssp_N : statistics from spqr_ssp (A,N).\n') ;
423        spqr_rank_stats (stats.stats_ssp_N, 0) ;
424        % all other opts used by spqr_ssp are the same stats.opts_used
425        if (isfield (stats.stats_ssp_N, 'opts_used') && ...
426            isfield (stats.stats_ssp_N.opts_used, 'k') && print_opts)
427                fprintf (['  stats_ssp_N.opts_used.k : %d : number of ' ...
428                'singular values to compute in spqr_ssp(A,N).\n'], ...
429                stats.stats_ssp_N.opts_used.k) ;
430        end
431    end
432
433    %---------------------------------------------------------------------------
434    % stats_ssp_NT
435    %---------------------------------------------------------------------------
436
437    if (isfield (stats, 'stats_ssp_NT'))
438        fprintf ('\nstats_ssp_NT : statistics from spqr_ssp (A'',NT).\n') ;
439        spqr_rank_stats (stats.stats_ssp_NT, 0) ;
440        % all other opts used by spqr_ssp are the same stats.opts_used
441        if (isfield (stats.stats_ssp_NT, 'opts_used') && ...
442            isfield (stats.stats_ssp_NT.opts_used, 'k') && print_opts)
443                fprintf (['  stats_ssp_NT.opts_used.k : %d : number of ' ...
444                'singular values to compute in spqr_ssp(A'',NT).\n'], ...
445                stats.stats_ssp_NT.opts_used.k) ;
446        end
447    end
448
449    %---------------------------------------------------------------------------
450    % stats_spqr_basic
451    %---------------------------------------------------------------------------
452
453    if (isfield (stats, 'stats_spqr_basic'))
454        % all opts used by spqr_basic are the same stats.opts_used
455        fprintf ('\nstats_spqr_basic : statistics from spqr_basic.\n') ;
456        spqr_rank_stats (stats.stats_spqr_basic, 0) ;
457    end
458
459    %---------------------------------------------------------------------------
460    % stats_spqr_null
461    %---------------------------------------------------------------------------
462
463    if (isfield (stats, 'stats_spqr_null'))
464        fprintf ('\nstats_spqr_null : statistics from spqr_null.\n') ;
465        % all other opts used by spqr_null are the same stats.opts_used
466        if (isfield (stats.stats_spqr_null, 'opts_used') && ...
467            isfield (stats.stats_spqr_null.opts_used, 'ssi_min_block'))
468                fprintf (['\n  stats_spqr_null.opts_used.ssi_min_block : %d'...
469                ' : initial block size in spqr_ssi as used by spqr_null.'], ...
470                stats.stats_spqr_null.opts_used.ssi_min_block) ;
471        end
472        spqr_rank_stats (stats.stats_spqr_null, 0) ;
473
474    end
475
476else
477
478    %---------------------------------------------------------------------------
479    % describe each statistic
480    %---------------------------------------------------------------------------
481
482    fprintf ('\nDescription of stats returned by ') ;
483    if method == 1
484        fprintf ('spqr_basic, spqr_null,  spqr_pinv \nor spqr_cod:\n') ;
485    elseif method == 2
486        fprintf ('spqr_ssi:\n') ;
487    elseif method == 3
488        fprintf ('spqr_ssp:\n') ;
489    elseif method == 4
490        fprintf ('all spqr_functions:\n') ;
491    end
492
493    if ( method == 1  || method == 2 || get_details >= 1 )
494        fprintf ([ ...
495        '\nstats.flag (for all routines except spqr_ssp) -- \n' ...
496        '   if stats.flag is 0 if it is likely, although not\n' ...
497        '   guaranteed, that stats.rank is the correct numerical rank for\n' ...
498        '   tolerance stats.tol (i.e. agrees with the numerical rank\n' ...
499        '   determined by the singular values of R).\n' ...
500        '   \n'...
501        '   stats.flag is 1 if the calculated numerical rank stats.rank ' ...
502            'may\n'...
503        '   be correct for the tolerance stats.tol but the estimated error\n'...
504        '   bounds are too large to confirm this.  However stats.rank '...
505            'appears\n'...
506        '   to be correct for an alternate tolerance stats.tol_alt.  More\n'...
507        '   generally stats.rank appears to be correct for any tolerance\n'...
508        '   between stats.est_sval_lower_bounds(nsvals_large) and\n'...
509        '   stats.est_sval_upper_bounds(nsvals_large+1).\n' ...
510        '   \n'...
511        '   stats.flag is 2 if the calculated numerical rank ' ...
512            'stats.numerical\n'...
513        '   may be correct but estimated error bounds are too large to ' ...
514            'confirm\n'...
515        '   this.  The conditions for stats.flag to be 0 or 1 are not\n'...
516        '   satisfied.\n' ...
517        '   \n'...
518        '   stats.flag is 3 if is likely that the numerical rank returned,\n'...
519        '   stats.rank, is too large.\n'...
520        '   \n'...
521        '   stats.flag is 4 if overflow occurred during the inverse power\n'...
522        '   method.  The method fails in this case, and all parameters ' ...
523            'other\n'...
524        '   stats are returned as empty ([ ]).\n' ...
525        '   \n'...
526        '   stats.flag is 5 if a catastrophic failure occurred.\n']) ;
527    end
528
529    if ( method == 3 || get_details >= 1 )
530        fprintf ([ ...
531        '\nstats.flag -- (for spqr_ssp) \n' ...
532        '   stats.flag is 0 if spqr_ssp converged with estimated relative\n' ...
533        '   error in singular value opts.k of A (or of A*N) <=\n' ...
534        '   opts_ssp.convergence_factor. stats.flag is 1 if this is not ' ...
535            'true.\n'])
536    end
537
538    if ( method == 1 || method == 2 || get_details >= 1 )
539        fprintf ([ ...
540        '\nstats.rank -- the estimated numerical rank when stats.flag is\n' ...
541        '   0, 1 or 2.  stats.rank is typically an upper bound on the\n'...
542        '   numerical rank when stats.flag is 3.  Note that stats.rank ' ...
543            'is a\n'...
544        '   correction to the rank returned by spqr (stats.rank_spqr) ' ...
545            'in the\n'...
546        '   case that the calculations in the routine inidicate that the ' ...
547            'rank\n'...
548        '   returned by spqr not correct.\n']) ;
549    end
550
551    if ( method == 1 || method == 2 || get_details >= 1 )
552        fprintf ( ...
553        '\nstats.tol -- the tolerance used to define the numerical rank.\n') ;
554    end
555
556    if ( method == 1 || get_details >= 1 )
557        fprintf ([ ...
558        '\nstat.tol_alt -- an alternate tolerance that corresponds to the\n' ...
559        '   calculated numerical rank when stats.flag is 1.\n']) ;
560
561        fprintf ([ ...
562        '\nstats.est_sval_upper_bounds -- stats.est_sval_upper_bounds(i) ' ...
563            'is an\n'...
564        '   estimate of an upper bound on singular value number\n' ...
565        '   stats.sval_numbers_for_bounds(i) of A.\n']) ;
566
567        fprintf ([ ...
568        '\nstats.est_sval_lower_bounds -- stats.est_sval_lower_bounds(i) ' ...
569            'is an\n'...
570        '   estimate of an lower bound on singular value number\n' ...
571        '   stats.sval_numbers_for_bounds(i) of A.\n']) ;
572
573        fprintf (['\n' ...
574        '   Note that stats.est_sval_upper_bounds(i) is a rigorous upper '...
575            'bound\n'...
576        '   on some singular value of (A+E) where where E is ' ...
577            'O(norm(A)*eps)\n'...
578        '   Also stats.est_sval_lower_bounds(i) is a rigorous lower ' ...
579            'bound on\n'...
580        '   some singular value of (A+E).  In both cases the singular ' ...
581            'value is\n'...
582        '   normally singular value number sval_numbers_for_bounds(i) ' ...
583            'of A,\n'...
584        '   but the singular value number is not guaranteed.  For i such ' ...
585            'that\n' ...
586        '   sval_numbers_for_bounds(i) = stats.rank (that is for estimates\n'...
587        '   of singular value stats.rank) if ' ...
588            'stats.est_sval_upper_bounds(i)\n' ...
589        '   is a large multiple of stats.est_sval_lower_bounds(i) then\n' ...
590        '   solution vectors x produced by spqr_basic may be ' ...
591            'inferior (i.e.\n'...
592        '   be significanty larger) than solutions produced by ' ...
593            'spqr_pinv or\n' ...
594        '   spqr_cod.\n']) ;
595    end
596
597    if ( method == 2 || get_details >= 1 )
598        fprintf ([ ...
599        '\nstats.est_svals_of_R -- computed by spqr_ssi.\n' ...
600        '   stats.est_svals_of_R contains estimates of the smallest ' ...
601            'singular\n' ...
602        '   of R.\n']) ;
603    end
604
605    if ( method == 3|| get_details >= 1 )
606        fprintf ([ ...
607        '\nstats.est_svals -- computed by spqr_ssp.\n' ...
608        '   stats.est_svals(i) is an estimate of the ith largest ' ...
609            'singular of\n' ...
610        '   A or of A*N.  Also for i = 1:nsval, stats.est_svals(i) is a ' ...
611            'lower\n' ...
612        '   bound on the ith largest singular value of A (or A*N).\n']) ;
613    end
614
615    if ( method == 2 || method == 3 || get_details >= 1 )
616        fprintf ([ ...
617        '\nstats.est_error_bounds -- computed by spqr_ssi and spqr_ssp.\n' ...
618        '   stats.est_error_bounds(i) is an estimated bound on the ' ...
619            'absolute\n'...
620        '   error in singular value number ' ...
621            'stats.sval_numbers_for_bounds(i).\n' ...
622        '   of R (for spqr_ssi) or of A or A*N (for spqr_ssp). It is ' ...
623            'also a\n' ...
624        '   rigorous bound on abs (s(i) - some true singular value of ' ...
625            '(B+E)),\n'...
626        '   where E is O(norm(B)*eps) and B = R (for spqr_ssi) and B =\n' ...
627        '   A or A*N (for spqr_ssp).\n']) ;
628     end
629
630    fprintf ([ ...
631    '\nstats.sval_numbers_for_bounds -- component i in the error bounds is ' ...
632        'an estimated\n'...
633    '   error bound for singular value number sval_numbers_for_bounds(i).\n']) ;
634
635    if ( method == 1 || get_details >= 1 )
636        fprintf ([ ...
637        '\nstats.est_norm_A_transpose_times_NT -- an estimate of ' ...
638            'norm(A''*NT).\n']) ;
639
640        fprintf ( ...
641        '\nstats.est_norm_A_times_N -- an estimate of norm(A*N).\n') ;
642    end
643
644    if (get_details >= 1)
645
646        fprintf (['\n***** Additional statistics when opts.get_details ' ...
647            'is 2: *****\n']) ;
648
649        fprintf ([ ...
650        '\nstats.rank_spqr -- the rough estimate of the numerical rank\n'...
651        '   computed by spqr.  This is typically correct if the numerical\n'...
652        '   rank is well-defined.\n']) ;
653
654        fprintf ('\nstats.stats_ssi -- statistics returned by spqr_ssi.\n') ;
655
656        fprintf ([ ...
657        '\nstats_ssi.ssi_max_block_used -- the maximum block size ' ...
658               'used by spqr_ssi.\n']) ;
659
660        fprintf ([ ...
661        '\nstats_ssi.ssi_min_block_used -- the initial block size ' ...
662               'used by spqr_ssi.\n']) ;
663    end
664
665    if  (get_details == 1)
666
667        fprintf (['\n***** Additions statistics when opts.get_details is ' ...
668            '1: *****\n']) ;
669
670        fprintf ([ ...
671        '\nstats.normest_A  -- an estimate of the Euclidean norm of A. '...
672            'Calculated using\n' ...
673        '   normest(A,0.01).\n']) ;
674
675        fprintf ([ ...
676        '\nstats.normest_R  -- an estimate of the Euclidean norm of R. '...
677            'Calculated for spqr_ssi\n' ...
678        '   using normest(R,0.01).\n']) ;
679
680        fprintf ([ ...
681        '\nstats.est_err_bound_norm_A_times_N  -- an estimate of an\n'...
682        '   error bound on stats.est_norm_A_times_N.  It is also a\n'...
683        '   rigorous bound on abs (stats.est_norm_A_times_N - s)\n'...
684        '   where s is some singular value of (A+E)*N and where E is\n' ...
685        '   O(norm(A)*eps). Usually the singular value is the first '...
686           'singular\n'...
687        '   value but this is not guaranteed.\n']) ;
688
689        fprintf ([ ...
690        '\nstats.est_err_bound_norm_A_transpose_times_NT  -- an estimate '...
691            'of an\n'...
692        '   error bound on stats.est_norm_A_transpose_times_NT.  It is '...
693            'also a\n'...
694        '   rigorous bound on abs (stats.est_norm_A_transpose_times_NT '...
695            '- s)\n'...
696        '   where s is some singular value of (A+E)''*NT and where E is\n' ...
697        '   O(norm(A)*eps). Usually the singular value is the first '...
698            'singular\n'...
699        '   value but this is not guaranteed.\n']) ;
700
701        fprintf ([ ...
702        '\nstats_ssi.norm_R_times_N -- Euclidean norm of (R*N), from ' ...
703              'spqr_ssi.\n']) ;
704
705        fprintf ([ ...
706        '\nstats_ssi.norm_R_transpose_times_NT -- Eucliean norm of ' ...
707              '(R''*NT), from spqr_ssi.\n']) ;
708
709        fprintf ([ ...
710        '\nstats_ssi.iters or stats_ssp_N.iters or stats_ssp_NT.iters -- ' ...
711            'number of\n' ...
712        '    iterations for subspace iteration in spqr_ssi or spqr_ssp.\n']) ;
713
714        fprintf ([ ...
715        '\nstats_ssi.nsvals_large_found -- the number of ''large'' (larger ' ...
716        'than tol) singular\n' ...
717        '   values found, from spqr_ssi.\n']) ;
718
719        fprintf ([ ...
720        '\nstats_ssi.final_blocksize -- final block size for subspace ' ...
721        'iteration in \n   spqr_ssi. \n']) ;
722
723        fprintf ([ ...
724        '\nstats.stats_spqr_basic -- statistics returned when spqr_basic ' ...
725        'is called by spqr_pinv.\n']) ;
726
727        fprintf ([ ...
728        '\nstats.stats_spqr_null -- statistics returned when spqr_null ' ...
729        'is called by spqr_pinv.\n']) ;
730
731        fprintf ([ ...
732        '\nstats.info_spqr1 -- statistics from spqr for the first QR ' ...
733           'factorization.\n' ...
734        '   See ''help spqr'' for details.\n']) ;
735
736        fprintf ([ ...
737        '\nstats.info_spqr2 -- statistics from spqr for the second QR ' ...
738           'factorization, if\n' ...
739        '   required.  See ''help spqr'' for details.\n']) ;
740
741        fprintf ([ ...
742        '\nstats.stats_ssp_N -- statistics from spqr_ssp when calculating ' ...
743           'the basis\n' ...
744        '   N for the null space of A.\n']) ;
745
746        fprintf ([ ...
747        '\nstats.stats_ssp_NT -- statistics from spqr_ssp when calculating ' ...
748           'the basis\n' ...
749        '   NT for the null space of A transpose.\n']) ;
750
751        fprintf ([ ...
752        '\nstats.opts_used, stats_ssi.opts_used, or stats_ssp.opts_used -- ' ...
753            'values of\n' ...
754        '   options used.  These can be different from values in opts ' ...
755            'since, for example,\n' ...
756        '   the size of A can restrict some values in opts.\n']) ;
757
758        fprintf ([ ...
759        '\nstats.time, stats_ssi.time, etc.  -- the total time of the ' ...
760           'routine including\n' ...
761        '   the times described below.\n']) ;
762
763        fprintf ([ ...
764        '\nstats.time_initialize, stats_ssi.time_initialize, etc. -- the '...
765            'time to\n' ...
766        '   set default values of opts, including calculating ' ...
767            'normest(A,0.01),\n' ...
768        '   or normest(R,0.01) if needed.\n']) ;
769
770        fprintf([ ...
771        '\nstats.time_basis -- the time to compute the basis for the ' ...
772            'numerical null space\n' ...
773        '   following any calls to spqr and spqr_ssi. This will be small\n'...
774        '   if the null space basis is returned in implicit form but can, '...
775           'in some cases,\n' ...
776        '   be significant if the null space basis is returned as an ' ...
777           'explicit matrix.\n']) ;
778
779        fprintf ([ ...
780        '\nstats_ssi.time_iters, stats_ssp_N.time_iters, etc.  -- the time ' ...
781           'for the\n' ...
782        '   subspace iterations in spqr_ssi or spqr_ssp. Excludes time '...
783           'for initialization,\n' ...
784        '   error flag calculation, etc..\n']) ;
785
786        fprintf ([ ...
787        '\nstats_ssi.time_est_error_bounds, ' ...
788           'stats_ssp_N.time_est_error_bounds, etc.  -- the time\n' ...
789           '   for estimating the singular value error bounds in ' ...
790               'spqr_ssi or spqr_ssp.\n']) ;
791
792        fprintf ([ ...
793        '\nstats.time_svd, stats_ssi.time_svd, etc.  -- the total time ' ...
794           'for calls to MATLAB''s SVD\n' ...
795        '   in the current routine and its subroutines.\n']) ;
796    end
797end
798
799%-------------------------------------------------------------------------------
800% print_vector
801%-------------------------------------------------------------------------------
802
803function print_vector (x)
804n = length (x) ;
805for k = 1:n
806fprintf (' %g', x (k)) ;
807end
808fprintf ('\n') ;
809