function [ a_lu, info ] = r8ge_np_trf ( m, n, a )

%*****************************************************************************80
%
%% R8GE_NP_TRF computes the LU factorization of a R8GE matrix.
%
%  Discussion:
%
%    The R8GE storage format is used for a general M by N matrix.  A storage
%    space is made for each logical entry.  The two dimensional logical
%    array is mapped to a vector, in which storage is by columns.
%
%    R8GE_NP_TRF is a nonpivoting version of R8GE_TRF, and will fail if
%    a zero element is encountered along the diagonal.
%
%    The factorization has the form
%      A = L * U
%    where L is lower triangular with unit diagonal elements (lower
%    trapezoidal if N < M), and U is upper triangular (upper trapezoidal
%    if M < N).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 March 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows of the matrix A.  0 <= M.
%
%    Input, integer N, the number of columns of the matrix A.  0 <= N.
%
%    Input, real A(M,N), the matrix to be factored.
%
%    Output, integer INFO.
%    = 0: successful exit
%    < 0: if INFO = -K, the K-th argument had an illegal value
%    > 0: if INFO = K, U(K,K) is exactly zero. The factorization
%         has been completed, but the factor U is exactly
%         singular, and division by zero will occur if it is used
%         to solve a system of equations.
%
%    Output, real A_LU(M,N), the factors L and U from the factorization
%    A = L*U; the unit diagonal elements of L are not stored.
%
  info = 0;
  a_lu(1:m,1:n) = a(1:m,1:n);
%
%  Test the input parameters.
%
  if ( m < 0 )
    info = -1;
    return
  elseif ( n < 0 )
    info = -2;
    return
  end

  if ( m == 0 | n == 0 )
    return
  end

  for j = 1 : min ( m, n )
%
%  Compute elements J+1:M of the J-th column.
%
    if ( a(j,j) ~= 0.0E+00 )
      a_lu(j+1:m,j) = a_lu(j+1:m,j) / a_lu(j,j);
    elseif ( info == 0 )
      info = j;
    end
%
%  Update the trailing submatrix.
%
    if ( j < min ( m, n ) )

      for ii = j+1 : m
        a_lu(ii,j+1:n) = a_lu(ii,j+1:n) - a_lu(ii,j) * a_lu(j,j+1:n);
      end

    end

  end

  return
end


function [y,r]=smooth(x,twice)
% SMOOTH will compute the non-linear running medians of
%     the input vector.  First it smooths the data, compute
%     the residuals, smooth the residuals, and add this back
%     to the first smooth.
%
% Usage: y = smooth(x, OPTIONAL twice?)
%  where x         is the input vector of minimum length 3
%        twice?    whether to do this twice (default = 1)
%        y         is the smoothed vector
%
% [y,r] = smooth(x, OPTIONAL twice?)
%     r  is the final residuals where x = y + r
%
% See also: R3R, SR, R3RSR, H

%
% Huy Le,  Massachusetts Institute of Technology.   1997
%
% See John Wilder Tukey, "EXPLORATORY DATA ANALYSIS".
% Addison-Wesley Publishing Co. 1977. Chpt 7, 16.

format long e;
xlen = length(x); x = x(:); y = x; r = x - y; batch = 1;
if nargin<2, twice = 1; end
if nargout<2, res = 0; end
if ~all(isfinite(x)), error('Input must have finite values.'); end
if xlen<3, error('Input vector must be at least 3 elements long.'); end
% first, run the 3RSR of vector x
xtemp1 = R3RSR(x,batch);
% first hanning
xtemp2 = H(xtemp1,batch);
% second hanning
xtemp1 = H(xtemp2,batch);
if twice,
   % compute first residuals
   rtemp = x - xtemp1;
   % run 3RSR on first residuals
   rtemp1 = R3RSR(rtemp,batch);
   % hanning of first residuals
   rtemp2 = H(rtemp1,batch);
   % sum of smooths
   xtemp = xtemp1 + rtemp2;
else
   xtemp = xtemp1;
end

for ii = 1:xlen,
   y(ii) = xtemp(ii);
   r(ii) = x(ii) - y(ii);
end

return


%DEMOPOLYGONCENTROIDS  One-line description here, please.
%
%   output = demoPolygonCentroids(input)
%
%   Example
%   demoPolygonCentroids
%
%   See also
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% INRAE - BIA Research Unit - BIBS Platform (Nantes)
% Created: 2022-02-16,    using Matlab 9.9.0.1570001 (R2020b) Update 4
% Copyright 2022 INRAE.

%% Demo polygon

% vertices of a "U"-shaped polygon
poly = [0 0;30 0;30 20;20 20;20 11;10 11;10 20;0 20];

% display the filled polygon and the open polyline
figure; hold on; axis equal; axis([-5 35 -5 30]);
fillPolygon(poly, 'c');
hPoly = drawPolygon(poly, 'linewidth', 2, 'color', 'k');
drawVertices(poly);

%% Computes various centroids

% computes the centroids
vxCentroid = centroid(poly);
lsCentroid = polylineCentroid(poly, 'closed');
pgCentroid = polygonCentroid(poly);

% display the centroids
hVxc = drawPoint(vxCentroid, 'marker', 'o', 'color', [0.8 0 0], 'linewidth', 2, 'MarkerFaceColor', 'w');
hLsc = drawPoint(lsCentroid, 'marker', 'o', 'color', [0 0.8 0], 'linewidth', 2, 'MarkerFaceColor', 'w');
hPgc = drawPoint(pgCentroid, 'marker', 'o', 'color', [0 0 0.8], 'linewidth', 2, 'MarkerFaceColor', 'w');

% decorate graph
legend([hPoly hVxc hLsc hPgc], ...
    {'Polygon', 'Vertex Centroid', 'Polyline Centroid', 'Polygon Centroid'}, ...
    'Location', 'NorthEast');

print(gcf, 'polygon_centroids.png', '-dpng');


function out = simbin(mat1,mat2,type,mask)

