function test22(nmat)
%TEST22 test pos.def and indef. matrices
% Example:
% test22(nmat)
%
% if nmat <= 0, just test problematic matrices
% See also cholmod_test

% Copyright 2006-2023, Timothy A. Davis, All Rights Reserved.
% SPDX-License-Identifier: GPL-2.0+

fprintf ('=================================================================\n');
fprintf ('test22: test pos.def and indef. matrices\n') ;

index = ssget ;

[ignore f] = sort (index.nrows) ;

if (nargin > 0)
    problematic = (nmat <= 0) ;
    if (problematic)
        % Matrices for which MATLAB and CHOLMOD differ, for which the error
        % is high, or other issues arose during debugging
        fprintf ('testing matrices for which MATLAB and CHOLMOD differ\n') ;
        f = [
            186 % HB/jgl011
            109 % HB/curtis54
            793 % Qaplib/lp_nug05
            607 % LPnetlib/lp_brandy
            707 % LPnetlib/lp_bore3d
            231 % HB/plskz362
            794 % Qaplib/lp_nug06
            673 % LPnetlib/lp_scorpion
           1156 % Sandia/oscil_dcop_45 (also 1157:1168)
            795 % Qaplib/lp_nug07
            796 % Qaplib/lp_nug08
            260 % HB/well1033
            261 % HB/well1850
            230 % HB/plsk1919
            649 % LPnetlib/lp_pds_02
            660 % LPnetlib/lp_qap12
            609 % LPnetlib/lp_cre_a
            619 % LPnetlib/lp_dfl001
            661 % LPnetlib/lp_qap15
            650 % LPnetlib/lp_pds_06
            379 % Cote/vibrobox
            638 % LPnetlib/lp_ken_11
            799 % Qaplib/lp_nug20
            ]' ;
    else
        nmat = max (0,nmat) ;
        nmat = min (nmat, length (f)) ;
        f = f (1:nmat) ;
    end
end

skip = [
    811, ...            % Simon/appu, which is a random matrix
    937:939, ...        % large ND/ problems
    1157:1168 ...       % duplicates
    799                 % rather large: Qaplib/lp_nug20
    ] ;

tlimit = 0.1 ;
fprintf ('test22: chol and chol2 are repeated so each take >= %g sec\n',tlimit);

klimit = 1 ;

% warmup, for more accurate timing
[R,p] = chol (sparse (1)) ;                                                 %#ok
[R,p] = chol2 (sparse (1)) ;                                                %#ok
clear R p

for i = f

    if (any (i == skip))
        continue ;
    end

    Problem = ssget (i) ;
    A = Problem.A ;
    [m n] = size (A) ;
    fprintf ('\n================== %4d: Problem: %s  m: %d n: %d nnz: %d', ...
        i, Problem.name, m, n, nnz (A)) ;
    clear Problem ;

    try % create a symmetric version of the matrix
        if (m == n)
            if (nnz (A-A') > 0)
                A = A+A' ;
            end
        else
            A = A*A' ;
        end
    catch
        fprintf ('skip\n') ;
        continue
    end

    fprintf (' %d\n', nnz (A)) ;

    p = amd2 (A) ;
    A = A (p,p) ;
    anorm = norm (A,1) ;

    % Run each code for at least 'tlimit' seconds

    % MATLAB
    k = 0 ;
    t1 = 0 ;
    while (t1 < tlimit & k < klimit)                                        %#ok
        tic ;
        [R1,p1] = chol (A) ;
        t = toc ;
        t1 = t1 + t ;
        k = k + 1 ;
    end
    t1 = t1 / k ;

    % CHOLMOD
    k = 0 ;
    t2 = 0 ;
    while (t2 < tlimit & k < klimit)                                        %#ok
        tic ;
        [R2,p2] = chol2 (A) ;
        t = toc ;
        t2 = t2 + t ;
        k = k + 1 ;
    end
    t2 = t2 / k ;

    if (klimit == 1)
        rmin = full (min (abs (diag (R2)))) ;
        rmax = full (max (abs (diag (R2)))) ;
        if (p2 ~= 0 | isnan (rmin) | isnan (rmax) | rmax == 0)              %#ok
            rcond = 0 ;
        else
            rcond = rmin / rmax ;
        end
        fprintf ('rcond: %30.20e\n', rcond) ;
    end

    if (p1 == 1)
        % MATLAB does not follow its own definitions.  If p is 1, then R is
        % supposed to be 0-by-n, not 0-by-0.  CHOLMOD fixes this bug.
        % Here, A is m-by-m
        R1 = sparse (0,m) ;
    end

    kerr = 0 ;
    if (p1 ~= p2)
        % MATLAB and CHOLMOD don't agree.  See if both are correct,
        % because differences in roundoff errors can make one go
        % a little farther than the other.

        % if p1 is zero, it means MATLAB was fully successful
        k1 = p1 ;
        if (k1 == 0)
            k1 = n ;
        end

        % if p2 is zero, it means CHOLMOD was fully successful
        k2 = p2 ;
        if (k2 == 0)
            k2 = n ;
        end

        if (k1 > k2)
            % MATLAB went further than CHOLMOD. This is OK if MATLAB found
            % a small entry where CHOLMOD stopped.
            k = k2 ;
            kerr = R1 (k,k) ;
            % now reduce R1 in size, to compare with R2
            R1 = R1 (1:k2-1,:) ;
        else
            % CHOLMOD went further than MATLAB. This is OK if CHOLMOD found
            % a small entry where MATLAB stopped.
            k = k1 ;
            kerr = R2 (k,k) ;
            % now reduce R2 in size, to compare with R1
            R2 = R2 (1:k1-1,:) ;
        end
    end

    err = norm (R1-R2,1) / max (anorm,1) ;
    fprintf ('p: %6d %6d MATLAB: %10.4f CHOLMOD: %10.4f speedup %6.2f err:', ...
        p1, p2, t1, t2, t1/t2) ;

    if (err == 0)
        fprintf ('      0') ;
    else
        fprintf (' %6.0e', err) ;
    end

    if (kerr == 0)
        fprintf ('      0\n') ;
    else
        fprintf (' %6.0e\n', kerr) ;
    end

%    if (err > 1e-6)
%       error ('!') ;
%    end

% pause
    clear R1 R2 p1 p2 p A

end

fprintf ('test22: all tests passed\n') ;