% Computes 106 measures of similarity and dissimilarity (distance) between
% two binary matrices. Matrices can be any dimensions, but must have the
% same dimensions. A mask can be used to indicate the relevant elements of
% the matrices (needed when the measure takes into account elements present
% in neither binary object). See further information below (including next
% to each measure).
%
% IMPORTANT: naming conventions for certain measures (e.g., the 5 Sokal and
% Sneath measures) are inconsistent across different researchers, different
% formulas for the same 'measure' exist in the literature, and different
% measures have similar names (e.g., Anderberg's vs. Anderberg's D). Thus,
% you should check that the formula used below corresponds to the
% particular measure that you wish to compute.
%
% Usage: out = overlap_similarity(mat1,mat2,type,mask)
%           mat1: 1st binary matrix
%           mat2: 2nd binary matrix
%           type: measure of (dis)similarity to be used
%           mask: binary mask indicating relevant matrix elements
%
%
% Further Information:
%
% All measures are symmetric (i.e., it does not matter which matrix is mat1
% vs. mat 2) except:
%                    AD, AMPLE, BUB1, BUB2, cole, diceasym1, diceasym2,
%                    digby, fleiss, forbes, GKlambda, GKtau, GK2, Ko2, LH,
%                    MP, Pcs, Pmsc, Pei1, Pei2, PHI, PH, Q0, RDeprob, SS4,
%                    SS5, tarantula, YQ, YQD, YY
%
% Computation of these measures takes into account (in some way) the
% elements present in neither binary object (i.e., d) (which may not be
% optimal if you want a straightforward measure of overlap):
%                    AD, AMPLE, baulieu, bc, Bshape, BUB1, BUB2, CK, cole,
%                    dennis, digby, disper, eyraud, faith, FD, fleiss,
%                    GKlambda, GKtau, GK1, GK2, GK3, GK4, GLS, goodall,
%                    gower, GW, hamann, HD, inprod, Kcam, Kpoai, LH,
%                    meanman, michael, MK, MP, pattern, Pcs, Pmsc, Pei1,
%                    Pei2, PHI, PH, Q0, RDeprob, Rpattern, RR, RT, scott,
%                    SM, Spattern, SS1, SS3, SS4, SS5, Stau, stiles,
%                    tarantula, tarwid, var, YQ, YQD, YY
%
% Positive monotomic relationship: bc, pattern
%                                  BSeuc, meanman, mirkin, var
%                                  BUB1, BUB2
%                                  DK, johnson
%                                  disper, MK, Stau
%                                  int, RR
%                                  hamann, inprod, SM
%                                  chord, hellinger
%                                  faith, tversky
%
% Negative monotomic relationship: BB with savage
%                                  BLWMN with dice
%                                  BSeuc, meanman, mirkin, and var with hamann, inprod, and SM
%                                  Bpattern with bc and pattern
%                                  Beuc with RT
%                                  steffensen with int and RR
%                                  YQ with YQD
%
% TAG:       MEASURE NAME:
% AMPLE      Analyzing Method Patterns to Locate Errors (Dallmeier et al, 2005) (similarity)
% AD         Anderberg's D (similarity)
% anderberg  Anderberg 1973 (similarity)
% baulieu    Baulieu 1989 (dissimilarity) (also called size difference)
% BB         Braun and Blanquet 1932 (similarity)
% bc         bc (dissimilarity)
% benini     Benini 1901 (similarity)
% Beuc       Binary euclidean distance (dissimilarity)
% BLWMN      Binary Lance and Williams nonmetric (dissimilarity) (also called Sokal and Sneath nonmetric or Bray and Curtis)
% Bpattern   Browsing pattern (similarity)
% BSeuc      Binary squared euclidean distance (dissimilarity) (also called Hamming, city block, Manhattan, or Filkov)
% Bshape     Binary shape (dissimilarity)
% BUB1       Baroni-Urbani and Buser 1976 1 (similarity)
% BUB2       Baroni-Urbani and Buser 1976 2 (similarity)
% chiY       Chi Square with correction of Yates
% chord      Chord (dissimilarity)
% CK         Cohen's kappa (similarity)
% cole       Cole 1949 (similarity)
% dennis     Dennis (similarity)
% dice       Dice (similarity) (also called Nei and Lei's genetic coefficient, Czekanowski, or Sorenson, or Bray)
% diceasym1  Dice asymmetric 1 (similarity)
% diceasym2  Dice asymmetric 2 (similarity)
% digby      Digby 1983 (similarity)
% disper     Dispersion (similarity)
% DK         Driver and Kroeber 1932 (similarity) (also called Kulczynski 1927 2)
% eyraud     Eyraud 1936 (similarity)
% fager      Fager (similarity)
% faith      Faith (similarity)
% FaMc       Fager and McGowan 1963 (similarity)
% FD         Forbes 1907's D (similarity)
% fleiss     Fleiss 1975 (similarity)
% forbes     Forbes 1925 (similarity)
% fossum     Fossum (similarity) (also called Jones and Curtis)
% gilbert    Gilbert's coefficient (similarity)
% gini       Gini 1912 index (similarity)
% GK1        Goodman and Kruskal 1954 1 (similarity)
% GK2        Goodman and Kruskal 1954 2 (similarity)
% GK3        Goodman and Kruskal 1954 3 (similarity)
% GK4        Goodman and Kruskal 1954 4 (similarity)
% GKlambda   Goodman and Kruskal's lambda (similarity)
% GKtau      Goodman and Kruskal's tau (similarity)
% goodall    Goodall 1967's angular transformation of simple matching coefficient (similarity) (also called Austin and Colwell)
% gower      Gower (similarity)
% GW         Gilbert and Wells 1966 (similarity)
% hamann     Hamann 1961 (similarity)
% HD         Hawkins and Dotson 1975 (similarity)
% hellinger  Hellinger (dissimilarity)
% inprod     Inner product (similarity)
% int        Intersection of two masks (similarity)
% jaccard    Jaccard 1908 (similarity) (also called similarity ratio or Tanimioto)
% johnson    Johnson 1967 (similarity) (also called McConnaughey 1964)
% Kcam       Kuhns 1965's coefficient of arithmetic means (similarity)
% Ko1        Koppen 1884 (similarity)
% Ko2        Koppen 1870 (similarity)
% Kpoai      Kuhns 1965's proportion of overlap above independence (similarity)
% kulczynski Kulczynski 1927 1 (similarity)
% meanman    Mean Manhattan (dissimilarity) (also called Canberra or Sneath total difference)
% michael    Michael 1920 (similarity)
% mirkin     Mirkin (dissimilarity)
% MK         Maron and Kuhns 1960 (similarity)
% modgini    Modified gini index (similarity)
% mountford  Mountford 1962 (similarity)
% MP         Maxwell and Pilliner 1968 (similarity)
% ochiai     Ochiai 1957 (similarity) (also called Driver and Kroeber or Otsuka)
% pattern    Pattern (dissimilarity)
% Pcs        Pearson 1905 chi-square (similarity)
% Pei1       Peirce 1884 1 (similarity)
% Pei2       Peirce 1884 2 (similarity)
% PH         Pearson and Heron 1913 (similarity)
% PHI        Fourfold point correlation (similarity) (also called Pearson and Heron 1913)
% Pmsc       Pearson 1905's coefficient of mean square contingency (similarity)
% Q0         Q0 (Batagelj and Bren 1995) (dissimilarity)
% Rcost      R cost
% RDeprob    Relative decrease of error probability (similarity)
% Rpattern   Retrieval pattern (similarity)
% RR         Russell and Rao 1940 (similarity)
% RT         Rogers and Tanimoto 1960 (similarity)
% savage     Savage (dissimilarity)
% Scost      S cost
% scott      Scott 1955 (similarity)
% simpson    Simpson 1943's ecological coexistence coefficient (similarity) (also called overlap)
% SM         Sokal and Michener 1958's simple matching (similarity) (also called Rand or Kendall)
% soergel    Soergel distance
% sorensen   Sorensen 1948 (similarity)
% sorgenfrei Sorgenfrei 1958 (similarity) (also called Fowlkes-Mallows)
% Spattern   Sneath pattern difference (dissimilarity)
% SS1        Sokal and Sneath 1963 1 (similarity)
% SS2        Sokal and Sneath 1963 2 (similarity)
% SS3        Sokal and Sneath 1963 3 (similarity)
% SS4        Sokal and Sneath 1963 4 (similarity) (also called Anderberg)
% SS5        Sokal and Sneath 1963 5 (similarity) (also called Ochiai 2)
% Stau       Stuart's tau (similarity)
% steffensen Steffensen 1934 (dissimilarity)
% stiles     Stiles (similarity)
% Tcost      T combined cost
% tarantula  Tarantula (Jones et al., 2002 & 2005) (similarity)
% tarwid     Tarwid 1960 (similarity)
% tversky    Tversky 1977's feature contrast model (similarity)
% Ucost      U cost
% unigram    Unigram subtuples
% US         Upholt 1977's S
% US         Upholt 1977's F
% var        Variance (dissimilarity)
% YQ         Yule 1911's Q coefficient of association (similarity)
% YQD        Yule's Q (Yule and Kendall, 1957) distance (dissimilarity)
% YY         Yule 1912's Y (or omega) coefficient of colligation (similarity)
%
%
% Author: Jeffrey M. Spielberg (jspielb2@gmail.com)
% Version: 05.06.16
%
% WARNING: This is a beta version. There no known bugs, but only limited
% testing has been perfomed. This software comes with no warranty (even the
% implied warranty of merchantability or fitness for a particular purpose).
% Therefore, USE AT YOUR OWN RISK!!!
%
% Copyleft 2014-2016. Software can be modified and redistributed, but
% modifed, redistributed versions must have the same rights

mat1 = double(mat1>0);
mat2 = double(mat2>0);

if nargin==2||isempty(type)
    type = 'dice';
    mask = ones(size(mat1));
elseif nargin<4
    mask = ones(size(mat1));
elseif nargin==4
    mask = double(mask>0);
end

mat1  = mat1.*mask;
mat2  = mat2.*mask;
nmat1 = not(mat1).*mask;
nmat2 = not(mat2).*mask;

a = sumn(mat1.*mat2);
b = sumn(nmat1.*mat2);
c = sumn(mat1.*nmat2);
d = sumn(nmat1.*nmat2);
tot = a+b+c+d;
q = (a+b)*(a+c)*(b+d)*(c+d);

switch type
    case 'AD'           % Anderberg's D (similarity) (measures the reduction in error probability when one item is used to predict the other) (range: 0:1)
        t1  = max(a,b)+max(c,d)+max(a,c)+max(b,d);
        t2  = max((a+c),(b+d))+max((a+d),(c+d));
        out = (t1-t2)/(2*tot);
    case 'AMPLE'        % Analyzing Method Patterns to Locate Errors (Dallmeier et al, 2005) (similarity) (undefined when a+b and/or c+d are 0)
        out = abs((a/(a+b))-(c/(c+d)));
    case 'anderberg'    % Anderberg 1973 (similarity)
        out = (8*a)/((8*a)+b+c);
    case 'baulieu'      % Baulieu 1989 (dissimilarity) (also called size difference) (range: 0:Inf)
        out = ((b-c)^2)/(tot^2);
    case 'BB'           % Braun and Blanquet 1932 (similarity) (range: 0:1)
        out = a/max((a+b),(a+c));
    case 'bc'           % bc (dissimilarity)
        out = (4*b*c)/(tot^2);
    case 'benini'       % Benini 1901 (similarity)
        out = (a-((a+b)*(a+c)))/(a+min(b,c)-((a+b)*(a+c)));
    case 'Beuc'         % Binary euclidean distance (dissimilarity) (range: 0:Inf)
        out = sqrt(b+c);
    case 'BLWMN'        % Binary Lance and Williams nonmetric (dissimilarity) (also called Sokal and Sneath nonmetric or Bray and Curtis) (range: 0:1)
        out = (b+c)/((2*a)+b+c);
    case 'Bpattern'     % Browsing pattern (similarity)
        out = a-(b*c);
    case 'BSeuc'        % Binary squared euclidean distance (dissimilarity) (also called Hamming, city block, Manhattan, or Filkov) (range: 0:Inf)
        out = b+c;
    case 'Bshape'       % Binary shape (dissimilarity) (range: no limits)
        out = ((tot*(b+c))-((b-c)^2))/(tot^2);
    case 'BUB1'         % Baroni-Urbani and Buser 1976 1 (similarity) (range: 0:1)
        out = (sqrt(a*d)+a)/(sqrt(a*d)+a+b+c);
    case 'BUB2'         % Baroni-Urbani and Buser 1976 2 (similarity)
        out = (sqrt(a*d)+a-b-c)/(sqrt(a*d)+a+b+c);
    case 'chiY'         % Chi Square with correction of Yates
        out = (tot*(abs((a*d)-(b*c))-(tot/2))^2)/q;
    case 'chord'        % Chord (dissimilarity)
        out = sqrt(2*(1-(a/sqrt((a+b)*(a+c)))));
    case 'CK'           % Cohen's kappa (similarity)
        out = (2*((a*d)-(b*c)))/(((a+b)*(b+d))+((a+c)*(c+d)));
    case 'cole'         % Cole 1949 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = ((a*d)-(b*c))/min(((a+b)*(a+c)),((b+d)*(c+d)));
    case 'dennis'       % Dennis (similarity)
        out = ((a*d)-(b*c))/sqrt(tot*(a+b)*(a+c));
    case 'dice'         % Dice (similarity) (also called Nei and Lei's genetic coefficient, Czekanowski, Sorenson, Bray, Upholt's F, Gower and Legendre's T, or percent positive agreement) (range: 0:1)
        out = (2*a)/((2*a)+b+c);
    case 'diceasym1'    % Dice asymmetric 1 (similarity)
        out = a/(a+c);
    case 'diceasym2'    % Dice asymmetric 2 (similarity)
        out = a/(a+b);
    case 'digby'        % Digby 1983 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (((a*d)^(3/4))-((b*c)^(3/4)))/(((a*d)^(3/4))+((b*c)^(3/4)));
    case 'disper'       % Dispersion (similarity) (range: -1:1)
        out = ((a*d)-(b*c))/(tot^2);
    case 'DK'           % Driver and Kroeber 1932 (similarity) (also called Kulczynski 1927 2) (measures the conditional probability that both items are positive) (range: 0:1)
        out = (a/2)*((1/(a+b))+(1/(a+c)));
    case 'eyraud'       % Eyraud 1936 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (a-((a+b)*(a+c)))/q;
        %out = ((tot^2)*((tot*a)-((a+b)*(a+c))))/q; % Alternative formula
    case 'fager'        % Fager (similarity)
        out = (a/sqrt((a+b)*(a+c)))-(1/(2*sqrt(min((a+b),(a+c)))));
        %out = (a/(((a+b)*(a+c))^2))-(max(b,c)/2); % Alternative formula
    case 'faith'        % Faith (similarity)
        out = (a+(0.5*d))/tot;
    case 'FaMc'         % Fager and McGowan 1963 (similarity)
        out = (a/sqrt((a+b)*(a+c)))-((a+max(b,c))/2);
    case 'FD'           % Forbes 1907's D (similarity) (also called Kocher and Wong)
        out = (a*tot)/((a+b)*(a+c));
    case 'fleiss'       % Fleiss 1975 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (((a*d)-(b*c))*(((a+b)*(b+d))+((a+c)*(c+d))))/(2*q);
    case 'forbes'       % Forbes 1925 (similarity) (also called Loevinger's H) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = ((tot*a)-((a+b)*(a+c)))/((tot*min((a+b),(a+c)))-((a+b)*(a+c)));
        %out = ((tot*a)-((a+b)*(a+c)))/((tot*min(b,c))-((a+b)*(a+c))); % Alternative formula
    case 'fossum'       % Fossum (similarity) (also called Jones and Curtis)
        out = (tot*((a-0.5)^2))/((a+b)*(a+c));
    case 'gilbert'      % Gilbert's coefficient (similarity) (undefined under certain circumstances)
        out = (a-((a+b)*(a+c)))/(a+b+c-((a+b)*(a+c)));
    case 'gini'         % Gini 1912 index (similarity) (undefined under certain circumstances)
        out = (a-((a+b)*(a+c)))/sqrt((1-((a+b)^2))*(1-((a+c)^2)));
    case 'GKlambda'     % Goodman and Kruskal's lambda (similarity) (measures the proportional reduction in error using one item to predict another) (range: 0:1)
        t1  = max(a,b)+max(c,d)+max(a,c)+max(b,d);
        t2  = max((a+c),(b+d))+max((a+d),(c+d));
        out = (t1-t2)/((2*tot)-t2);
    case 'GKtau'        % Goodman and Kruskal's tau (similarity) (undefined when a+b and/or c+d are 0)
        out = (((((a-((a+b)*(a+c)))^2)+((b-((a+b)*(b+d)))^2))/(a+b))/(1-((a+c)^2)-((b+d)^2)))+(((((c-((a+c)*(c+d)))^2)+((d-((b+d)*(c+d)))^2))/(c+d))/(1-((a+c)^2)-((b+d)^2)));
    case 'GK1'          % Goodman and Kruskal 1 1954 (similarity)
        out = ((2*min(a,d))-b-c)/((2*min(a,d))+b+c);
    case 'GK2'          % Goodman and Kruskal 2 1954 (similarity)
        out = (max(a,c)+max(b,d)-max((a+b),(c+d)))/(1-max((a+b),(c+d)));
    case 'GK3'          % Goodman and Kruskal 3 1954 (similarity)
        out = (a+d-max(a,d)-((b+c)/2))/(1-max(a,d)-((b+c)/2));
    case 'GK4'          % Goodman and Kruskal 4 1954 (similarity)
        out = ((max(a,b)+max(c,d)+max(a,c)+max(b,d))/(2-max((a+c),(b+d))-max((a+b),(c+d))))-((max((a+c),(b+d))+max((a+b),(c+d)))/(2-max((a+c),(b+d))-max((a+b),(c+d))));
    case 'goodall'      % Goodall 1967's angular transformation of simple matching coefficient (similarity) (also called Austin and Colwell)
        out = asin(sqrt((a+d)/tot))/(50*pi);
    case 'gower'        % Gower (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (a+d)/sqrt(q);
    case 'GW'           % Gilbert and Wells 1966 (similarity) (undefined when a+b and/or a+c are 0)
        out = log((a*tot)/((a+b)*(a+c)));
    case 'hamann'       % Hamann 1961 (similarity) (range: -1:1)
        out = ((a+d)-(b+c))/tot;
    case 'HD'           % Hawkins and Dotson 1975 (similarity)
        out = 0.5*((a/(a+b+c))+(d/(b+c+d)));
    case 'hellinger'    % Hellinger (dissimilarity)
        out = 2*sqrt(1-(a/sqrt((a+b)*(a+c))));
    case 'inprod'       % Inner product (similarity)
        out = a+d;
    case 'int'          % Intersection of two masks (similarity)
        out = a;
    case 'jaccard'      % Jaccard 1908 (similarity) (also called similarity ratio or Tanimioto) (range: 0:1)
        out = a/(a+b+c);
    case 'johnson'      % Johnson 1967 (similarity) (also called McConnaughey 1964)
        out = (a/(a+b))+(a/(a+c));
    case 'Kcam'         % Kuhns 1965's coefficient of arithmetic means (similarity)
        out = (2*((a*d)-(b*c)))/(tot*((2*a)+b+c));
    case 'Ko1'          % Koppen 1884 (similarity)
        out = a+((b+c)/2);
    case 'Ko2'          % Koppen 1870 (similarity) (undefined when a+b and/or 1-a-b are 0)
        out = (((a+b)*(1-a-b))-c)/((a+b)*(1-a-b));
    case 'Kpoai'        % Kuhns 1965's proportion of overlap above independence (similarity) (undefined when a+c and/or a+c are 0)
        out = ((a*d)-(b*c))/(tot*(a/((a+b)*(a+c)))*((2*a)+b+c-(((a+b)*(a+c))/tot)));
    case 'kulczynski'   % Kulczynski 1927 1 (similarity) (range: 0:Inf)
        out = a/(b+c);
    case 'meanman'      % Mean Manhattan (dissimilarity) (also called Canberra or Sneath total difference)
        out = (b+c)/tot;
    case 'michael'      % Michael 1920 (similarity) (range: 0:1)
        out = (4*((a*d)-(b*c)))/(((a+d)^2)+((b+c)^2));
    case 'mirkin'       % Mirkin (dissimilarity)
        out = 2*(b+c);
    case 'MK'           % Maron and Kuhns 1960 (similarity)
        out = ((a*d)-(b*c))/tot;
    case 'modgini'      % Modified gini index (similarity)
        out = (a-((a+b)*(a+c)))/(1-(abs(b-c)/2)-((a+b)*(a+c)));
    case 'mountford'    % Mountford 1962 (similarity)
        out = a/((0.5*((a*b)+(a*c)))+(b*c));
    case 'MP'           % Maxwell and Pilliner 1968 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (2*((a*d)-(b*c)))/q;
    case 'ochiai'       % Ochiai 1957 (similarity) (also called Driver and Kroeber or Otsuka) (binary form of cosine similarity) (range: 0:1)
        out = a/sqrt((a+b)*(a+c));
    case 'pattern'      % Pattern (dissimilarity) (range: 0:1)
        out = (b*c)/(tot^2);
    case 'Pcs'          % Pearson 1905 chi-square (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (tot*(((a*d)-(b*c))^2))/q;
    case 'Pmsc'         % Pearson 1905's coefficient of mean square contingency (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        ch2 = (tot*(((a*d)-(b*c))^2))/q;
        out = sqrt(ch2/(tot+ch2));
    case 'Pei1'         % Peirce 1884 1 (similarity) (undefined when a+c and/or b+d are 0)
        out = ((a*b)-(b*c))/((a+c)*(b+d));
    case 'Pei2'         % Peirce 1884 2 (similarity) (undefined when a+c and/or b+d are 0)
        out = ((a*b)+(b*c))/((a*b)+(2*b*c)+(c*d));
    case 'PHI'          % Fourfold point correlation (similarity) (also called Pearson and Heron 1913) (binary form of the Pearson product-moment correlation) range: 0:1) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = ((a*d)-(b*c))/sqrt(q);
    case 'PH'           % Pearson and Heron 1913 (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = cos((180*sqrt(b*c))/(sqrt(a*d)+sqrt(b*c)));
    case 'Q0'           % Q0 (Batagelj and Bren 1995) (dissimilarity) (range: 0:Inf) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (b*c)/(a*d);
    case 'Rcost'        % R cost
        out = log(1+(a/(a+b)))*log(1+(a/(a+c)));
    case 'RDeprob'      % Relative decrease of error probability (similarity)
        out = (max(a,b)+max(c,d)-max((a+c),(b+d)))/(1-max((a+c),(b+d)));
    case 'Rpattern'     % Retrieval pattern (similarity)
        out = a*d;
    case 'RR'           % Russell and Rao 1940 (similarity) (range: 0:1)
        out = a/tot;
    case 'RT'           % Rogers and Tanimoto 1960 (similarity) (binary dot product) (range: 0:1)
        out = (a+d)/(a+d+(2*(b+c)));
    case 'savage'       % Savage (dissimilarity)
        out = 1-(a/(a+max(b,c)));
    case 'Scost'        % S cost
        out = log(1+min(b,c)/(a+1))^-.5;
    case 'scott'        % Scott 1955 (similarity)
        out = ((4*((a*d)-(b*c)))-((b-c)^2))/(((2*a)+b+c)+(b+c+(2*d)));
    case 'simpson'      % Simpson 1943's ecological coexistence coefficient (similarity) (also called overlap) (range: 0:1)
        out = a/min((a+b),(a+c));
    case 'SM'           % Sokal and Michener 1958's simple matching (similarity) (also called Rand or Kendall) (range: 0:1)
        out = (a+d)/tot;
    case 'soergel'      % Soergel distance
        out = (b+c)/(b+c+d);
    case 'sorensen'     % Sorensen 1948 (similarity)
        out = (4*a)/((4*a)+b+c);
    case 'sorgenfrei'   % Sorgenfrei 1958 (similarity) (also called Fowlkes-Mallows)
        out = (a^2)/((a+b)*(a+c));
    case 'Spattern'     % Sneath pattern difference (dissimilarity)
        out = (2*sqrt(b*c))/tot;
    case 'SS1'          % Sokal and Sneath 1963 1 (similarity) (also called Gower and Legendre's S)
        out = (2*(a+d))/((2*(a+d))+b+c);
    case 'SS2'          % Sokal and Sneath 1963 2 (similarity)
        out = a/(a+(2*(b+c)));
    case 'SS3'          % Sokal and Sneath 1963 3 (similarity) (range: 0:Inf)
        out = (a+d)/(b+c);
    case 'SS4'          % Sokal and Sneath 1963 4 (similarity) (also called Anderberg) (measures the conditional probability that both items are in the same state [present or absent]) (range: 0:1) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = ((a/(a+b))+(a/(a+c))+(d/(b+d))+(d/(c+d)))/4;
    case 'SS5'          % Sokal and Sneath 1963 5 (similarity) (also called Ochiai 2) (range: 0:1) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (a*d)/sqrt(q);
    case 'Stau'         % Stuart's tau (similarity)
        out = 2*((a*d)-(b*c));
    case 'steffensen'   % Steffensen 1934 (dissimilarity)
        out = (a-((a+b)*(a+c)))/2;
    case 'stiles'       % Stiles (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0 and other circumstances)
        out = log10((tot*((abs((a*d)-(b*c))-(tot/2))^2))/q);
    case 'tarantula'    % Tarantula (Jones et al., 2002 & 2005) (similarity) (undefined when a+b and/or c+d are 0)
        out = (a/(a+b))/((a/(a+b))+(c/(c+d)));
    case 'tarwid'       % Tarwid 1960 (similarity)
        out = ((tot*a)-((a+b)*(a+c)))/((tot*a)+((a+b)*(a+c)));
    case 'Tcost'        % T combined cost
        R = log(1+(a/(a+b)))*log(1+(a/(a+c)));
        S = log(1+min(b,c)/(a+1))^-.5;
        U = log(1+((min(b,c)+a)/(max(b,c)+a)));
        out = sqrt(U*S*R);
    case 'tversky'      % Tversky 1977's feature contrast model (similarity)
        out = a-b-c;
    case 'Ucost'        % U cost
        out = log(1+((min(b,c)+a)/(max(b,c)+a)));
    case 'unigram'      % Unigram subtuples
        out = log((a*d)/(b*c))-(3.29*sqrt((1/a)+(1/b)+(1/c)+(1/d)));
    case 'UF'           % Upholt 1977's F (also called Gower and Legendre's T)
        out = (2*a)/((2*a)+b+c);
    case 'US'           % Upholt's S 1977
        F = (2*a)/((2*a)+b+c);
        out = (0.5*(-F+sqrt((F^2)+(8*F))))^(1/tot);
    case 'var'          % Variance (dissimilarity) (range: 0:Inf)
        out = (b+c)/(4*tot);
    case 'YQ'           % Yule 1911's Q coefficient of association (similarity) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = ((a*d)-(b*c))/((a*d)+(b*c));
    case 'YQD'          % Yule's Q distance (dissimilarity) (range: -1:1) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (b*c)/((a*d)+(b*c));
    case 'YY'           % Yule 1912's Y (or omega) coefficient of colligation (similarity) (range: -1:1) (undefined when a+b, b+d, a+c, and/or c+d are 0)
        out = (sqrt(a*d)-sqrt(b*c))/(sqrt(a*d)+sqrt(b*c));
end

function out = sumn(in)
out = sum(in(:));


function [ r, info ] = r8pp_fa ( n, a )

%*****************************************************************************80
%
%% R8PP_FA factors a R8PP matrix.
%
%  Discussion:
%
%    The R8PP storage format is appropriate for a symmetric positive
%    definite matrix.  Only the upper triangle of the matrix is stored,
%    by successive partial columns, in an array of length (N*(N+1))/2,
%    which contains (A11,A12,A22,A13,A23,A33,A14,...,ANN)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 February 2004
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Dongarra, Moler, Bunch and Stewart,
%    LINPACK User's Guide,
%    SIAM, (Society for Industrial and Applied Mathematics),
%    3600 University City Science Center,
%    Philadelphia, PA, 19104-2688.
%    ISBN 0-89871-172-X
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Input, real A((N*(N+1))/2), a R8PP matrix.
%
%    Output, real R((N*(N+1))/2), an upper triangular matrix R, stored
%    in packed form, so that A = R'*R.
%
%    Output, integer INFO, error flag.
%    0, for normal return.
%    K, if the leading minor of order K is not positive definite.
%
  info = 0;

  r(1:(n*(n+1))/2) = a(1:(n*(n+1))/2);

  jj = 0;

  for j = 1 : n

    s = 0.0E+00;
    kj = jj;
    kk = 0;

    for k = 1 : j-1

      kj = kj + 1;
      t = r(kj);
      for i = 1 : k-1
        t = t - r(kk+i) * r(jj+i);
      end
      kk = kk + k;
      t = t / r(kk);
      r(kj) = t;
      s = s + t * t;

    end

    jj = jj + j;
    s = r(jj) - s;

    if ( s <= 0.0E+00 )
      info = j;
      return;
    end

    r(jj) = sqrt ( s );

  end

  return
end


function otr = transform(itr,tmx)

%
% FUNCTION
% otr = transform(itr,tmx)
%
% DESCRIPTION
% transform 3D-tensor (Euclidean or Cartesion tensor) of any order (>0) to another coordinate system
%
% PARAMETERS
% otr = output tensor, after transformation; has the same dimensions as the input tensor
% itr = input tensor, before transformation; should be a 3-element vector, a 3x3 matrix, or a 3x3x3x... multidimensional array, each dimension containing 3 elements
% tmx = transformation matrix, 3x3 matrix that contains the direction cosines between the old and the new coordinate system
%

ne = numel(itr);                % number of tensor elements
nd = ndims(itr);                % number of tensor dimensions, i.e. order of tensor
if (ne==3), nd = 1; end         % order of tensor is 1 in case of a 3x1 or 1x3 vector

otr = itr;                      % create output tensor
otr(:) = 0;                     % fill output tensor with zeros; this way a symbolic tensor remains symbolic

iie = zeros(nd,1);              % initialise vector with indices of input tensor element
ioe = zeros(nd,1);              % initialise vector with indices of output tensor element
cne = cumprod(3*ones(nd,1))/3;  % vector with cumulative number of elements for each dimension (divided by three)

for oe = 1:ne,                                 % loop over all output elements
   ioe = mod(floor((oe-1)./cne),3)+1;          % calculate indices of current output tensor element
   for ie = 1:ne,                              % loop over all input elements
      pmx = 1;                                 % initialise product of transformation matrices
      iie = mod(floor((ie-1)./cne),3)+1;       % calculate indices of current input tensor element
      for id = 1:nd,                           % loop over all dimensions
         pmx = pmx * tmx( ioe(id), iie(id) );  % create product of transformation matrices
      end
      otr(oe) = otr(oe) + pmx * itr(ie);       % add product of transformation matrices and input tensor element to output tensor element
   end
end


function L = gaussianNoiseExpectationLogLikelihood(noise, mu, varsigma, y)

% GAUSSIANNOISEEXPECTATIONLOGLIKELIHOOD Likelihood of the data under the GAUSSIAN noise model.
% FORMAT
% DESC returns the likelihoods for data points under the  Gaussian noise model.
% ARG noise : the noise structure for which the likelihood is required.
% ARG mu : input mean locations for the likelihood.
% ARG varSigma : input variance locations for the likelihood.
% ARG y : target locations for the likelihood.
%
% SEEALSO : gaussianNoiseParamInit, gaussianNoiseLogLikelihood, noiseLikelihood
%
% COPYRIGHT : Neil D. Lawrence, 2004, 2005

N = size(y, 1);
D = size(y, 2);
varsigma = varsigma + noise.sigma2;
for i = 1:D
  mu(:, i) = mu(:, i) + noise.bias(i);
end
arg = (mu - y)./sqrt(varsigma);
L = (2*pi*varsigma).^(-1/2).*exp( - .5*arg.*arg);


function [ mD ] = CalcDistanceMatrixCRows( mX )
% ----------------------------------------------------------------------------------------------- %
% [ mD ] = CalcDistanceMatrixARows( mX )
%   Calculates the distance matrix for the input data. The distance matrix
%   is a symmetric matrix where 'mD(ii, jj) = dist(mX(ii, :), mX(jj, :));'.
%   This function uses the squared Euclidean Distance for the distance
%   metric.
% Input:
%   - mX            -   Data Matrix.
%                       Each data sample is a row of the matrix.
%                       Structure: Matrix (numVars x varDim).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
% Output:
%   - mD            -   Distance Matrix.
%                       A symmetric matrix where 'mD(ii, jj) = dist(mX(ii,
%                       :), mX(jj, :));'.
%                       Structure: Matrix (numVars x numVars).
%                       Type: 'Single' / 'Double'.
%                       Range: [0, inf).
% References
%   1.  A
% Remarks:
%   1.  B
% TODO:
%   1.  C
% Release Notes:
%   -   1.0.000     01/01/2021  Royi Avital	RoyiAvital@yahoo.com
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

FALSE   = 0;
TRUE    = 1;

OFF     = 0;
ON      = 1;

mG = mX * mX.';
vG = diag(mG);

mD = vG.' + vG - (2 * mG);

end


%NS1
% Numerical solution of 2-D instationary Navier-Stokes equations.
% Rectangular domain; nonuniform Cartesian staggered grid.
% Time discretization with omega-scheme.
% Pressure-correction method.
% Central or upwind scheme for inertia terms.

% Copyright 2001 P. Wesseling
% This program and its subprograms may be freely used, modified and distributed
% under the GNU General Public License: http://www.gnu.org/copyleft/gpl.html

% Theory is given in Chapter 6 of
% 	Principles of Computational Fluid Dynamics, by P. Wesseling
% 	Springer-Verlag, Berlin etc., 2001. ISBN 3-540-67853-0
% See http://dutita0.twi.tudelft.nl/nw/users/wesseling/

% Theory is also given in Chapter 5 of
%	Computational Fluid Dynamics
%	Lecture Notes by P. Wesseling
%	Department of Applied Mathematical Analysis, ITS, TU Delft
% See http://ta.twi.tudelft.nl/nw/users/wesseling/

% This program generates Figures  and  in the Lecture Notes.

% Functions called: startup,problem_specification, grid_generation, draw_grid,
%		    viscous_matrix, grad_and_div, initial_condition,
%		    right_hand_side, inertia_matrix, errornorm, isobarplot,
%		    streamlineplot, velocity_profile, relchangeplot

startup, format compact, clear all
time0 = clock;
global geval n u0 v0 J K yu yv yseglen alpha
% ........................................Input..............................
geval = 3;	% Enter 1 for horizontal Poiseuille flow to the right
		%  or 2 for vertical Poiseuille flow
		%  or 3 for backward facing step
		%  or 4 for driven cavity
		%  or 5 for uniform flow under angle alpha without segmentation
		%  or 6 for uniform flow under angle alpha with segmentation
		%  or 7 for horizontal Poiseuille flow to the left

problem_specification	% Prepare file problem_specification.m as part of input
% User must prepare files ubd.m, vbd.m, pbd.m to specify boundary values

% .................................End of input......................

grid_generation
draw_grid
h = waitbar(0,'Computing...');
viscous_matrix		% Generate viscous matrices Bu, Bv and Masku, Maskv
grad_and_div		% Generate pressure gradient matrices Pu, Pv and
			%  divergence matrices Du, Dv
initial_condition	% Generate initial u0, v0, p0
tic
[Lp,Up] = lu([Du Dv]*[Pu;Pv]);	% LU decomposition of pressure correction matrix
tijd = toc; disp(['Pres. corr. matrix LU time = ',num2str(tijd)])
if max(abs(sum(([Du Dv]*[Pu;Pv])'))) < 10*eps
  % Do consistency check
end

nstep = floor(tend/dt);	% Number of time steps
%nstep = 2;
relchange = zeros(nstep,1);	% For plotting relative change per time step
t = 0; n = 0;
right_hand_side		% Generate right-hand sides ru, rv; has to be moved
			% inside time loop if boundary conditions time-dependent
u1 = u0; v1 = v0;
for n = 1:nstep		% Time-stepping with omega scheme
  t = n*dt;
  u0 = u1; v0 = v1;
%  right_hand_side	% Generate right-hand sides ru, rv; can be moved outside
			% time loop if boundary conditions not time-dependent

  % Navier-Stokes, predictor:
  inertia_matrix	% Generate inertia matrices and adapt right-hand sides
  rum = (ru + rum)'; rvm = (rv + rvm)'; rum = rum(:); rvm = rvm(:);
  if n == 1, tic, end
  Cu = dt*(Bu + Cu); Cv = dt*(Bv + Cv);
  u1 = (speye(length(u0)) + omega*Cu)\...
        (Masku*u0 + dt*(rum - Pu*p0) - (1-omega)*Cu*u0);
  v1 = (speye(length(v0)) + omega*Cv)\...
        (Maskv*v0 + dt*(rvm - Pv*p0) - (1-omega)*Cv*v0);

  % End of Navier-Stokes predictor

  % Stokes:
  %rum = ru'; rum = rum(:); rvm = rv'; rvm = rvm(:);
  %if n == 1, tic, end
  %u1 = Bu\(dt*(rum - Pu*p0) + Masku*u0);
  %v1 = Bv\(dt*(rvm - Pv*p0) + Maskv*v0);
  % End of Stokes

  if n == 1, tijd = toc; disp(['velocity solve time = ',num2str(tijd)]), tic,end
  dp = Up\(Lp\(Du*u1 + Dv*v1));	p0 = p0 + dp/dt;
  u1 = u1 - Pu*dp;	v1 = v1 - Pv*dp;
  if n == 1, tijd = toc; disp(['press. corr. time = ',num2str(tijd)]),end
  mm = max([norm(u1,inf),norm(v1,inf)]); relchange(n) = max([norm(u1-u0,inf)...
  /mm,norm(v1-v0,inf)/mm, norm(dp,inf)/(norm(p0,inf) + 0.5*mm^2)]);
  waitbar(n/nstep)
end

disp(['Relative change = ',num2str(relchange(end))])
divergence = norm(Du*u1 + Dv*v1,inf);
if (geval==1)|(geval==2)
  errornorm		% Maximum norm of error in outflow profile if exact
			% solution is available
end
close(h)
tic
isobarplot		% Plot of isobars and velocity vectors
streamlineplot 		% Plot of streamlines and velocity vectors
velocity_profile	% Plot of velocity profiles
relchangeplot		% Plot of relative change per time step
tijd = toc; disp(['Plotting time = ',num2str(tijd)])
disp(['Total time = ',num2str(etime(clock,time0))])


function [H] = rotate(D);

% ROTATE returns the homogenous coordinate transformation matrix
% corresponding to a rotation around the x, y and z-axis. The direction of
% the rotation is according to the right-hand rule.
%
% Use as
%   [H] = rotate(R)
% where
%   R		[rx, ry, rz] in degrees
%   H		corresponding homogenous transformation matrix
%
% Note that the order in which the rotations are performs matters. The
% rotation is first done around the z-axis, then the y-axis and finally the
% x-axis.

% Copyright (C) 2000-2005, Robert Oostenveld
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

% $Log: rotate.m,v $
% Revision 1.1  2009/01/30 04:02:11  arno
% *** empty log message ***
%
% Revision 1.5  2006/09/12 13:35:28  roboos
% convert input rotation from degrees (according to documentation) into radians (needed for computations)
%
% Revision 1.4  2005/08/15 08:15:33  roboos
% reimplemented the rotate function, which contained an error (the error is in the AIR technical reference)
% changed all functions to be dependent on the rotate, translate and scale function
% all functions now behave consistenly, which also means that they are not compleetly backward compatible w.r.t. the order of the rotations
%
% Revision 1.3  2004/05/19 09:57:07  roberto
% added GPL copyright statement, added CVS log item
%

% convert degrees to radians
R = D*pi/180;

% get the individual angles (in radians)
rx = R(1);
ry = R(2);
rz = R(3);

% precompute the sin/cos values of the angles
cX = cos(rx);
cY = cos(ry);
cZ = cos(rz);
sX = sin(rx);
sY = sin(ry);
sZ = sin(rz);

% according to Roger Woods' http://bishopw.loni.ucla.edu/AIR5/homogenous.html
% it should be this, but I cannot reproduce his rotation matrix
% H = eye(4,4);
% H(1,1) = cZ*cY + sZ*sX*sY;
% H(1,2) = sZ*cY - cZ*sX*sY;
% H(1,3) =            cX*sY;
% H(2,1) = -sZ*cX;
% H(2,2) =  cZ*cX;
% H(2,3) =     sX;
% H(3,1) =  sZ*sX*cY - cZ*sY;
% H(3,2) = -cZ*sX*cY - sZ*sY;
% H(3,3) =             cX*cY;

% instead, the following rotation matrix does work according my
% expectations. It rotates according to the right hand rule and first
% rotates around z, then y and then x axis
H = [
           cZ*cY,          -sZ*cY,              sY,               0
  cZ*sY*sX+sZ*cX, -sZ*sY*sX+cZ*cX,          -cY*sX,               0
 -cZ*sY*cX+sZ*sX,  sZ*sY*cX+cZ*sX,           cY*cX,               0
               0,               0,               0,               1
];

if 0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The following code can be used to construct the combined rotation matrix
% for either xyz or zyx ordering (using the Matlab symbolic math toolbox)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  syms sX sY sZ cX cY cZ
  % this is for only rotating around x
  Rx = [
    1   0    0   0
    0   cX  -sX  0
    0   sX   cX  0
    0   0    0   1
    ];
  % this is for only rotating around y
  Ry = [
    cY  0   sY  0
    0   1   0   0
    -sY  0   cY  0
    0   0   0   1
    ];
  % this is for only rotating around z
  Rz = [
    cZ -sZ  0   0
    sZ  cZ  0   0
    0   0   1   0
    0   0   0   1
    ];
  % combine them
  Rzyx = Rz * Ry * Rx  % rotate around x, y, then z
  Rxyz = Rx * Ry * Rz  % rotate around z, y, then x
end


function [L,S,obj,err,iter] = igc(A,C,lambda,opts)

% Reference: Chen, Yudong, Sujay Sanghavi, and Huan Xu. Improved graph clustering.
% IEEE Transactions on Information Theory 60.10 (2014): 6440-6455.
%
% min_{L,S} ||L||_*+lambda*||C \cdot S||_1, s.t. A=L+S, 0<=L<=1.
%
% ---------------------------------------------
% Input:
%       A       -    d*n matrix
%       C       -    d*n matrix
%       lambda  -    >0, parameter
%       opts    -    Structure value in Matlab. The fields are
%           opts.tol        -   termination tolerance
%           opts.max_iter   -   maximum number of iterations
%           opts.mu         -   stepsize for dual variable updating in ADMM
%           opts.max_mu     -   maximum stepsize
%           opts.rho        -   rho>=1, ratio used to increase mu
%           opts.DEBUG      -   0 or 1
%
% Output:
%       L       -    d*n matrix
%       S       -    d*n matrix
%       obj     -    objective function value
%       err     -    residual
%       iter    -    number of iterations
%
% version 1.0 - 19/06/2016
%
% Written by Canyi Lu (canyilu@gmail.com)
%

tol = 1e-8;
max_iter = 500;
rho = 1.1;
mu = 1e-4;
max_mu = 1e10;
DEBUG = 0;

if ~exist('opts', 'var')
    opts = [];
end
if isfield(opts, 'tol');         tol = opts.tol;              end
if isfield(opts, 'max_iter');    max_iter = opts.max_iter;    end
if isfield(opts, 'rho');         rho = opts.rho;              end
if isfield(opts, 'mu');          mu = opts.mu;                end
if isfield(opts, 'max_mu');      max_mu = opts.max_mu;        end
if isfield(opts, 'DEBUG');       DEBUG = opts.DEBUG;          end

C = abs(C);
[d,n] = size(A);

L = zeros(d,n);
S = L;
Z = L;
Y1 = L;
Y2 = L;

iter = 0;
for iter = 1 : max_iter
    Lk = L;
    Sk = S;
    Zk = Z;
    % first super block {L,S}
    [L,nuclearnormL] = prox_nuclear(Z-Y2/mu,1/mu);
    S = prox_l1(-Z+A-Y1/mu,C*(lambda/mu));

    % second super block {Z}
    Z = project_box((-S+A+L+(Y2-Y1)/mu)/2,0,1);

    dY1 = Z+S-A;
    dY2 = L-Z;
    chgL = max(max(abs(Lk-L)));
    chgS = max(max(abs(Sk-S)));
    chgZ = max(max(abs(Zk-Z)));
    chg = max([chgL chgS chgZ max(abs(dY1(:))) max(abs(dY2(:)))]);
    if DEBUG
        if iter == 1 || mod(iter, 10) == 0
            obj = nuclearnormL+lambda*sum(sum(C.*abs(S)));
            err = sqrt(norm(dY1,'fro')^2+norm(dY2,'fro')^2);
            disp(['iter ' num2str(iter) ', mu=' num2str(mu) ...
                    ', obj=' num2str(obj) ', err=' num2str(err)]);
        end
    end

    if chg < tol
        break;
    end
    Y1 = Y1 + mu*dY1;
    Y2 = Y2 + mu*dY2;
    mu = min(rho*mu,max_mu);
end
obj = nuclearnormL+lambda*sum(sum(C.*abs(S)));
err = sqrt(norm(dY1,'fro')^2+norm(dY2,'fro')^2);


function triangulate ( prefix, animate )

%*****************************************************************************80
%
%% TRIANGULATE triangulates a polygon using the ear slicing algorithm.
%
%  Discussion:
%
%    The polygon is described by a file which lists the coordinates of the
%    vertices in consecutive order during a counterclockwise traversal.
%
%    Note that no two successive vertices can be equal, nor can the first
%    and last vertices be equal.
%
%    Information about the polygon is stored as a structure we will call
%    a "vertex array".
%
%    There is one entry in the array for each of the N vertices in the
%    polygon.  The I-th entry is a structure with the following fields:
%
%      vertex(i).index  the index of the node.
%      vertex(i).next   the index of the next node.
%      vertex(i).prev   the index of the previous node.
%      vertex(i).x      the X coordinate.
%      vertex(i).y      the Y coordinate.
%      vertex(i).ear    1 if the vertex represents an "ear" that can
%                       be sliced off.
%
%  Usage:
%
%    triangulate ( 'prefix', 'animate' )
%
%    where
%
%    * 'prefix' is the filename prefix
%    * 'animate' is 'y' if you want to see an animation of the triangulation.
%
%    reads
%
%    * 'prefix'_nodes.txt, the node coordinate file,
%
%    creates
%
%    * 'prefix'_diagonals.txt, the internal diagonals file.
%    * 'prefix'_elements.txt, the triangle file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2013
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, string PREFIX, the filename prefix.
%
%    Input, string ANIMATE, is 'y' if the user wants to see the triangulation
%    process animated.
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TRIANGULATE\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Read a file listing the coordinates of the vertices\n' );
  fprintf ( 1, '  of a polygon, and determine a triangulation.\n' );
%
%  If the user did not supply the filename prefix, request it.
%
  if ( nargin < 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATE:\n' );
    prefix = input ( '  Enter the filename prefix (in ''quotes''!).\n' );
  end
%
%  If the user did not supply the animation option, assume it is NO.
%
  if ( nargin < 2 )
    animate = 'n';
  end
%
%  Create filenames.
%
  node_filename     = strcat ( prefix, '_nodes.txt' );
  diagonal_filename = strcat ( prefix, '_diagonals.txt' );
  triangle_filename = strcat ( prefix, '_elements.txt' );
%
%  Read the node coordinates.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Processing the vertex coordinate file "%s".\n', node_filename )
  direction = +1;
  vertex = read_vertices ( node_filename, direction );

  vertex = ear_init ( vertex );

  area = area_poly2 ( vertex );
%
%  If area is zero, refuse to go on.
%
  if ( area == 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'TRIANGULATE - Fatal area!\n' );
    fprintf ( 1, '  The area is computed to be exactly zero.\n' );
    return
  end
%
%  If area is NEGATIVE, reverse the ordering.
%
  if ( area < 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Polygon area is negative!\n' );
    fprintf ( 1, '  Will try reversing vertex ordering.\n' );
    direction = -1;
    vertex = read_vertices ( node_filename, direction );
    vertex = ear_init ( vertex );
    area = area_poly2 ( vertex );
  end

  n = length ( vertex );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of vertices is %d\n', n );

  print_vertices ( vertex );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Area of polygon is %g\n', area );
%
%  Refuse to triangulate a region in which two successive vertices are equal.
%
  for i = 1 : n
    j = vertex(i).next;
    if ( vertex(i).x == vertex(j).x && vertex(i).y == vertex(j).y )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'TRIANGULATE - Fatal error!\n' );
      fprintf ( 1, '  Two neighbor vertices are equal.\n' );
      fprintf ( 1, '  Vertex(%d) = Vertex(%d)\n', i, j );
      error ( 'TRIANGULATE - Fatal error!' );
    end
  end
%
%  Determine a reasonable scale for the plot.
%
  xmin = vertex(1).x;
  xmax = vertex(1).x;
  ymin = vertex(1).y;
  ymax = vertex(1).y;
  for i = 2 : n
    xmin = min ( xmin, vertex(i).x );
    xmax = max ( xmax, vertex(i).x );
    ymin = min ( ymin, vertex(i).y );
    ymax = max ( ymax, vertex(i).y );
  end

  dx = 0.0125 * max ( xmax - xmin, ymax - ymin );
%
%  Draw the (non-triangulated) polygon.
%
%  You might think a single PLOT command would suffice to display
%  the vertices.  However, the proper way of extracting a vector of
%  values from a structure eludes me.
%
  figure ( 1 )

  clf

  grid on

  hold on
%
%  Make the plot a little bigger than the data.
%
  plot ( xmin - 2 * dx, ymin - 2 * dx, 'w.' );
  plot ( xmax + 2 * dx, ymin + 2 * dx, 'w.' );

  for i = 1 : n
    plot ( vertex(i).x, vertex(i).y, 'k.', 'MarkerSize', 25 )
  end

  for i = 1 : n
    text ( vertex(i).x + dx, vertex(i).y + dx, num2str ( i ) );
  end

  for i = 1 : n
    line ( [ vertex(i).x, vertex(vertex(i).next).x ], ...
           [ vertex(i).y, vertex(vertex(i).next).y ], ...
           'LineWidth', 3, 'Color', 'r' )
  end

  xlabel ( '<-- X -->' )
  ylabel ( '<-- Y -->' )
  title ( prefix );
  axis equal
%
%  Triangulate the polygon.
%
  triangles = polygon_triangulate ( vertex );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Internal diagonals for triangulation:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n - 3
    fprintf ( 1, '  %2d  %2d\n', triangles(i,1:2) );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Triangles:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n - 2
    fprintf ( 1, '  %2d  %2d  %2d\n', triangles(i,1:3) );
  end
%
%  Draw the triangulated polygon.
%
  figure ( 2 )

  clf

  grid on

  hold on
%
%  Make the plot a little bigger than the data.
%
  plot ( xmin - 2 * dx, ymin - 2 * dx, 'w.' );
  plot ( xmax + 2 * dx, ymin + 2 * dx, 'w.' );

  for i = 1 : n
    plot ( vertex(i).x, vertex(i).y, 'k.', 'MarkerSize', 25 )
  end

  for i = 1 : n
    text ( vertex(i).x + dx, vertex(i).y + dx, num2str ( i ) );
  end

  for i = 1 : n
    line ( [ vertex(i).x, vertex(vertex(i).next).x ], ...
           [ vertex(i).y, vertex(vertex(i).next).y ], 'LineWidth', 2, 'Color', 'r' )
  end

  for i = 1 : n - 3
    i1 = triangles(i,1);
    i2 = triangles(i,2);
    line ( [ vertex(i1).x, vertex(i2).x ], ...
           [ vertex(i1).y, vertex(i2).y ], 'LineWidth', 3, 'Color', 'b' )
  end

  xlabel ( '<-- X -->' )
  ylabel ( '<-- Y -->' )
  title ( sprintf ( 'Triangulation of "%s"', prefix ) );
  axis equal
%
%  Optionally, animate the triangulation.
%
  if ( animate == 'y' )

    fprintf ( 1, '\n' );
    fprintf ( 1, '  ANIMATION OPTION SELECTED!\n' );
    fprintf ( 1, '  Press return to see each diagonal added.\n' );

    figure ( 3 )

    clf

    grid on

    hold on
%
%  Make the plot a little bigger than the data.
%
    plot ( xmin - 2 * dx, ymin - 2 * dx, 'w.' );
    plot ( xmax + 2 * dx, ymin + 2 * dx, 'w.' );

    for i = 1 : n
      plot ( vertex(i).x, vertex(i).y, 'k.', 'MarkerSize', 25 )
    end

    for i = 1 : n
      text ( vertex(i).x + dx, vertex(i).y + dx, num2str ( i ) );
    end

    for i = 1 : n
      line ( [ vertex(i).x, vertex(vertex(i).next).x ], ...
             [ vertex(i).y, vertex(vertex(i).next).y ], 'LineWidth', 2, 'Color', 'r' )
    end

    for i = 1 : n - 3
      i1 = triangles(i,1);
      i2 = triangles(i,2);
      i3 = triangles(i,3);
      axis equal
      pause

      patch ( [ vertex(i1).x, vertex(i2).x, vertex(i3).x ], ...
              [ vertex(i1).y, vertex(i2).y, vertex(i3).y ], 'g' );

      line ( [ vertex(i1).x, vertex(i2).x ], ...
             [ vertex(i1).y, vertex(i2).y ], 'LineWidth', 3, 'Color', 'b' )

      axis equal

    end

    pause
    i = n - 2;
    i1 = triangles(i,1);
    i2 = triangles(i,2);
    i3 = triangles(i,3);
    line ( [ vertex(i1).x, vertex(i2).x ], ...
           [ vertex(i1).y, vertex(i2).y ], 'LineWidth', 3, 'Color', 'b' )

    patch ( [ vertex(i1).x, vertex(i2).x, vertex(i3).x ], ...
            [ vertex(i1).y, vertex(i2).y, vertex(i3).y ], 'g' );

    xlabel ( '<-- X -->' )
    ylabel ( '<-- Y -->' )
    title ( sprintf ( 'Triangulation of "%s"', prefix ) );
    axis equal

  end
%
%  Write the diagonals to a file.
%
  i4mat_write ( diagonal_filename, 2, n-3, triangles(1:n-3,1:2)' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Diagonals written to "%s".\n', diagonal_filename );
%
%  Write the triangles to a file.
%
  i4mat_write ( triangle_filename, 3, n-2, triangles(1:n-2,1:3)' );

  fprintf ( 1, '  Triangles written to "%s".\n', triangle_filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TRIANGULATE\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function area = area_poly2 ( vertex )

%*****************************************************************************80
%
%% AREA_POLY2 computes the area of a polygon.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex array VERTEX(*).
%
%    Output, real AREA, the area of the polygon.
%
  area = 0.0;

  first = 1;

  i = first;

  ip1 = vertex(i).next;
  if ( ip1 == first )
    return
  end

  ip2 = vertex(ip1).next;
  if ( ip2 == first )
    return
  end

  while ( 1 )

    area = area + triangle_area ( vertex(i), vertex(ip1), vertex(ip2) );

    i = ip1;
    ip1 = ip2;
    ip2 = vertex(ip1).next;

    if ( ip2 == first )
      break
    end

  end

  return
end
function value = between ( va, vb, vc )

%*****************************************************************************80
%
%% BETWEEN is TRUE if vertex VC is between vertices VA and VB.
%
%  Discussion:
%
%    The points must be (numerically) collinear.
%
%    Given that condition, we take the greater of VA.X - VB.X and VA.Y - VB.Y
%    as a "scale" and check where VC's value lies.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, real VA, VB, VC, the vertices.
%
%    Output, integer VALUE, is 1 if VC is between VA and VB,
%    and 0 otherwise.
%
  if ( ~collinear ( va, vb, vc ) )
    value = 0;
    return
  end

  if ( abs ( va.y - vb.y ) < abs ( va.x - vb.x ) )
    xmax = max ( va.x, vb.x );
    xmin = min ( va.x, vb.x );
    value = ( xmin <= vc.x && vc.x <= xmax );
  else
    ymax = max ( va.y, vb.y );
    ymin = min ( va.y, vb.y );
    value = ( ymin <= vc.y && vc.y <= ymax );
  end

  return
end
function value = collinear ( va, vb, vc )

%*****************************************************************************80
%
%% COLLINEAR returns a measure of collinearity for three points.
%
%  Discussion:
%
%    In order to deal with collinear points whose coordinates are not
%    numerically exact, we compare the area of the largest square
%    that can be created by the line segment between two of the points
%    to (twice) the area of the triangle formed by the points.
%
%    If the points are collinear, their triangle has zero area.
%    If the points are close to collinear, then the area of this triangle
%    will be small relative to the square of the longest segment.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, real VA, VB, VC, the vertices.
%
%    Output, integer VALUE, is 1 if the points are judged to be collinear,
%    and 0 otherwise.
%
  area = 0.5 * ( ( vb.x - va.x ) * ( vc.y - va.y ) ...
               - ( vc.x - va.x ) * ( vb.y - va.y ) );
%
%  MATLAB's MAX function has decided to be unfriendly, and I am
%  too annoyed to try to figure out how to placate it when all
%  I want to say is M = max ( A, B, C )!
%
  area_max =                 ( va.x - vb.x )^2 + ( va.y - vb.y )^2;
  area_max = max ( area_max, ( vb.x - vc.x )^2 + ( vb.y - vc.y )^2 );
  area_max = max ( area_max, ( vc.x - va.x )^2 + ( vc.y - va.y )^2 );

  if ( area_max <= eps )
    value = 1;
  elseif ( 2.0 * abs ( area ) <= eps * area_max )
    value = 1;
  else
    value = 0;
  end

  return
end
function value = diagonal ( im1, ip1, vertex )

%*****************************************************************************80
%
%% DIAGONAL: VERTEX(IM1):VERTEX(IP1) is a proper internal diagonal.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 May 2014
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, integer IM1, IP1, the indices of two vertices.
%
%    Input, vertex array VERTEX(*).
%
%    Output, integer VALUE, the value of the test.
%
  value = in_cone ( im1, ip1, vertex ) && ...
          in_cone ( ip1, im1, vertex ) && ...
          diagonalie ( im1, ip1, vertex );

  return
end
function value = diagonalie ( im1, ip1, vertex )

%*****************************************************************************80
%
%% DIAGONALIE: VERTEX(IM1):VERTEX(IP1) is a proper diagonal.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, integer IM1, IP1, the indices of two vertices.
%
%    Input, vertex array VERTEX(*).
%
%    Output, int VALUE, the value of the test.
%
  first = im1;

  j = vertex(first).index;
  jp1 = vertex(first).next;

  value = 1;
%
%  For each edge VERTEX(J):VERTEX(JP1) of the polygon:

  while ( 1 )
%
%  Skip any edge that includes vertex IM1 or IP1.
%
    if ( j == im1 || j == ip1 || jp1 == im1 || jp1 == ip1 )

    else
      if ( intersect ( vertex(im1), vertex(ip1), vertex(j), vertex(jp1) ) )
        value = 0;
        return
      end
    end

    j = jp1;
    jp1 = vertex(j).next;

    if ( j == vertex(first).index )
      break
    end

  end

  return
end
function vertex = ear_init ( vertex )

%*****************************************************************************80
%
%% EAR_INIT initializes the "earity" of each vertex.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input/output, vertex array VERTEX(*).  On output, the "ear" field
%    of the vertex array has been initialized.
%
  im1 = vertex(1).prev;
  i   = vertex(1).index;
  ip1 = vertex(1).next;

  while ( 1 )

    vertex(i).ear = diagonal ( im1, ip1, vertex );

    im1 = i;
    i   = ip1;
    ip1 = vertex(i).next;

    if ( i == vertex(1).index )
      break
    end

  end

  return
end
function value = i4_modp ( i, j )

%*****************************************************************************80
%
%% I4_MODP returns the nonnegative remainder of I4 division.
%
%  Discussion:
%
%    If
%      NREM = I4_MODP ( I, J )
%      NMULT = ( I - NREM ) / J
%    then
%      I = J * NMULT + NREM
%    where NREM is always nonnegative.
%
%    The MOD function computes a result with the same sign as the
%    quantity being divided.  Thus, suppose you had an angle A,
%    and you wanted to ensure that it was between 0 and 360.
%    Then mod(A,360) would do, if A was positive, but if A
%    was negative, your result would be between -360 and 0.
%
%    On the other hand, I4_MODP(A,360) is between 0 and 360, always.
%
%  Example:
%
%        I     J     MOD  I4_MODP    Factorization
%
%      107    50       7       7    107 =  2 *  50 + 7
%      107   -50       7       7    107 = -2 * -50 + 7
%     -107    50      -7      43   -107 = -3 *  50 + 43
%     -107   -50      -7      43   -107 =  3 * -50 + 43
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 March 1999
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, the number to be divided.
%
%    Input, integer J, the number that divides I.
%
%    Output, integer VALUE, the nonnegative remainder when I is
%    divided by J.
%
  if ( j == 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4_MODP - Fatal error!\n' );
    fprintf ( 1, '  Illegal divisor J = %d\n', j );
    error ( 'I4_MODP - Fatal error!' );
  end

  value = mod ( i, j );

  if ( value < 0 )
    value = value + abs ( j );
  end

  return
end
function value = i4_wrap ( ival, ilo, ihi )

%*****************************************************************************80
%
%% I4_WRAP forces an integer to lie between given limits by wrapping.
%
%  Example:
%
%    ILO = 4, IHI = 8
%
%    I   Value
%
%    -2     8
%    -1     4
%     0     5
%     1     6
%     2     7
%     3     8
%     4     4
%     5     5
%     6     6
%     7     7
%     8     8
%     9     4
%    10     5
%    11     6
%    12     7
%    13     8
%    14     4
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 October 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer IVAL, an integer value.
%
%    Input, integer ILO, IHI, the desired bounds for the integer value.
%
%    Output, integer I4_WRAP, a "wrapped" version of IVAL.
%
  jlo = min ( ilo, ihi );
  jhi = max ( ilo, ihi );

  wide = jhi - jlo + 1;

  if ( wide == 1 )
    value = jlo;
  else
    value = jlo + i4_modp ( ival - jlo, wide );
  end

  return
end
function i4mat_write ( output_filename, m, n, table )

%*****************************************************************************80
%
%% I4MAT_WRITE writes an I4MAT file.
%
%  Discussion:
%
%    An I4MAT is an array of I4's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 June 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, integer TABLE(M,N), the points.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'I4MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %12d', round ( table(i,j) ) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function value = in_cone ( im1, ip1, vertex )

%*****************************************************************************80
%
%% IN_CONE is TRUE if the diagonal VERTEX(IM1):VERTEX(IP1) is strictly internal.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, integer IM1, IP1, the indices of two vertices.
%
%    Input, vertex array VERTEX(*).
%
%    Output, int VALUE, the value of the test.
%
  im2 = vertex(im1).prev;
  i = vertex(im1).next;

  if ( left_on ( vertex(im1), vertex(i), vertex(im2) ) )

    value = left ( vertex(im1), vertex(ip1), vertex(im2) ) && ...
            left ( vertex(ip1), vertex(im1), vertex(i) );

  else

    value = ~ ( left_on ( vertex(im1), vertex(ip1), vertex(i) ) && ...
                left_on ( vertex(ip1), vertex(im1), vertex(im2) ) );

  end

  return
end
function value = intersect ( va, vb, vc, vd )

%*****************************************************************************80
%
%% INTERSECT is true if lines VA:VB and VC:VD intersect.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex VA, VB, VC, VD, four vertices.
%
%    Output, integer VALUE, the value of the test.
%
  if ( intersect_prop ( va, vb, vc, vd ) )
    value = 1;
  elseif ( between ( va, vb, vc ) || ...
           between ( va, vb, vd ) || ...
           between ( vc, vd, va ) || ...
           between ( vc, vd, vb ) )
    value = 1;
  else
    value = 0;
  end

  return
end
function value = intersect_prop ( va, vb, vc, vd )

%*****************************************************************************80
%
%% INTERSECT_PROP is TRUE if lines VA:VB and VC:VD have a proper intersection.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex VA, VB, VC, VD, four vertices.
%
%    Output, integer VALUE, the result of the test.
%
  if ( collinear ( va, vb, vc ) || ...
       collinear ( va, vb, vd ) || ...
       collinear ( vc, vd, va ) || ...
       collinear ( vc, vd, vb ) )
    value = 0;
  else
    value = xor ( left ( va, vb, vc ), left ( va, vb, vd ) ) && ...
            xor ( left ( vc, vd, va ), left ( vc, vd, vb ) );
  end

  return
end
function value = left ( va, vb, vc )

%*****************************************************************************80
%
%% LEFT is true if VC is to the left of the line VA:VB.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex VA, VB, VC, three vertices.
%
%    Output, integer VALUE, the result of the test.
%
  value = ( 0 < triangle_area ( va, vb, vc ) );

  return
end
function value = left_on ( va, vb, vc )

%*****************************************************************************80
%
%% LEFT_ON is TRUE if VC is to the left of, or on, the line VA:VB.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex VA, VB, VC, three vertices.
%
%    Output, integer VALUE, the result of the test.
%
  value = ( 0 <= triangle_area ( va, vb, vc ) );

  return
end
function triangles = polygon_triangulate ( vertex )

%*****************************************************************************80
%
%% POLYGON_TRIANGULATE determines a triangulation of a polygon.
%
%  Discussion:
%
%    There are N-3 triangles in the triangulation.
%
%    For the first N-2 triangles, the first edge listed is always an
%    internal diagonal.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 February 2011
%
%  Author:
%
%    Original C version by Joseph ORourke.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Joseph ORourke,
%    Computational Geometry in C,
%    Cambridge, 1998,
%    ISBN: 0521649765,
%    LC: QA448.D38.
%
%  Parameters:
%
%    Input, vertex array VERTEX(N).
%
%    Output, integer TRIANGLES(N-2,3), the triangles of the triangulation.
%
  n = length ( vertex );
  first = 1;

  triangles = zeros ( n - 2, 3 );
  triangle_num = 0;

  i2 = first;

  while ( triangle_num < n - 3 )
%
%  If I2 is an ear, gather information necessary to carry out
%  the slicing operation and subsequent "healing".
%
    if ( vertex(i2).ear )

      i3 = vertex(i2).next;
      i4 = vertex(i3).next;
      i1 = vertex(i2).prev;
      i0 = vertex(i1).prev;
%
%  Make vertex I2 disappear.
%
      vertex(i1).next = i3;
      vertex(i2).index = 0;
      vertex(i3).prev = i1;
%
%  Update the earity of I1 and I3, because I2 disappeared.
%
      vertex(i1).ear = diagonal ( i0, i3, vertex );
      vertex(i3).ear = diagonal ( i1, i4, vertex );
%
%  Add the diagonal [I3, I1, I2] to the list.
%
      triangle_num = triangle_num + 1;
      triangles(triangle_num,1) = i3;
      triangles(triangle_num,2) = i1;
      triangles(triangle_num,3) = i2;

    end
%
%  Try the next vertex.
%
    i2 = vertex(i2).next;

  end
%
%  The last triangle is formed from the three remaining vertices.
%
  i3 = vertex(i2).next;
  i1 = vertex(i2).prev;
  triangle_num = triangle_num + 1;
  triangles(triangle_num,1) = i3;
  triangles(triangle_num,2) = i1;
  triangles(triangle_num,3) = i2;

  return
end
function print_vertices ( vertex )

%*****************************************************************************80
%
%% PRINT_VERTICES prints the vertex information.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, vertex array VERTEX(*).
%
  n = length ( vertex );

  fprintf ( 1, '\n' );
  fprintf ( 1, '   I IM1 IP1      X           Y       Earity\n' );
  fprintf ( 1, '\n' );

  for i = 1 : n

    if ( vertex(i).ear == -1 )
      earity = 'Unknown';
    elseif ( vertex(i).ear == 0 )
      earity = 'No';
    else
      earity = 'Yes';
    end

    fprintf ( 1, '  %2d  %2d  %2d  %10f  %10f  %s\n', ...
      vertex(i).index, vertex(i).prev, vertex(i).next, ...
      vertex(i).x, vertex(i).y, earity );

  end

  return
end
function vertex = read_vertices ( filename, direction )

%*****************************************************************************80
%
%% READ_VERTICES reads vertex coordinates and initializes the vertex structure.
%
%  Discussion:
%
%    If the polygon was found to have negative area on the first pass,
%    we try again, reversing the vertex ordering, and hoping the user simply
%    listed the vertices in clockwise order.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 January 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string FILENAME, the name of the file to be read.
%
%    Input, integer DIRECTION, the ordering for the vertices.
%    +1, first vertex is 1, and count up.
%    -1, first vertex is N, and count down.
%
%    Output, vertex array VERTEX(*).
%
  xy = load ( filename );

  [ n, dim ] = size ( xy );

  if ( direction == -1 )
    xy(1:n,1) = xy(n:-1:1,1);
    xy(1:n,2) = xy(n:-1:1,2);
  end

  for i = 1 : n
    vertex(i).index = i;
    vertex(i).prev = i4_wrap ( i - 1, 1, n );
    vertex(i).next = i4_wrap ( i + 1, 1, n );
    vertex(i).x = xy(i,1);
    vertex(i).y = xy(i,2);
    vertex(i).ear = -1;
  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end
function area = triangle_area ( v1, v2, v3 )

%*****************************************************************************80
%
%% TRIANGLE_AREA computes the signed area of a triangle.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, vertex V1, V2, V3, three vertices.
%
%    Output, real AREA, the signed area of the triangle.
%
  area = 0.5 * ( ( v2.x - v1.x ) * ( v3.y - v1.y ) ...
               - ( v3.x - v1.x ) * ( v2.y - v1.y ) );

  return
end


% created: Zoya Bylinskii, Aug 2014
% Code for computing degrees of visual angle

% This code has been written to make it easier to report visual angle in
% papers, and to ensure a standardized calculation is used.

% This code can take variable input (e.g. horizontal, vertical, or diagonal
% screen measurements in any units), and will calculate any number of
% degrees of visual angle in pixels, as well as degrees of visual angle
% spanned by the computer screen or an image.

% The code is provided on: http://saliency.mit.edu/

% Resources used: http://osdoc.cogsci.nl/miscellaneous/visual-angle/,
%                 http://en.wikipedia.org/wiki/Visual_angle
% Thank you to Lavanya Sharan and Melissa Vo for helpful discussion.

function computeDegVisAngle_gui()

% ------ INPUT ARGUMENTS: ------
% necessary:
% 'distance'         distance to screen with units (e.g. 56 cm)

% provide at least one of:
% 'height'           height of screen with units
% 'width'            width of screen with units
% 'diagonal'         diagonal of screen with units

% provide at least one of:
% 'hres'             horizontal resolution of screen (provide this if also provided 'height')
% 'vres'             vertical resolution of screen (provide this if also provided 'width')
% provide both if only provided 'diagonal'

% optional:
%'outputUnit'        output units to measure screen, distance in (default: cm)
%'numDegs'           number of degres of visual angle (in pixels) to calculate (default numDegs=1)
%'imageWidth'        width of image in pixels
%'imageHeight'       height of image in pixels

% NOTE: if you provide the screen diagonal and resolution, then the screen
% height and width will be estimated under the assumption that the aspect
% ratio of the screen dimensions matches that of the set resolution.
% If these estimates look wrong, either:
% (1) you measured the monitor dimensions, instead of the screen dimensions
% (2) the screen resolution aspect ratio does not match the screen
%     dimensions
% (3) explicitely enter the screen height and width instead of the diagonal

% Common mistake: remember that the number of pixels per unit size of screen
% or image is a linear function, but number of pixels per degree of visual
% angle is NOT.

% Remember: when writing a paper, include enough information for visual
% angle to be calculated - providing screen resolution without screen
% dimensions or vice versa is insufficient! Also, remember to measure the
% screen itself, rather than the whole monitor.

% units required for distance, height, width, and diagonal values
ui=inputdlg({'distance (with units)','height (with units)',...
    'width (with units)','diagonal (with units)',...
    'horizontal resolution','vertical resolution',...
    'output units (optional)','number of degrees (optional)',...
    'image width in pixels (optional)','image height in pixels (optional)'},...
    'Visual Angle Calculator',1,...
    {'','','','','','','cm','1','',''});

dist = ui{1};
height = ui{2};
width = ui{3};
diagonal = ui{4};
hres = str2num(ui{5});
vres = str2num(ui{6});
outputUnit = ui{7};
numDegs = str2num(ui{8});
imageWidth = str2num(ui{9});
imageHeight = str2num(ui{10});

computeDegVisAngle_helper(dist,height,width,diagonal,hres,vres,outputUnit,numDegs,imageWidth,imageHeight);


function [ x, seed ] = maxwell_sample ( a, seed )

%*****************************************************************************80
%
%% MAXWELL_SAMPLE samples the Maxwell PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, the parameter of the PDF.
%    0 < A.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real X, a sample of the PDF.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
  a2 = 3.0;
  [ x, seed ] = chi_square_sample ( a2, seed );

  x = a * sqrt ( x );

  return
end


function err = test_performance
%TEST_PERFORMANCE compare performance of factorization/solve methods.
% Returns the largest relative residual seen.
%
% Example
%   err = test_performance
%
% See also test_all, test_factorize, factorize, inverse, mldivide

% Copyright 2009, Timothy A. Davis, University of Florida

fprintf ('\nPerformance comparisons of 5 methods:\n') ;
fprintf ('    backslash: A\\b, or L\\b (and related) for solve times.\n') ;
fprintf ('    linsolve:  a built-in MATLAB function\n') ;
fprintf ('    factorize1:  the simple factorization object (uses LU)\n') ;
fprintf ('    factorize:  the full-featured factorization object\n') ;
fprintf ('    inv: x=inv(A)*b, the explicit inverse (ack!)\n') ;
fprintf ('Run times are in seconds.\n') ;
fprintf ('Times relative to best times are in parentheses.\n') ;

% linsolve options:
A_is_posdef.POSDEF = true ;     % for x = A\b where A is sym. pos. definite
A_is_posdef.SYM = true ;
lsolve.LT = true ;              % for x = L\b where L is lower triangular
usolve.UT = true ;              % for x = U\b where U is upper triangular
ltsolve.LT = true ;             % for x = L'b where L is lower triangular
ltsolve.TRANSA = true ;

nn = [50 100 500 1000] ;        % matrix sizes to test
ns = length (nn) ;
tmax = 1 ;                      % minimum testing time
err = 0 ;                       % largest relative residual seen

for posdef = 0:1

    if (posdef)
        fprintf ('\n------------------ For positive definite matrices:\n') ;
    else
        fprintf ('\n------------------ For unsymmetric matrices:\n') ;
    end

    Tfactor = zeros (ns,5) ;
    Tsolve  = zeros (ns,5) ;

    %-----------------------------------------------------------------------
    % compare factorizations times (plus a single solve)
    %-----------------------------------------------------------------------

    fprintf ('\nCompare factorization times:\n') ;
    for i = 1:ns
        n = nn (i) ;

        fprintf ('n %4d ', n) ;

        A = rand (n) ;
        if (posdef)
            A = A'*A + eye (n) ;
        end
        anorm = norm (A,1) ;
        b = rand (n,1) ;

        % method 1: backslash
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            x = A\b ;
            k = k + 1 ;
            t = toc ;
        end
        Tfactor (i,1) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x

        if (posdef)

            % method 2: linsolve (pos. definite case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = linsolve (A,b, A_is_posdef) ;
                k = k + 1 ;
                t = toc ;
            end
            Tfactor (i,2) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

        else

            % method 2: linsolve (unsymmetric case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = linsolve (A,b) ;
                k = k + 1 ;
                t = toc ;
            end
            Tfactor (i,2) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

        end

        % method 3: factorize1 method
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            F = factorize1 (A) ;
            x = F\b ;
            k = k + 1 ;
            t = toc ;
        end
        Tfactor (i,3) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x F

        % method 4: factorize method
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            F = factorize (A, posdef) ;
            x = F\b ;
            k = k + 1 ;
            t = toc ;
        end
        Tfactor (i,4) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x F

        % method 5: inv method (ack!)
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            S = inv (A) ;
            x = S*b ;               %#ok
            k = k + 1 ;
            t = toc ;
        end
        Tfactor (i,5) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x S

        tbest = min (Tfactor (i,:)) ;
        fprintf ('tbest %10.6f : backslash (%5.2f) ', tbest, ...
            Tfactor (i,1) / tbest);
        fprintf ('linsolve (%5.2f) ', Tfactor (i,2) / tbest) ;
        fprintf ('factorize1 (%5.2f) ', Tfactor (i,3) / tbest) ;
        fprintf ('factorize (%5.2f) ', Tfactor (i,4) / tbest) ;
        fprintf ('inv (%5.2f)\n',  Tfactor (i,5) / tbest) ;

    end

    %-----------------------------------------------------------------------
    % compare solve times
    %-----------------------------------------------------------------------

    fprintf ('\nCompare solve times:\n') ;
    for i = 1:ns
        n = nn (i) ;

        fprintf ('n %4d ', n) ;

        A = rand (n) ;
        if (posdef)
            A = A'*A + eye (n) ;
        end
        b = rand (n,1) ;
        anorm = norm (A,1) ;

        if (posdef)
            L = chol (A, 'lower') ;
        else
            [L,U,p] = lu (A,'vector') ;
        end

        S = inv (A) ;
        F = factorize  (A) ;
        F1 = factorize1 (A) ;

        if (posdef)

            % method 1: backslash (pos. definite case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = L' \ (L\b) ;
                k = k + 1 ;
                t = toc ;
            end
            Tsolve (i,1) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

            % method 2: linsolve (pos. definite case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = linsolve (L, linsolve (L, b, lsolve), ltsolve) ;
                k = k + 1 ;
                t = toc ;
            end
            Tsolve (i,2) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

        else

            % method 1: backslash (unsymmetric case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = U \ (L \ (b (p))) ;
                k = k + 1 ;
                t = toc ;
            end
            Tsolve (i,1) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

            % method 2: linsolve (unsymmetric case)
            t = 0 ;
            k = 0 ;
            tic
            while (t < tmax)
                x = linsolve (U, linsolve (L, b (p), lsolve), usolve) ;
                k = k + 1 ;
                t = toc ;
            end
            Tsolve (i,2) = t / k ;
            err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
            clear x

        end

        % method 3: factorize1 object
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            x = F1\b ;
            k = k + 1 ;
            t = toc ;
        end
        Tsolve (i,3) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x

        % method 4: factorize object
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            x = F\b ;
            k = k + 1 ;
            t = toc ;
        end
        Tsolve (i,4) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x

        % method 5: "inv" method (ack!)
        t = 0 ;
        k = 0 ;
        tic
        while (t < tmax)
            x = S*b ;           %#ok
            k = k + 1 ;
            t = toc ;
        end
        Tsolve (i,5) = t / k ;
        err = max (err, norm (A*x-b,1) / (anorm + norm (x,1))) ;
        clear x

        tbest = min (Tsolve (i,:)) ;
        fprintf ('tbest %10.6f : backslash (%5.2f) ', tbest, ...
            Tsolve (i,1) / tbest);
        fprintf ('linsolve (%5.2f) ', Tsolve (i,2) / tbest) ;
        fprintf ('factorize1 (%5.2f) ', Tsolve (i,3) / tbest) ;
        fprintf ('factorize (%5.2f) ', Tsolve (i,4) / tbest) ;
        fprintf ('inv (%5.2f)\n',  Tsolve (i,5) / tbest) ;

        clear F F1 S L U p

    end

    % determine break-even values for inv
    fprintf ('\nBreak-even values K for inv vs the other methods\n') ;
    fprintf ('(# of solves must exceed K for inv(A)*b to be faster):\n') ;
    for i = 1:ns
        n = nn (i) ;
        s = zeros (4,1) ;
        for t = 1:4
            if (Tfactor (i,5) > Tfactor (i,t) && ...
                Tsolve (i,5) > Tsolve (i,t))
                % inv is always slower, for any K
                s (t) = inf ;
            elseif (Tfactor (i,5) < Tfactor (i,t) && ...
                Tsolve (i,5) < Tsolve (i,t))
                % inv is always faster, for any K
                s (t) = 1 ;
            else
                s (t) = (Tfactor (i,5) - Tfactor (i,t)) / ...
                         (Tsolve (i,t) - Tsolve (i,5));
            end
        end

        fprintf ('n %4d  # solves vs backslash %8.1f', n, max (1, s (1))) ;
        fprintf (' vs linsolve: %8.1f  ', max (1, s (2))) ;
        fprintf (' vs factorize1: %8.1f  ', max (1, s (3))) ;
        fprintf (' vs factorize: %8.1f\n', max (1, s (4))) ;
    end

end

%---------------------------------------------------------------------------
% compute the Schur complement, S = A-B*inv(D)*C
%---------------------------------------------------------------------------

fprintf ('\nSchur complement, S=A-B*inv(D)*C or A-B(D\\C),\n') ;
fprintf ('where A, B, C, and D are square and unsymmetric.\n') ;
fprintf ('"inverse" means S=A-B*inverse(D)*C, which does not actually\n') ;
fprintf ('use the inverse, but uses the factorization object instead.\n') ;

Tschur = zeros (ns,6) ;

for i = 1:ns
    n = nn (i) ;
    fprintf ('n %4d ', n) ;

    A = rand (n) ;
    B = rand (n) ;
    C = rand (n) ;
    D = rand (n) ;

    % method 1: backslash
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B*(D\C) ;                                               %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,1) = t / k ;
    clear S

    % method 2: linsolve
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B * linsolve (D,C) ;                                    %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,2) = t / k ;
    clear S

    % method 3: factorize1 object
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B*(factorize1(D)\C) ;                                   %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,3) = t / k ;
    clear F S

    % method 4: factorize object
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B*(factorize(D)\C) ;                                    %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,4) = t / k ;
    clear F S

    % method 5:
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B*inverse(D)*C ;                                        %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,5) = t / k ;
    clear S

    % method 6: "inv" method, using the explicit inverse (ack!)
    t = 0 ;
    k = 0 ;
    tic
    while (t < tmax)
        S = A - B*inv(D)*C ;                                            %#ok
        k = k + 1 ;
        t = toc ;
    end
    Tschur (i,6) = t / k ;
    clear S

    tbest = min (Tschur (i,:)) ;
    fprintf ('tbest %10.6f : backslash (%5.2f) ', tbest, ...
        Tschur (i,1) / tbest);
    fprintf ('linsolve (%5.2f) ', Tschur (i,2) / tbest) ;
    fprintf ('factorize1 (%5.2f) ', Tschur (i,3) / tbest) ;
    fprintf ('factorize (%5.2f) ', Tschur (i,4) / tbest) ;
    fprintf ('inverse (%5.2f) ', Tschur (i,5) / tbest) ;
    fprintf ('inv (%5.2f)\n',  Tschur (i,6) / tbest) ;

end


function y = log_normcdf( x, approx )

%LOG_NORMCDF   Logarithm of the cumulative normal distribution.
%   Y = LOG_NORMCDF(X) is the logarithm of the CDF of the normal
%   distribution at the point X.
%
%                                1    / x
%       LOG_NORMCDF(X) = LOG( ------- |   exp(-t^2/2) dt )
%                             sqrt(2) / -Inf
%
%   For numeric X, LOG_NORMCDF(X) is computed using the equivalent
%   expression LOG(0.5*ERFC(-X*SQRT(0.5))). When X is a CVX variable, a
%   a piecewise quadratic *approximation* is employed instead. This
%   approximation gives good results when -4 <= x <= 4, and will be
%   improved in future releases of CVX.
%
%   For array values of X, the LOG_NORMCDF returns an array of identical
%   size with the calculation applied independently to each element.
%
%   X must be real.
%
%   Disciplined convex programming information:
%       LOG_NORMCDF is concave and nondecreasing in X. Therefore, when used
%       in CVX specifications, X must be concave.

error(nargchk(1,2,nargin));
if ~isreal( x ),
    error( 'Argument must be real.' );
end
if nargin > 1,
    % For debugging purposes only
    y = cvx_constant(log_normcdf(cvx(x)));
else
    y = log(0.5*erfc(-x*sqrt(0.5)));
end


function out = DN_cv(x,k)
% DN_cv     Coefficient of variation
%
% Coefficient of variation of order k is sigma^k / mu^k (for sigma, standard
% deviation and mu, mean) of a data vector, x
%
%---INPUTS:
%
% x, the input data vector
% k, the order of coefficient of variation (k = 1 is default)

% ------------------------------------------------------------------------------
% Copyright (C) 2020, Ben D. Fulcher <ben.d.fulcher@gmail.com>,
% <http://www.benfulcher.com>
%
% If you use this code for your research, please cite the following two papers:
%
% (1) B.D. Fulcher and N.S. Jones, "hctsa: A Computational Framework for Automated
% Time-Series Phenotyping Using Massive Feature Extraction, Cell Systems 5: 527 (2017).
% DOI: 10.1016/j.cels.2017.10.001
%
% (2) B.D. Fulcher, M.A. Little, N.S. Jones, "Highly comparative time-series
% analysis: the empirical structure of time series and their methods",
% J. Roy. Soc. Interface 10(83) 20130048 (2013).
% DOI: 10.1098/rsif.2013.0048
%
% This function is free software: you can redistribute it and/or modify it under
% the terms of the GNU General Public License as published by the Free Software
% Foundation, either version 3 of the License, or (at your option) any later
% version.
%
% This program is distributed in the hope that it will be useful, but WITHOUT
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
% details.
%
% You should have received a copy of the GNU General Public License along with
% this program. If not, see <http://www.gnu.org/licenses/>.
% ------------------------------------------------------------------------------

%-------------------------------------------------------------------------------
% Check inputs
%-------------------------------------------------------------------------------
if nargin < 2 || isempty(k)
    k = 1; % Do standard CV by default
end

if (rem(k,1) ~= 0) || (k < 0)
    warning('k should probably be a positive integer');
    % Carry on with just this warning, though
end

% Compute the coefficient of variation (of order k) of the data

out = (std(x))^k / (mean(x))^k;

end