classdef InverseGammaD
%%INVERSEGAMMAD Functions to handle the inverse gamma distribution.
%Implemented methods are: mean, var, PDF, CDF, rand, entropy
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(k, beta)
%%MEAN Obtain the mean of the inverse gamma distribution for given shape
%      and scale parameters.
%
%INPUTS: k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: val The mean of the inverse gamma distribution.
%
%If k<1, then the distribution has no mean and a NaN is returned.
%
%The distribution arises when estimating radar cross sections in Ch.
%10.3.2 of [1].
%
%REFERENCES:
%[1] W. Koch, Tracking and Sensor Fusion: Methodological Framework and
%    Selected Applications. Berlin, Germany: Springer, 2014.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(k<1)
        val=NaN;
    else
        val=beta/(k-1);
    end
end

function val=var(k,beta)
%%VAR Obtain the variance of the inverse gamma distribution for given shape
%     and scale parameters.
%
%INPUTS: k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: val  The variance of the inverse gamma distribution.
%
%If k<2, then the distribution has no variance and a NaN is returned.
%
%The distribution arises when estimating radar cross sections in Ch.
%10.3.2 of [1].
%
%REFERENCES:
%[1] W. Koch, Tracking and Sensor Fusion: Methodological Framework and
%    Selected Applications. Berlin, Germany: Springer, 2014.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(k<2)
        val=NaN;
    else
        val=beta^2/((k-1)^2*(k-2));
    end
end

function val=PDF(x,k,beta)
%%PDF Evaluate the probability density function (PDF) of the inverse gamma
%     distribution at the desired points.
%
%INPUTS: x The point(s) at which the inverse gamma PDF is to be evaluated.
%          Note that x>=0.
%        k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: val The value(s) of the PDF of the inverse gamma distribution
%             with parameters k and beta evaluated at x.
%
%The inverse gamma distribution is the distribution of the inverse of a
%gamma random variable. Thus, with a little bit of algebra, it can be
%expressed in terms of the gamma PDF.
%
%The distribution arises when estimating radar cross sections in Ch.
%10.3.2 of [1].
%
%REFERENCES:
%[1] W. Koch, Tracking and Sensor Fusion: Methodological Framework and
%    Selected Applications. Berlin, Germany: Springer, 2014.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=(beta^k/gamma(k)).*x.^(-k-1).*exp(-beta./x);
end

function val=CDF(x,k,beta)
%%CDF Evaluate the cumulative distribution function (CDF) of the inverse
%     gamma distribution at desired points.
%
%INPUTS: x The point(s) at which the inverse gamma CDF is to be  evaluated.
%          Note that x>=0.
%        k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: prob The value(s) of the CDF of the inverse gamma distribution
%              with parameters k and beta evaluated at x.
%
%The inverse gamma distribution is the distribution of the inverse of a
%gamma random variable. Thus, with a little bit of algebra, it can be
%expressed in terms of the gamma PDF.
%
%The distribution arises when estimating radar cross sections in Ch.
%10.3.2 of [1].
%
%REFERENCES:
%[1] W. Koch, Tracking and Sensor Fusion: Methodological Framework and
%    Selected Applications. Berlin, Germany: Springer, 2014.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=1-GammaD.CDF(1./x,k,1/beta);
end

function vals=rand(N,k,beta)
%%RAND Generate inverse gamma distributed random variables with the given
%      parameters.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row  vector, then rand
%          returns an MXN1 matrix of random variables.
%        k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated inverse gamma random variables.
%
%This just takes the inverse of gamma distributed random variables.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    vals=1./randGamma(N,k,1/beta);
end

function entropyVal=entropy(k,beta)
%%ENTROPY Obtain the differential entropy of the inverse gamma
%         distribution given in nats. The differential entropy of a
%         continuous distribution is entropy=-int_x p(x)*log(p(x)) dx where
%         the integral is over all values of x. Units of nats mean that the
%         natural logarithm is used in the definition. Unlike the Shannon
%         entropy for discrete variables, the differential entropy of
%         continuous variables can be both positive and negative.
%
%INPUTS: k The shape parameter of the distribution; k>0.
%     beta The scale parameter of the distribution; beta>0.
%
%OUTPUTS: entropyVal The value of the differential entropy in nats.
%
%Differential entropy is defined in Chapter 8 of [1].
%
%REFERENCES:
%[1] T. M. Cover and J. A. Thomas, Elements of Information Theory, 2nd ed.
%    Hoboken, NJ: Wiley-Interscience, 2006.
%
%April 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.

    entropyVal=k+log(beta)+gammaln(k)-(1+k)*psi(k);
end

end
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function pde = sincosRobindata
%% SINCOSDATA trigonometric  data for Poisson equation
%
%     f = 8*pi^2*sin(2*pi*x)*cos(2*pi*y);
%     u = sin(2*pi*x)*cos(2*pi*y);
%     Du = (2*pi*cos(2*pi*x)*cos(2*pi*y), -2*pi*sin(2*pi*x)*sin(2*pi*y));
%
%  Impose Robin boundary condition g_R*u+ du/dn = g_N on [0,1]^2.
%
% Copyright (C)  Long Chen. See COPYRIGHT.txt for details.

pde = struct('f',@f,'exactu',@exactu,'Du',@Du,'g_D',@g_D,'g_R',@g_R,'g_N',@g_N);

% load data (right hand side function)
function rhs =  f(p)
    x = p(:,1); y = p(:,2);
    rhs =  8*pi^2*sin(2*pi*x).*cos(2*pi*y);
end
% exact solution
function u =  exactu(p)
    x = p(:,1); y = p(:,2);
    u =  sin(2*pi*x).*cos(2*pi*y);
end
% derivative of the exact solution
function uprime =  Du(p)
    x = p(:,1); y = p(:,2);
    uprime(:,1) = 2*pi*cos(2*pi*x).*cos(2*pi*y);
    uprime(:,2) = -2*pi*sin(2*pi*x).*sin(2*pi*y);
end
% Dirichlet boundary condition
function u =  g_D(p)
    u =  exactu(p);
end
% coefficients of Robin boundary condition g_R*u+ du/dn = g_N
function f = g_R(p)
    f = ones(size(p,1),1);
end
%
function f = g_N(p)
    f = zeros(size(p,1),1);
    x = p(:,1); y = p(:,2);
    uprime = Du(p);
    leftbd = (abs(x)<eps);  % n = (-1,0);
    f(leftbd) = g_R(p(leftbd,:)).*exactu(p(leftbd,:)) - uprime(leftbd,1);
    rightbd = (abs(x-1)<eps); % n = (1,0);
    f(rightbd) = g_R(p(rightbd,:)).*exactu(p(rightbd,:)) + uprime(rightbd,1);
    topbd = (abs(y-1)<eps);   % n = (0,1)
    f(topbd) = g_R(p(topbd,:)).*exactu(p(topbd,:)) + uprime(topbd,2);
    bottombd = (abs(y)<eps);% n = (0,-1)
    f(bottombd) = g_R(p(bottombd,:)).*exactu(p(bottombd,:)) - uprime(bottombd,2);
end
end


function ind = ichoose(n,k)
%ICHOOSE Choose K indices from the set 1:N.
%   ICHOOSE(N,K) gives all combinations of choosing K indices from
%   the set 1:N without order and without repetitions.
%
%   Example:
%   	ind = ichoose(4,2);
%   	v = 'ABCD';
%   	v(ind) % ['AB';'AC';'AD';'BC';'BD';'CD']
%
%   See also NCHOOSEK

%   Author: Jonas Lundgren <splinefit@gmail.com> 2011

% Check input
if ~isscalar(n) || ~isfinite(n) || n < 0 || fix(n) < n
    error('ICHOOSE:N','N must be a non-negative integer.')
elseif ~isscalar(k) || ~isfinite(k) || k < 0 || fix(k) < k
    error('ICHOOSE:K','K must be a non-negative integer.')
elseif n < k
    ind = zeros(0,k);
    return
elseif k == 0
    ind = zeros(1,0);
    return
end

% Initiate indices
if n < 256
    ind = uint8(k:n)';
elseif n < 65536
    ind = uint16(k:n)';
else
    ind = (k:n)';
end

m = n-k+1;
b = 1:m;

% Generate indices
for j = 1:k-1
    a = b;
    b = cumsum(b);
    c = b(m) + 1 - b(1:m-1);
    if m > 1
        p = ones(b(m),1);
        p(c) = 1 - a(1:m-1);
        p = cumsum(p);
        ind = ind(p,:);
    end
    p = zeros(b(m),1);
    p(1) = k-j;
    p(c) = 1;
    p = cumsum(p);
    ind = [p,ind]; %#ok
end


function [LL,lls]=normloglik(x,mu,sigma2)
% Log-likelihood for the normal distribution
%
% USAGE:
%   [LL,LLS]=normloglik(X,MU,SIGMA2)
%
% INPUTS:
%   X      - Normal random variables, either scalar or column vector
%   MU     - Mean of X, either scalar or size(x)
%   SIGMA2 - Variance of X, either scalar or size(x)
%
% OUTPUTS:
%   LL    - Log-likelihood evaluated at X
%   LLS   - Vector of log-likelihoods corresponding to X
%
% COMMENTS:
%
% REFERENCES:
%   [1] Cassella and Berger (1990) 'Statistical Interence'
%
% See also NORMCDF, NORMINV, NORMRND, NORMPDF

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 9/1/2005

[T,K]=size(x);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if K~=1
    error('x must be a column vector');
end

if nargin==1
    sigma2=ones(T,K);
elseif nargin==2
    %Check mu's conformability
    if length(mu)~=1 && ~all(size(mu)==[T K])
        error('mu must be either a scalar or the same size as X');
    end
    x=x-mu;
    sigma2=ones(T,K);
elseif nargin==3
    if length(mu)~=1 && ~all(size(mu)==[T K])
        error('mu must be either a scalar or the same size as X');
    end
    if any(sigma2<=0)
        error('sigma2 must contain only positive elements')
    end
    if length(sigma2)==1
        sigma2=sigma2*ones(T,K);
    elseif size(sigma2,1)~=T || size(sigma2,2)~=1
        error('sigma2 must be a scalar or a vector with the same dimensions as x');
    end
    x=x-mu;
else
    error('Only 1 to 3 inputs supported');
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargout>1
%Compute the individual log likelihoods if needed
    lls = -0.5*(log(2*pi) + log(sigma2) + x.^2./sigma2);
    % Use these to comput the LL
    LL = sum(lls);
else
    %Compute the log likelihood
    LL  =  -0.5 * (sum(log(sigma2)) + sum((x.^2)./sigma2)  +  T*log(2*pi));
end


function x=fibosearch(fhandle,a,b,npoints)
% fibonacci search for minimum of unknown unimodal function in one variable
%     x = fibosearch(fhandle,a,b,npoints)
% a,b define the search interval with resolution 1/npoints
%create fibonacci sequence of length nfibo
nfibo=22;
fibo=[1,1,zeros(1,nfibo-2)];
for k=1:nfibo-2
    fibo(k+2)=fibo(k+1)+fibo(k);
end
%find number of required iterations
fiboindex=3;
while fibo(fiboindex)<npoints
        fiboindex=fiboindex+1;
end
for k=1:fiboindex-2
    if k==1
        x1 = a+fibo(fiboindex-k-1)/fibo(fiboindex-k+1)*(b-a);
        x2 = b-fibo(fiboindex-k-1)/fibo(fiboindex-k+1)*(b-a);
        fx1 = fhandle(x1);
        fx2 = fhandle(x2);
    end
    if fx1<fx2
        b=x2;
        x2=x1; fx2=fx1;
        x1=a+fibo(fiboindex-k-1)/fibo(fiboindex-k+1)*(b-a);
        fx1=fhandle(x1);
    else
        a=x1;
        x1=x2; fx1=fx2;
        x2=b-fibo(fiboindex-k-1)/fibo(fiboindex-k+1)*(b-a);
        fx2=fhandle(x2);
    end
end
if fx1<fx2
    x=x1;
else
    x=x2;
end
% disp(fiboindex-2)


% .............................................................
    function [shape,naturalDerivatives]=shapeFunctionQ12(xi,eta)

    % shape function and derivatives for Q12 elements
    % shape : Shape functions
    % naturalDerivatives: derivatives w.r.t. xi and eta
    % xi, eta: natural coordinates (-1 ... +1)

    shape=[1/32*(1-xi)*(1-eta)*(-10+9*(xi^2+eta^2));
           1/32*(1+xi)*(1-eta)*(-10+9*(xi^2+eta^2));
           1/32*(1+xi)*(1+eta)*(-10+9*(xi^2+eta^2));
           1/32*(1-xi)*(1+eta)*(-10+9*(xi^2+eta^2));
           9/32*(1-xi^2)*(1-1/3*xi)*(1-eta);
           9/32*(1-xi^2)*(1+1/3*xi)*(1-eta);
           9/32*(1+xi)*(1-eta^2)*(1-1/3*eta);
           9/32*(1+xi)*(1-eta^2)*(1+1/3*eta);
           9/32*(1-xi^2)*(1+1/3*xi)*(1+eta);
           9/32*(1-xi^2)*(1-1/3*xi)*(1+eta);
           9/32*(1-xi)*(1-eta^2)*(1+1/3*eta);
           9/32*(1-xi)*(1-eta^2)*(1-1/3*eta)];

 naturalDerivatives=...
       [9/16*(1-eta)*(1-xi)*xi-(1/32)*(1-eta)*(-10+9*(eta^2+xi^2)),9/16*(1-eta)*eta*(1-xi)-1/32*(1-xi)*(-10+9*(eta^2+xi^2));
        9/16*(1-eta)*xi*(1+xi)+(1/32)*(1-eta)*(-10+9*(eta^2+xi^2)),9/16*(1-eta)*eta*(1+xi)-(1/32)*(1+xi)*(-10+9*(eta^2+xi^2)) ;
        9/16*(1+eta)*xi*(1+xi)+(1/32)*(1+eta)*(-10+9*(eta^2+xi^2)),9/16*eta*(1+eta)*(1+xi)+(1/32)*(1+xi)*(-10+9*(eta^2+xi^2)) ;
        9/16*(1+eta)*(1-xi)*xi-(1/32)*(1+eta)*(-10+9*(eta^2+xi^2)),9/16*eta*(1+eta)*(1-xi)+(1/32)*(1-xi)*(-10+9*(eta^2+xi^2)) ;
        -(9/16)*(1-eta)*(1-3*xi)*xi-(27/32)*(1-eta)*(1-xi^2),-(9/32)*(1-3*xi)*(1-xi^2);
        -(9/16)*(1-eta)*xi*(1+3*xi)+(27/32)*(1-eta)*(1-xi^2),-(9/32)*(1+3*xi)*(1-xi^2);
        (9/32)*(1-3*eta)*(1-eta^2),-(9/16)*(1-3*eta)*eta*(1+xi)-(27/32)*(1-eta^2)*(1+xi);
        (9/32)*(1+3*eta)*(1-eta^2),-(9/16)*eta*(1+3*eta)*(1+xi)+(27/32)*(1-eta^2)*(1+xi);
        -(9/16)*(1+eta)*xi*(1+3*xi)+(27/32)*(1+eta)*(1-xi^2),(9/32)*(1+3*xi)*(1-xi^2);
        -(9/16)*(1+eta)*(1-3*xi)*xi-(27/32)*(1+eta)*(1-xi^2),(9/32)*(1-3*xi)*(1-xi^2);
        -(9/32)*(1+3*eta)*(1-eta^2),-(9/16)*eta*(1+3*eta)*(1-xi)+(27/32)*(1-eta^2)*(1-xi);
        -(9/32)*(1-3*eta)*(1-eta^2),-(9/16)*(1-3*eta)*eta*(1-xi)-(27/32)*(1-eta^2)*(1-xi)];

    end % end function shapeFunctionQ12


function [EVec, Eload, EVal] = pca_calc(vecs);
%
%  PCA_CALC   Principal Component Analysis
%
%   [EVEC, ELOAD, EVAL] = PCA_CALC(X) takes a column-wise de-meaned
%       data matrix X of size n-by-m and calculates the n
%       Eigenvectors (EVEC of size n-by-n) of the data covariance
%       matrix, the factor loadings (ELOAD of size n-by-m) and the
%       corresponding Eigenvalues (EVAL of size n-by-1).
%
%
% Author: Rami K. Niazy, FMRIB Centre, University of Oxford
%
% Copyright (c) 2004 University of Oxford.
%

[m,n]=size(vecs);
[Us,S,EVec] = svd(vecs,0);

if m == 1
    S = S(1);
else
    S = diag(S);
end
Eload = Us .* repmat(S',m,1);
S = S ./ sqrt(m-1);
if m <= n
    S(m:n,1) = 0;
    S(:,m:n) = 0;
end
EVal = S.^2;


function lagrange_interp_1d_test03 ( prob, m, nd )

%*****************************************************************************80
%
%% LAGRANGE_INTERP_1D_TEST03 tests LAGRANGE_APPROX_1D with Chebyshev spaced data.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROB, the problem index.
%
%    Input, integer M, the polynomial approximant degree.
%
%    Input, integer ND, the number of data points.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'LAGRANGE_INTERP_1D_TEST03:\n' );
  fprintf ( 1, '  Approximate Chebyshev-spaced data from TEST_INTERP_1D problem #%d.\n', prob );
  fprintf ( 1, '  Use polynomial approximant of degree %d.\n', m );
  fprintf ( 1, '  Number of data points = %d\n', nd );

  a = 0.0;
  b = 1.0;
  xd = r8vec_chebyspace ( nd, a, b );

  yd = p00_f ( prob, nd, xd );

  if ( nd < 10 )
    r8vec2_print ( nd, xd, yd, '  Data array:' );
  end
%
%  #1:  Does interpolant match function at interpolation points?
%
  ni = nd;
  xi = xd;
  yi = lagrange_approx_1d ( m, nd, xd, yd, ni, xi );

  int_error = norm ( yi - yd ) / ni;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  L2 approximation error averaged per data node = %g\n', int_error );
%
%  #2: Plot the piecewise linear interpolant and polynomial approximants.
%
  figure ( 1 );
  clf
  ni = 501;
  xi = r8vec_linspace ( ni, a, b );
  yi = lagrange_approx_1d ( m, nd, xd, yd, ni, xi );

  hold on
  plot ( xd, yd, 'k.', 'Markersize', 30 );
  plot ( xd, yd, 'b-', 'Linewidth', 3 );
  plot ( xi, yi, 'r-', 'Linewidth', 4 );
  xlabel ( '<--- X --->' );
  ylabel ( '<--- Y --->' );
  title ( sprintf ( 'Lagrange/Chebyshev Polynomial Approximant of degree %d for %d nodes', m, nd ) )
  grid on
  hold off

  filename = sprintf ( 'p%02d_lagcheby_%02d_%02d.png', prob, m, nd );
  print ( '-dpng', filename );
  fprintf ( 1, '  Created plot file "%s".\n', filename );

  return
end


function [ res, jac ] = opt07_rj ( x, flag )

%*****************************************************************************80
%
%% OPT07_RJ evaluates RES and JAC for test case #7.
%
%  Discussion:
%
%    This example is known as the helical valley function.
%
%    The optimizing value is
%
%      X* = (1,0,0)
%
%    for which
%
%      RES(X*) = (0,0,0).
%
%  Modified:
%
%    07 January 2008
%
%  Author:
%
%    Jeff Borggaard,
%    Gene Cliff,
%    Virginia Tech.
%
%  Reference:
%
%    John Dennis, Robert Schnabel,
%    Numerical Methods for Unconstrained Optimization
%    and Nonlinear Equations,
%    SIAM, 1996,
%    ISBN13: 978-0-898713-64-0,
%    LC: QA402.5.D44.
%
%  Parameters:
%
%    Input, real X(3), the evaluation point.
%
%    Input, string FLAG, indicates what must be computed.
%    'f' means only the value of RES is needed,
%    'g' means only the value of JAC is needed,
%    'all' means RES and JAC are needed.
%    It is acceptable to behave as though FLAG was 'all'
%    on every call.
%
%    Output, real RES(3,1), the function column vector.
%
%    Output, real JAC(3,3), the Jacobian matrix.
%
  n = length ( x );

  if ( n ~= 3 )
    fprintf ( '\n' );
    fprintf ( 'OPT07_RJ - Fatal error!\n' );
    fprintf ( '  The input vector X should have length 3.\n'),
    fprintf ( '  Instead, it has length = %d.\n', n );
    keyboard
  end

  if ( 0 < x(1) )
    theta = atan ( x(2) / x(1) ) / ( 2 * pi );
  elseif ( x(1) < 0 )
    theta = atan ( x(2) / x(1) ) / ( 2 * pi ) + 0.5;
  elseif ( 0 < x(2) )
    theta = 0.25;
  elseif ( x(2) < 0 )
    theta = - 0.25;
  else
    theta = 0;
  end

  res = zeros(3,1);

  res(1,1) = 10 * ( x(3) - 10 * theta );
  res(2,1) = 10 * ( sqrt ( x(1)^2 + x(2)^2 ) - 1 );
  res(3,1) = x(3);

  if ( x(1)^2 + x(2)^2 == 0 )
    dtdx1 = 0;
    dtdx2 = 0;
  else
    dtdx1 = - x(2) / ( 2 * pi * ( x(1)^2 + x(2)^2 ) );
    dtdx2 =   x(1) / ( 2 * pi * ( x(1)^2 + x(2)^2 ) );
  end

  jac = zeros(3,3);

  jac(1,1) = -100 * dtdx1;
  jac(1,2) = -100 * dtdx2;
  jac(1,3) = 10;

  if ( x(1)^2 + x(2)^2 == 0 )
    jac(2,1) = 0;
    jac(2,2) = 0;
  else
    jac(2,1) = 10 * x(1) / sqrt ( x(1)^2 + x(2)^2 );
    jac(2,2) = 10 * x(2) / sqrt ( x(1)^2 + x(2)^2 );
  end
  jac(2,3) = 0;

  jac(3,1) = 0;
  jac(3,2) = 0;
  jac(3,3) = 1;


function [tetIsoIndex]=tetIsotropyIndex(E,V)
%% function for computing  triangular faces isotropy index.
% This is an index of the  "regularity" of the triangle. Equilateral triangle (perfectly regular)
%
% INPUTS:
% * E: nElements-by-4 array representing the list of vertices for tetrahedral elements
% * V: nVertices-by-3 array representing the 3D positions of the vertices of E
%
% OUTPUTS:
% * tetIsoIndex: isotropy index for each element. value of 1 means
% perfectly isotropic (equilateral tetrahedron). value of 0 means vertices are coplanar.
%
%From the paper: Surface-Marker Cluster Design Criteria for 3-D Bone Movement Reconstruction (1997)
% Aurelio Cappozzo, Angelo Cappello, Ugo Della Croce, and Francesco Pensalfini
%%

tetIsoIndex=zeros(size(E,1),1);
for itet=1:size(E,1)

    x1=V(E(itet,1),:)';
    x2=V(E(itet,2),:)';
    x3=V(E(itet,3),:)';
    x4=V(E(itet,3),:)';

    if any(any(isnan([x1 x2 x3 x4]))) % if any nan, iso index=nan
        tetIsoIndex(itet)=NaN;
    else
        xa=(x1+x2+x3+x4)/3;
        X=[x1-xa,x2-xa,x3-xa,x4-xa]; %cluster position model
        K=X*X'/4;
        Keig=real(eig(K)); %eigenvalues of X
        tetIsoIndex(itet)=3*Keig(1)/(Keig(1)+Keig(2)+Keig(3)); % isotropy index
    end
end

end

%%
% MultiDIC: a MATLAB Toolbox for Multi-View 3D Digital Image Correlation
%
% License: <https://github.com/MultiDIC/MultiDIC/blob/master/LICENSE.txt>
%
% Copyright (C) 2018  Dana Solav
%
% If you use the toolbox/function for your research, please cite our paper:
% <https://engrxiv.org/fv47e>


function sp=orthpoly(n,opfamily,alpha,beta)
% orthpoly: generate an n'th order (symbolic) orthogonal polynomial
% usage: sp=orthpoly(n,opfamily,alpha,beta);
%
% arguments: (input)
%  n        - order of polynomial requested
%
%  opfamily - (OPTIONAL) character string - specifies the
%             type of orthogonal polynomial to be generated.
%             Legal polytypes are: {'legendre', 'hermite',
%             '1cheby', '2cheby', 'laguerre', 'jacoby'}
%
%             Default == 'legendre'
%
%             Note: 1cheby refers to first kind
%             chebychev polynomials (Tn(x)),
%             and 2cheby refers to second kind
%             chebychev polynomials (Un(x))
%
%             The domain of support is [-1,1] for the polynomial
%             families 'legendre', '1cheby', '2cheby', 'jacoby'.
%             It is [0,inf] for 'laguerre', and [-inf,inf] for
%             the 'hermite' family.
%
%             See Abramowitz & Stegun for in-depth information
%             on all of these polynomial families.
%
%  alpha,beta - scalar - orthogonal family parameters -
%             See Abramowitz & Stegun for more information.
%
%             These parameters are ignored for 'legendre',
%             'hermite', '1cheby' and '2cheby' polys.
%
% arguments: (output)
%  p        - sympoly object containing the polynomial

% defaults
if (nargin<2)|isempty(opfamily)
  % default is legendre
  opfamily = 'legendre';
else
  if ~ischar(opfamily)
    error 'Opfamily must be a character string'
  end
  valtypes = {'legendre', 'hermite', 'cheby1', '1chebychev' ...
            'cheby2', '2chebychev', 'laguerre', 'jacobi'};

  ptind = strmatch(opfamily,valtypes);
  if isempty(ptind)
    % no match
    error 'Invalid opfamily'
  elseif length(ptind)>1
    % match more than one
    error 'Ambiguous opfamily'
  else
    % there was exactly one match
    opfamily = valtypes{ptind};
  end
end

if nargin<1
  error 'Polynomial order must be supplied. No default for n.'
end

if (nargin<3) || isempty(alpha)
  % default is 0
  alpha = 0;
end

if (nargin<4) || isempty(beta)
  % default is 0
  beta = 0;
end

% initialize (-1)'th and zero'th order sympolys
% for the three term recurrence relation.
pnm1=sympoly(0);
pn=sympoly(1);
x=sympoly('x');

if n==0
  % p0 is easy to get
  sp=pn;
  return
elseif n<0
  error 'Polynomial order must not be negative'
end

% iterate to get polynomial
for i=0:(n-1)
  switch opfamily
    case 'legendre'
      pnp1=((2*i+1)*x*pn - i*pnm1)./(i+1);
      % normalize so that Tn(1)=1
      pnp1=pnp1./double(subs(pnp1,'x',1));

    case 'hermite'
      % neither alpha nor beta is meaningful
      pnp1=2*pn*x - 2*i*pnm1;

    case 'laguerre'
      % only alpha is meaningful here
      pnp1=((2*i+alpha+1)*pn - pn*x - (i+alpha)*pnm1)./(i+1);

    case {'cheby1' '1chebychev'}
      % first kind chebychev
      % neither alpha nor beta is meaningful
      pnp1=(2*pn*x - pnm1);
      % normalize so that Tn(1)=1
      pnp1=pnp1/double(subs(pnp1,'x',1));

    case {'cheby2' '2chebychev'}
      % second kind chebychev
      % neither alpha nor beta is meaningful
      pnp1=(2*pn*x - pnm1);

    case 'jacobi'
      % both alpha and beta are needed
      if (alpha~=0) | (beta~=0)
        a1n=2*(i+1)*(i+alpha+beta+1)*(2*i+alpha+beta);
        a2n=(2*i+alpha+beta+1)*(alpha^2-beta^2);
        if (2*i+alpha+beta)<=150
          a3n=gamma(2*i+alpha+beta+3)./gamma(2*i+alpha+beta);
        else
          a3n=exp(gammaln(2*i+alpha+beta+3)-gammaln(2*i+alpha+beta));
        end
        a4n=2*(i+alpha)*(i+beta)*(2*i+alpha+beta+2);
        pnp1=(a2n*pn + a3n*pn*x - a4n*pnm1)/a1n;
      else
        pnp1=((2*i+1)*pn*x - i*pnm1)/(i+1);
      end
  end
  pnm1=pn;
  pn=pnp1;

end

% return the generated sympoly
sp=pnp1;


%% Generating the leading mode-n vectors
% The leading mode-n vectors are those vectors that span the subspace of
% the mode-n fibers. In other words, the left singular vectors of the
% n-mode matricization of X.
%% Using nvecs to calculate the leading mode-n vectors
% The |nvecs| command efficient computes the leading n-mode vectors.
rand('state',0);
X = sptenrand([4,3,2],6) %<-- A sparse tensor
%%
nvecs(X,1,2) %<-- The 2 leading mode-1 vectors
%%
nvecs(X,1,3) % <-- The 3 leading mode-1 vectors
%%
nvecs(full(X),1,3) %<-- The same thing for a dense tensor
%%
X = ktensor({rand(3,2),rand(3,2),rand(2,2)}) %<-- A random ktensor
%%
nvecs(X,2,1) %<-- The 1 leading mode-2 vector
%%
nvecs(full(X),2,1) %<-- Same thing for a dense tensor
%%
X = ttensor(tenrand([2,2,2,2]),{rand(3,2),rand(3,2),rand(2,2),rand(2,2)}); %<-- A random ttensor
%%
nvecs(X,4,2) %<-- The 1 leading mode-2 vector
%%
nvecs(full(X),4,2) %<-- Same thing for a dense tensor
%% Using nvecs for the HOSVD
X = tenrand([4 3 2]) %<-- Generate data
%%
U1 = nvecs(X,1,4); %<-- Mode 1
U2 = nvecs(X,2,3); %<-- Mode 2
U3 = nvecs(X,3,2); %<-- Mode 3
S = ttm(X,{pinv(U1),pinv(U2),pinv(U3)}); %<-- Core
Y = ttensor(S,{U1,U2,U3}) %<-- HOSVD of X
%%
norm(full(Y) - X) %<-- Reproduces the same result.

%%
U1 = nvecs(X,1,2); %<-- Mode 1
U2 = nvecs(X,2,2); %<-- Mode 2
U3 = nvecs(X,3,2); %<-- Mode 3
S = ttm(X,{pinv(U1),pinv(U2),pinv(U3)}); %<-- Core
Y = ttensor(S,{U1,U2,U3}) %<-- Rank-(2,2,2) HOSVD approximation of X
%%
100*(1-norm(full(Y)-X)/norm(X)) %<-- Percentage explained by approximation


function val=cosInt(x)
%%COSINT Evaluate the cosine integral of a real non-negative value x. The
%        cosine integral of x is defined to be the negative of the integral
%        from x to infinity of cos(t)/t dt. The derivative of the cosine
%        integral function is cos(x)/x.
%
%INPUTS:    x A matrix of non-negative real values, at which one wishes to
%             evaluate the cosine integral. x does not have to be finite.
%
%OUTPUTS: val A matrix of the real values of the cosine integral evaluated
%             at the points in x.
%
%The cosine integral can be related to the exponential integral as
%discussed in [1]. This function uses Matlab's built-in expint function to
%evaluate the cosine integral using the expint function.
%
%The cosine integral asymptotically approaches zero. If the results from
%the exponential integral functions are not finite, then it is assumed that
%the corresponding values of x were too large and the asymptotic result (0)
%is substituted.
%
%x should be non-negative. If negative values of x are (incorrectly)
%provided, then the value of cosInt(abs(x)) is returned. Strict definitions
%of the cosine integral are usually such that negative values return
%complex numbers.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Cosine Integral." From MathWorld--A Wolfram Web
%    Resource. http://mathworld.wolfram.com/CosineIntegral.html
%
%June 2014 David F.Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

    %The real function is in case of finite precision problems.
    val=-0.5*real(expint(1j*x)+expint(-1j*x));
    val(~isfinite(val))=0;

    %Make sure that NaN inputs remain NaN on the output.
    val(isnan(x))=NaN;
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function value = r8vec_diff_norm ( n, a, b )

%*****************************************************************************80
%
%% R8VEC_DIFF_NORM returns the L2 norm of the difference of R8VEC's.
%
%  Discussion:
%
%    The vector L2 norm is defined as:
%
%      value = sqrt ( sum ( 1 <= I <= N ) A(I)**2 ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in A.
%
%    Input, real A(N), B(N), the vectors.
%
%    Output, real VALUE, the L2 norm of A - B.
%
  value = norm ( a(1:n) - b(1:n) );

  return
end


function [ f, g, H ] = opt02_fgh ( x, flag )

%*****************************************************************************80
%
%% OPT02_FGH evaluates F, G and H for test case #2.
%
%  Discussion:
%
%    This example is discussed in Dennis and Schnabel, pages 120 and 138.
%
%    A suggested initial value for X is
%
%      X init = ( 1, 1 ).
%
%    The optimizing value is
%
%      X* = ( 0, 0 )
%
%    and the optimal function value is
%
%      F(X*) = 0.
%
%  Modified:
%
%    02 January 2008
%
%  Author:
%
%    Jeff Borggaard,
%    Gene Cliff,
%    Virginia Tech.
%
%  Reference:
%
%    John Dennis, Robert Schnabel,
%    Numerical Methods for Unconstrained Optimization
%    and Nonlinear Equations,
%    SIAM, 1996,
%    ISBN13: 978-0-898713-64-0,
%    LC: QA402.5.D44.
%
%  Parameters:
%
%    Input, real X(2), the evaluation point.
%
%    Input, string FLAG, indicates what must be computed.
%    'f' means only the value of F is needed,
%    'g' means only the value of G is needed,
%    'all' means F, G and H (if appropriate) are needed.
%    It is acceptable to behave as though FLAG was 'all'
%    on every call.
%
%    Output, real F, the optimization function.
%
%    Output, real G(2,1), the gradient column vector.
%
%    Output, real H(2,2), the Hessian matrix.
%
  n = length ( x );

  if ( n ~= 2 )
    fprintf ( '\n' );
    fprintf ( 'OPT02_FGH - Fatal error!\n' );
    fprintf ( '  The input vector X should have length 2.\n'),
    fprintf ( '  Instead, it has length = %d.\n', n );
    keyboard
  end

  f    = x(1)^4 + x(1)^2 + x(2)^2;

  g    = [ 4*x(1)^3 + 2*x(1); 2*x(2) ];

  H    = [ 12*x(1) + 2 ,   0    ;
                0      ,   2    ];

  return


function dist = sphere01_distance_xyz ( xyz1, xyz2 )

%*****************************************************************************80
%
%% SPHERE01_DISTANCE_XYZ computes great circle distances on a sphere.
%
%  Discussion:
%
%    XYZ coordinates are used.
%
%    We assume the points XYZ1 and XYZ2 lie on the same sphere.
%
%    This computation is a special form of the Vincenty formula.
%    It should be less sensitive to errors associated with very small
%    or very large angular separations.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    "Great-circle distance",
%    Wikipedia.
%
%  Parameters:
%
%    Input, real XYZ1(3), the coordinates of the first point.
%
%    Input, real XYZ2(3), the coordinates of the second point.
%
%    Output, real DIST, the great circle distance between the points.
%
  lat1 = r8_asin ( xyz1(3) );
  lon1 = r8_atan ( xyz1(2), xyz1(1) );

  lat2 = r8_asin ( xyz2(3) );
  lon2 = r8_atan ( xyz2(2), xyz2(1) );

  top = ( cos ( lat2 ) * sin ( lon1 - lon2 ) ).^2 ...
      + ( cos ( lat1 ) * sin ( lat2 ) ...
      -   sin ( lat1 ) * cos ( lat2 ) * cos ( lon1 - lon2 ) ).^2;

  top = sqrt ( top );

  bot = sin ( lat1 ) * sin ( lat2 ) ...
      + cos ( lat1 ) * cos ( lat2 ) * cos ( lon1 - lon2 );

  dist = atan2 ( top, bot );

  return
end


function [ num_int, p ] = circles_imp_int_2d ( r1, center1, r2, center2 )

%*****************************************************************************80
%
%% CIRCLES_IMP_INT_2D: finds the intersection of two implicit circles in 2D.
%
%  Discussion:
%
%    Two circles can intersect in 0, 1, 2 or infinitely many points.
%
%    The 0 and 2 intersection cases are numerically robust; the 1 and
%    infinite intersection cases are numerically fragile.  The routine
%    uses a tolerance to try to detect the 1 and infinite cases.
%
%    An implicit circle in 2D satisfies the equation:
%
%      ( X - CENTER(1) )**2 + ( Y - CENTER(2) )**2 = R**2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R1, the radius of the first circle.
%
%    Input, real CENTER1(2,1), the center of the first circle.
%
%    Input, real R2, the radius of the second circle.
%
%    Input, real CENTER2(2,1), the center of the second circle.
%
%    Output, integer NUM_INT, the number of intersecting points found.
%    NUM_INT will be 0, 1, 2 or 3.  3 indicates that there are an infinite
%    number of intersection points.
%
%    Output, real P(2,2), if NUM_INT is 1 or 2,
%    the coordinates of the intersecting points.
%
  dim_num = 2;

  tol = eps;

  p(1:dim_num,1:2) = 0.0;;
%
%  Take care of the case in which the circles have the same center.
%
  t1 = ( abs ( center1(1,1) - center2(1,1) ) ...
       + abs ( center1(2,1) - center2(2,1) ) ) / 2.0;

  t2 = ( abs ( center1(1,1) ) + abs ( center2(1,1) ) ...
       + abs ( center1(2,1) ) + abs ( center2(2,1) ) + 1.0 ) / 5.0;

  if ( t1 <= tol * t2 )

    t1 = abs ( r1 - r2 );
    t2 = ( abs ( r1 ) + abs ( r2 ) + 1.0 ) / 3.0;

    if ( t1 <= tol * t2 )
      num_int = 3;
    else
      num_int = 0;
    end

    return

  end

  distsq = sum ( ( center1(1:2,1) - center2(1:2,1) ).^2 );

  root = 2.0 * ( r1 * r1 + r2 * r2 ) * distsq - distsq * distsq ...
    - ( r1 - r2 ) * ( r1 - r2 ) * ( r1 + r2 ) * ( r1 + r2 );

  if ( root < -tol )
    num_int = 0;
    return
  end

  sc1 = ( distsq - ( r2 * r2 - r1 * r1 ) ) / distsq;

  if ( root < tol )
    num_int = 1;
    p(1:dim_num,1) = center1(1:dim_num,1) ...
      + 0.5 * sc1 * ( center2(1:dim_num,1) - center1(1:dim_num,1) );
    return
  end

  sc2 = sqrt ( root ) / distsq;

  num_int = 2;

  p(1,1) = center1(1,1) + 0.5 * sc1 * ( center2(1,1) - center1(1,1) ) ...
                        - 0.5 * sc2 * ( center2(2,1) - center1(2,1) );
  p(2,1) = center1(2,1) + 0.5 * sc1 * ( center2(2,1) - center1(2,1) ) ...
                        + 0.5 * sc2 * ( center2(1,1) - center1(1,1) );

  p(1,2) = center1(1,1) + 0.5 * sc1 * ( center2(1,1) - center1(1,1) ) ...
                        + 0.5 * sc2 * ( center2(2,1) - center1(2,1) );
  p(2,2) = center1(2,1) + 0.5 * sc1 * ( center2(2,1) - center1(2,1) ) ...
                        - 0.5 * sc2 * ( center2(1,1) - center1(1,1) );

  return
end


function value = r8vec_diff_norm_l1 ( n, a, b )

%*****************************************************************************80
%
%% R8VEC_DIFF_NORM_L1 returns the L1 norm of the difference of R8VEC's.
%
%  Discussion:
%
%    The vector L1 norm is defined as:
%
%      value = sum ( 1 <= I <= N ) abs ( A(I) ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in A.
%
%    Input, real A(N), B(N), the vectors.
%
%    Output, real VALUE, the L1 norm of A - B.
%
  value = sum ( abs ( a(1:n) - b(1:n) ) );

  return
end


function b = isPointOnLine3d(point, line, varargin)
%ISPOINTONLINE3D Test if a 3D point belongs to a 3D line.
%
%   B = isPointOnLine3d(POINT, LINE)
%   with POINT being [xp yp zp], and LINE being [x0 y0 z0 dx dy dz].
%   Returns 1 if point lies on the line, 0 otherwise.
%
%   If POINT is an N-by-3 array of points, B is a N-by-1 array of booleans.
%
%   If LINE is a N-by-6 array of lines, B is a N-by-1 array of booleans.
%
%   B = isPointOnLine3d(POINT, LINE, TOL)
%   Specifies the tolerance used for testing location on 3D line.
%
%   See also:
%   lines3d, distancePointLine3d, linePosition3d, isPointOnLine
%

% ---------
% author : David Legland
% e-mail: david.legland@inra.fr
% INRA - TPV URPOI - BIA IMASTE
% created the 31/10/2003.
%

%   HISTORY
%   17/12/2013 create from isPointOnLine

% extract computation tolerance
tol = 1e-14;
if ~isempty(varargin)
    tol = varargin{1};
end

% test if lines are colinear, using norm of the cross product
b = bsxfun(@rdivide, vectorNorm3d( ...
        crossProduct3d(bsxfun(@minus, line(:,1:3), point), line(:,4:6))), ...
        vectorNorm3d(line(:,4:6))) < tol;


function area = polygonArea(poly, varargin)
%POLYGONAREA Compute the signed area of a polygon.
%
%   A = polygonArea(POINTS);
%   Compute area of a polygon defined by POINTS. POINTS is a N-by-2 array
%   of double containing coordinates of vertices.
%
%   Vertices of the polygon are supposed to be oriented Counter-Clockwise
%   (CCW). In this case, the signed area is positive.
%   If vertices are oriented Clockwise (CW), the signed area is negative.
%
%   If polygon is self-crossing, the result is undefined.
%
%   Examples
%     % compute area of a simple shape
%     poly = [10 10;30 10;30 20;10 20];
%     area = polygonArea(poly)
%     area =
%         200
%
%     % compute area of CW polygon
%     area2 = polygonArea(poly(end:-1:1, :))
%     area2 =
%         -200
%
%     % Computes area of a paper hen
%     x = [0 10 20  0 -10 -20 -10 -10  0];
%     y = [0  0 10 10  20  10  10  0 -10];
%     poly = [x' y'];
%     area = polygonArea(poly)
%     area =
%        400
%
%     % Area of unit square with 25% hole
%     pccw = [0 0; 1 0; 1 1; 0 1];
%     pcw = pccw([1 4 3 2], :) * .5 + .25;
%     polygonArea ([pccw; nan(1,2); pcw])
%     ans =
%        0.75
%
%   References
%   algo adapted from P. Bourke web page
%   http://paulbourke.net/geometry/polygonmesh/
%
%   See also:
%   polygons2d, polygonCentroid, polygonSecondAreaMoments, triangleArea
%

%   ---------
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 05/05/2004.
%

%   HISTORY
%   25/04/2005: add support for multiple polygons
%   12/10/2007: update doc

%% Process special cases

% in case of polygon sets, computes the sum of polygon areas
if iscell(poly)
    area = 0;
    for i = 1:length(poly)
        area = area + polygonArea(poly{i});
    end
    return;
end

% check there are enough points
if size(poly, 1) < 2
    area = 0;
    return;
end

% case of polygons with holes -> computes the sum of areas
if any(isnan(poly))
    area = sum(polygonArea(splitPolygons(poly)));
    return;
end

%% Process single polygons or single rings

% extract coordinates
if nargin == 1
    % polygon given as N-by-2 array
    px = poly(:, 1);
    py = poly(:, 2);

elseif nargin == 2
    % poylgon given as two N-by-1 arrays
    px = poly;
    py = varargin{1};
end

% indices of next vertices
N = length(px);
iNext = [2:N 1];

% compute area (vectorized version)
area = sum(px .* py(iNext) - px(iNext) .* py) / 2;


function [ i_choose, w_choose ] = subset_sum_task ( weights, target, range )

%*****************************************************************************80
%
%% SUBSET_SUM_TASK seeks a subset of a set that has a given sum.
%
%  Discussion:
%
%    This function tries to compute a target value as the sum of
%    a selected subset of a given set of weights.
%
%    This function works by brute force, that is, it tries every
%    possible subset to see if it sums to the desired value.
%
%    Given N weights, every possible selection can be described by
%    one of the N-digit binary numbers from 0 to 2^N-1.
%
%    This function includes a range, which allows the user to
%    control which subsets are to be checked.  Thus, if there are
%    N weights, specifying a range of [ 0, 2^N-1] indicates that
%    all subsets should be checked.  On the other hand, this full
%    range could be broken down into smaller subranges, each of
%    which could be checked independently.
%
%    It is possible that, in the given range, there may be multiple
%    solutions of the problem.  This function will only return
%    one such solution, if found.
%
%  Example:
%
%    [ c, wv ] = subset_sum_task ( [1 2 4 8 16 32], 22, [0 2^6 - 1] )
%
%    c = 2 3 5
%    wv = 2 4 16
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 May 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer WEIGHTS(N), a set of weights.
%
%    Input, integer TARGET, the target value.
%
%    Input, integer RANGE(2), the lower and upper limits to be searched.
%
%    Output, integer I_CHOOSE(K), the indices of the chosen weights.
%
%    Output, integer W_CHOOSE(K), the values of the chosen weights.
%

%
%  Initialize the output to empty matrices.
%
  i_choose = [];
  w_choose = [];
%
%  Iterate through all possible combinations in the provided range.
%
  n = length ( weights );

  for i = range(1) : range(2)
%
%  Find the combination of weights represented by the current attempt.
%
    choose = find ( bitget ( i, 1:n ) );
%
%  If the sum of those weights matches the target, return combination.
%
    if ( sum ( weights(choose) ) == target )
      i_choose = choose;
      w_choose = weights(choose);
      return
    end

  end

  return
end


%% 1D Linear Advection Equation
%
% du/dt + a du/dx = 0
%
% Ref's:
%   Randall J. Leveque;
%   Finite Volume Methods for Hyperbolic Problems
%   Cambridge Press, 2002.
%
% Subroutine for solving using Upwind Method.
% by Manuel Diaz, manuel.ade'at'gmail.com
% Institute of Applied Mechanics, 2012.08.12

clear all; close all; clc;

%% Parameters
a = 0.5;
a_m = min(0,a);
a_p = max(0,a);
dx = 0.01;
cfl = 0.9;
dt = cfl*dx/abs(a);
t_end = 0.6;

%% Discretization of Domain
x = 1:dx:2;
t = 0:dt:t_end;

%% Initial Condition
n = length(x);
%u_0 = zeros(1,n);
u0(1:ceil(n/2)) = 1;
u0((ceil(n/2)+1):n) = 2;

%% Main Loop
% Initilize vector variables
u_next = zeros(size(u0)); % u^{n+1}
u_bar1 = zeros(size(u0)); % preallocate for MacCormack
u_bar2 = zeros(size(u0)); % preallocate for MacCormack

% Load Initial condition
u = u0;

% Main Loop
for k = t
    % plot every time step
    plot(x,u,'.')

    for j = 2:n-1
        % Single Sided Upwind
        %u_next(j) = u(j) - a*dt/dx*(u(j)-u(j-1)); % Upwind
        %u_next(j) = u(j) - a*dt/dx*(u(j+1)-u(j)); % Downwind

        % Double Sided Upwind
        u_next(j) = u(j) - a_p*dt/dx*(u(j)-u(j-1)) - a_m*dt/dx*(u(j+1)-u(j));

        % Comparing to Lax-Wendroff:
        %u_next(j) = u(j) - a*dt/(2*dx)*(u(j+1)-u(j-1)) ...
        %   +(dt^2/2)/(dx^2)*(a^2)*(u(j+1)-2*u(j)+u(j-1)); % LW

        % Comparing to MacCormack Method:
        % Predictor steps
        %u_bar1(j) = u(j) - a*dt/dx*(u(j+1)-u(j));
        %    u_bar1(1) = u_bar1(2); % Neumann BC in predictor step
        %u_bar2(j) = u_bar1(j) - a*dt/dx*(u_bar1(j)-u_bar1(j-1));
        % Corrector step
        %u_next(j) = 1/2*(u(j)+u_bar2(j));
    end
    % BC
    u_next(1) = u_next(2);      % Neumann BC
    u_next(n) = u_next(n-1);    % Neumann BC

    % UPDATE info
    u = u_next(1:n);

    % update figure
    pause(0.05); drawnow
end

%% Plot final Result
plot(x,u,'.')


function C = hcp_lattice(I,J,K)
  % HCP_LATTICE generate the center locations of a hexagonal close-packed
  % lattice of unit-radius spheres.
  %
  % Inputs:
  %   I  #I list of x-coordinate indices
  %   J  #I list of y-coordinate indices
  %   K  #I list of z-coordinate indices
  % Outputs:
  %   C  #I by 3 list of center locations
  %
  % Example:
  %   [I,J,K] = meshgrid(0:9,0:9,0:9);
  %   C = hcp_lattice(I(:),J(:),K(:));
  %   [SV,SF] = lloyd_sphere(300);
  %   [V,F] = repmesh(SV,SF,C);
  i = I(:);
  j = J(:);
  k = K(:);
  % https://en.wikipedia.org/wiki/Close-packing_of_equal_spheres#Simple_hcp_lattice
  C = [2*i + mod(j+k,2), sqrt(3)*(j+1/3*mod(k,2)), 2*sqrt(6)/3*k];
end


function areRPrime=areRelativelyPrime(a)
%%ARERELATIVELYPRIME Determine whether a set of numbers is relatively
%               prime (are coprime). A collections of numbers are
%               relatively prime if the greatest common divisor between all
%               pairs of the numbers is 1. Relatively prime numbers are
%               also known as coprime numbers.
%
%INPUTS: a An nXnumSets set of numSets sets of n-integers where one wishes
%          to determine whether the n numbers in each set are relatively
%          prime.
%
%OUTPUTS: areRPrime A numSetsX1 boolean array indicating whether the
%                   numbers in each set are coprime.
%
%Coprime numbers arise in a number of areas, such as in the Chinese
%remainder theorem. This function jst goes through all pairs of numbers and
%uses the gcd function to see whether the greatest common divisor between
%all pairs is 1.
%
%EXAMPLE:
% a=zeros(3,2);
% %This set of numbers is coprime even though 4 is not a prime number.
% a(:,1)=[7;9;4];
% %This set of numbers is not coprime
% a(:,2)=[3;2;9];
% areRPrime=areRelativelyPrime(a)
%The functions returns [1;0]
%
%September 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

N=size(a,1);
numSets=size(a,2);

areRPrime=true(numSets,1);

for curSet=1:numSets
    for n1=1:(N-1)
        for n2=(n1+1):N
            if(gcd(a(n1,curSet),a(n2,curSet))~=1)
                areRPrime(curSet)=false;
                break;
            end
        end

        if(areRPrime(curSet)~=true)
            break;
        end
    end
end
end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function [out] = Combination(n, k)
% Produces the array of combinations possible picking k from n
% adapted from Combinadics
% http://msdn.microsoft.com/en-us/library/aa289166(VS.71).aspx
%
% USAGE:
%
%    [out] = Combination(n, k)
%
% INPUTS:
%    n:      number of elements in the pool
%    k:      number of elements to pick from `n`
%
% OUTPUT:
%    out:    array of combinations

    if (n < 0 || k < 0) % normally n >= k
      disp('Negative parameter in constructor');
      out = [];
      return
    end

    data(k) = 0;
    for i = 1:k;
      data(i) = i;
    end
   % Combination(n,k)
    out.choose = getNumberCombinations(n,k);

   % determine the combinations
   for i = 1:out.choose
       out.all(:,i) = getCombination(n,k,i-1);
   end
return;

function [m] = getNumberCombinations(n,k)
   % find number of combinations by choose k items from n
    if (n < k)
      m = 0;  % special case
    else
        if (n == k)
            m = 1;
        else
            m = factorial(n) / (factorial(k) * factorial(n-k));
        end
    end

return;

function [c] = getCombination(n,k,index)
    c(1) = 1;
    x = 1;
    for i = 1:n
        if (k == 0)
            return;
        end

        threshold = getNumberCombinations(n-i,k-1);
        %disp(sprintf('index = %d, threshold = %d',index,threshold));
        if (index < threshold)
            c(x) = i;
            x = x+1;
            k = k-1;
        else
            if (index >= threshold)
                index = index - threshold;
            end
        end
    end
return;


% Find cycles of length 4 in a graph;
% Note: Valid for an undirected graph only
%
% INPUTS: adjacency matrix
% OUTPUTS: number of 4-cycles, for which no edges repeat in the cycle

% Other routines used: numEdges.m, numConnTriples.m, cycles3.m
% GB: last updated January 28, 2016

function l4 = cycles4(adj)

	l4 = trace(adj^4) - 2*numEdges(adj) - 4*numConnTriples(adj) - 8*cycles3(adj);

	l4 = l4/8;


%% Solving LQR via SDP (LMIs)
% http://www1.se.cuhk.edu.hk/~zhang/Courses/Seg5660/Lecture%206.pdf

%% Continuous LQR
clc
Gs = tf(2,[0.5 0.2 0.1]);
[A,B] = ssdata(ss(Gs));
Q = diag([10;10]); R = 1;

[K,S] = lqr(A,B,Q,R)

%LQR LMI - Vars are P11 P12 P22
P = sym('[P11 P12; P12 P22]')
Lp = vpa([R B'*P; P*B Q + A'*P + P*A],5)

% Objective (max)
f = -[1 0 1]; %just diagonal elements

% Semidefinite Constraint (cheap way to pick off elements)
C = -double(subs(Lp,P,zeros(2)));
A1 = double(diff(Lp,P(1)));
A2 = double(diff(Lp,P(2)));
A3 = double(diff(Lp,P(end)));
sdcone = sparse([C(:) A1(:) A2(:) A3(:)]);

% Create OPTI Object
Opt = opti('f',f,'sdcone',sdcone)
% Solve the SDP
x = solve(Opt)

%Reform P and solve K
P = [x(1) x(2); x(2) x(3)];
Ksdp = R\(B'*P) %see help lqr

%% Discrete LQR
clc
Gd = c2d(Gs,0.1);
[A,B] = ssdata(ss(Gd));
Q = diag([10;10]); R = 1;

[K,S] = dlqr(A,B,Q,R)

%LQR LMI - Vars are P11 P12 P22
P = sym('P',[2 2]);
Lp = vpa([B'*P*B+R B'*P*A; A'*P*B Q + A'*P*A - P],5)

% Objective (max)
f = -[1 0 1]; %just diagonal elements

% Semidefinite Constraint (cheap way to pick off elements)
C = -double(subs(Lp,P,zeros(2)));
A1 = double(diff(Lp,P(1)));
A2 = double(diff(Lp,P(2))) + double(diff(Lp,P(3)));
A3 = double(diff(Lp,P(end)));

sdcone = sparse([C(:) A1(:) A2(:) A3(:)]);

% Create OPTI Object
Opt = opti('f',f,'sdcone',sdcone)
% Solve the SDP
x = solve(Opt)

%Reform P and solve K
P = [x(1) x(2); x(2) x(3)];
Ksdp = (B'*P*B + R)\(B'*P*A) %see help dlqr

%% Continuous Lyapunov
clc
[A,B] = ssdata(ss(Gs));
X = lyap(A,Q)

%LYAP LMI - Vars are P11 P12 P22
P = sym('P',[2 2]);
Lp = vpa(A*P + P*A' + Q)

% Objective (max)
f = -[1 1 1]; %just diagonal elements

% Semidefinite Constraint (cheap way to pick off elements)
C = -double(subs(Lp,P,zeros(2)));
A1 = double(diff(Lp,P(1)));
A2 = double(diff(Lp,P(2))) + double(diff(Lp,P(3)));
A3 = double(diff(Lp,P(end)));

sdcone = sparse([C(:) A1(:) A2(:) A3(:)]);

% Create OPTI Object
Opt = opti('f',f,'sdcone',sdcone,'solver','dsdp')
% Solve the SDP
[x,f,e,i] = solve(Opt)
P = [x(1) x(2); x(2) x(3)];

A*P + P*A' + Q
A*X + X*A' + Q

%% Discrete Lyapunov
clc
[A,B] = ssdata(ss(Gd));
X = dlyap(A,Q)

%LYAP LMI - Vars are P11 P12 P22
P = sym('P',[2 2]);
Lp = vpa(A*P*A' - P + Q)

% Objective (max)
f = -[1 1 1]; %just diagonal elements

% Semidefinite Constraint (cheap way to pick off elements)
C = -double(subs(Lp,P,zeros(2)));
A1 = double(diff(Lp,P(1)));
A2 = double(diff(Lp,P(2))) + double(diff(Lp,P(3)));
A3 = double(diff(Lp,P(end)));

sdcone = sparse([C(:) A1(:) A2(:) A3(:)]);

% Create OPTI Object
Opt = opti('f',f,'sdcone',sdcone,'solver','dsdp')
% Solve the SDP
[x,f,e,i] = solve(Opt)
P = [x(1) x(2); x(2) x(3)];

A*P*A' - P + Q
A*X*A' - X + Q


function R = sep(varargin);
% SEP - An Algorithm for Converting Covariance to Spherical Error Probable
%
% Version 1.0
%
% Copyright 2004, Michael Kleder
%
% USAGE:
%
% R = sep(sx,sy,sz)
% R = sep(sx,sy,sz,prob)
%
% This function computes Spherical Error Probable radius from inputs consisting of the
% square roots of the eigenvalues of a covariance matrix (equivalently, from sigma-x,
% sigma-y, and sigma-z, of a trivariate normal distribution in a coordinate system
% where there is no cross-correlation between variables.) This means that if you have
% a covariance matrix and wish to compute the S.E.P., simply obtain the square roots
% of the eigenvalues and use these as inputs. For example, list them via "sqrt(eig(C))"
% where C is your covariance matrix.
%
% The S.E.P. is the radius of a sphere which contains a fraction of probability equal
% to the input "prob," which is asumed to be 0.5 if omitted.
%
% Note: if one of the input sigmas is significantly smaller than both others,
% calculation time may rise.
%
% By uncommenting a labeled line of code, the user can enter a diagnostic mode
% to verify the accuracy of this algorithm for whatever inputs are specified.
%
% The mathematical formulas contained herein were created by the author and
% are copyrighted. Feel free to use them provided you credit the author:
% Kleder, Michael. "An Algorithm for Converting Covariance to Spherical Error Probable"
% Mathworks Central File Exchange, 2004.

[sx,sy,sz]=deal(varargin{1:3});
target = .5;
if nargin>3
    target=varargin{4};
end
lowend=0;
highend=10*max([sx sy sz]);
R = fminbnd(@enclosederr,lowend,highend,[],sx,sy,sz,target);
% diagnostic(R,sx,sy,sz) % use this to verify results against RANDN
return
function enclerr = enclosederr(R,sx,sy,sz,target)
enclerr=dblquad(@dens,0,pi,0,2*pi,[],[],R,sx,sy,sz);
enclerr=(target-enclerr)^2;
return
function outp = dens(th,phi,R,sx,sy,sz)
sinth  = sin(th);
sinphi = sin(phi);
costh  = cos(th);
cosphi = cos(phi);
subexprA = sinth.^2.*cosphi.^2.*sy.^2.*sz.^2+sinth.^2.*...
    sinphi.^2.*sx.^2.*sz.^2+costh.^2.*sx.^2.*sy.^2;
subexprB = sx.*sy.*sz;
outp = -1./8.*sinth.*2.^(.5).*subexprB.*(2.*R.*exp(-.5.*subexprA.*...
    R.^2./subexprB.^2).*subexprA.^(.5)-pi.^(.5).*2.^(.5).*erf(.5.*...
    2.^(.5)./subexprB.*subexprA.^(.5).*R).*subexprB)./pi.^(1.5)./subexprA.^(1.5);
return
function diagnostic(R,sx,sy,sz)
disp('Running test of SEP.')
for i=10:-1:1
    fprintf('%g ',i);
    x=randn(1e6,1)*sx;;
    y=randn(1e6,1)*sy;
    z=randn(1e6,1)*sz;
    r=sqrt(sum([x y z].^2,2));
    m(i) = sum(r<R)/length(r);
end
disp(' ');
m=mean(m);
disp([num2str(m*100) ' percent of random points were located within the computed SEP.'])
return


function centroids = computeCentroids(X, idx, K)
%COMPUTECENTROIDS returs the new centroids by computing the means of the
%data points assigned to each centroid.
%   centroids = COMPUTECENTROIDS(X, idx, K) returns the new centroids by
%   computing the means of the data points assigned to each centroid. It is
%   given a dataset X where each row is a single data point, a vector
%   idx of centroid assignments (i.e. each entry in range [1..K]) for each
%   example, and K, the number of centroids. You should return a matrix
%   centroids, where each row of centroids is the mean of the data points
%   assigned to it.
%

% Useful variables
[m n] = size(X);

% You need to return the following variables correctly.
centroids = zeros(K, n);

% ====================== YOUR CODE HERE ======================
% Instructions: Go over every centroid and compute mean of all points that
%               belong to it. Concretely, the row vector centroids(i, :)
%               should contain the mean of the data points assigned to
%               centroid i.
%
% Note: You can use a for-loop over the centroids to compute this.
%

for i = 1:K
    centroids(i,:) = mean(X(idx==i,:),1);
end

% =============================================================

end


function fx1 = p10_fx1 ( x )

%*****************************************************************************80
%
%% P10_FX1 evaluates the derivative of the function for problem 10.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the abscissa.
%
%    Output, real FX1, the first derivative of the function at X.
%
  fx1 = ( 1.0 - 10.0 * x ) * ( 1.0 + 10.0 * x ) / ( 100.0 * x * x + 1.0 ).^2;

  return
end


% GeneralizedFibonacci.m by David Terr, Raytheon, 5-11-04

% Given integers n, a, and b, compute the nth generalized Fibonacci number
% U_n, defined by the recurrence U_n = a U_{n-1} + b U_{n-2} and the
% initial conditions U_0 = 0 and U_1 = 1.

function gfib = GeneralizedFibonacci(n,a,b)

% Make sure arguments are integers.
if ( n ~= floor(n) )
    error('First argument must be a nonnegative integer.');
    return;
end

if ~isreal(n) || n < 0
    error('First argument must be a nonnegative integer.');
    return;
end

if size(n,1) ~= 1 || size(n,2) ~= 1
    error('First argument must be a nonnegative integer.');
    return;
end

if ( a ~= floor(a) )
    error('Second argument must be an integer.');
    return;
end

if ~isreal(a)
    error('Second argument must be an integer.');
    return;
end

if size(a,1) ~= 1 || size(a,2) ~= 1
    error('Second argument must be an integer.');
    return;
end

if ( b ~= floor(b) )
    error('Third argument must be an integer.');
    return;
end

if ~isreal(b)
    error('Third argument must be an integer.');
    return;
end

if size(b,1) ~= 1 || size(b,2) ~= 1
    error('Third argument must be an integer.');
    return;
end

if ( n == 0 )
    gfib = 0;
    return;
end

D = a^2 + 4*b;  % discriminant

if ( D <= 0 )
    error('Discriminant must be positive.');
    return;
end

alpha = (a + sqrt(D))/2;
beta = (a - sqrt(D))/2;
gfib = round( ( alpha^n - beta^n ) / sqrt(D) );


function g = sigmoidGradient(z)
%SIGMOIDGRADIENT returns the gradient of the sigmoid function
%evaluated at z
%   g = SIGMOIDGRADIENT(z) computes the gradient of the sigmoid function
%   evaluated at z. This should work regardless if z is a matrix or a
%   vector. In particular, if z is a vector or matrix, you should return
%   the gradient for each element.

g = zeros(size(z));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the gradient of the sigmoid function evaluated at
%               each value of z (z can be a matrix, vector or scalar).

g = sigmoid(z).*(1 - sigmoid(z));

% =============================================================

end


function radians = degrees_to_radians ( degrees )

%*****************************************************************************80
%
%% DEGREES_TO_RADIANS converts an angle measure from degrees to radians.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real DEGREES, the angle measure in degrees.
%
%    Output, real RADIANS, the angle measure in radians.
%
  radians = ( degrees / 180.0 ) * 3.141592653589793;

  return
end


%  FOLD Apply a binary function left-associatively to a vector
%    FOLD(F, V, INITIALVALUE) iteratively computes
%    RES = F(V(1), V(2))
%    RES = F(RES, V(3))
%    ....
%    RES = F(RES, V(END))
%    and, finally, returns RES. If V is empty, INITIALVALUE is returned.
%    For non-empty V, the third argument INITIALVALUE may be left out.
%
%    Example:
%    syms x
%    fold(@or, x == 1:3) gives x == 1 | x==2 | x==3
%    fold(@and, [], true) gives true
%    fold(@intersect, {[1, 3], [2, 3, 29], [3, 1, 17]}) gives 3
%
%    See also PROD, SUM.
%
%    Reference page in Doc Center
%       doc fold
%
%    Other functions named fold
%
%       symfun/fold    ts/fold
%


% In this example, we consider three disjoint subspaces.
% Any two of them span the third one.
% We take random points from each subspace
% We apply sparse subspace clustering
% via orthogonal matching pursuit algorithm
% to cluster them.
% We finally verify the labels assigned by the clustering
% algorithm with the true labels and measure the
% quality of clustering using f-score.

clear all; close all; clc; rng('default');

shuffle_indices = false;
perform_ssc_omp = true;

% Ambient space dimensions
D = 50;
% number of subspaces = number of clusters
ns = 3;
% subspace dimension
K = 4;
% Angle between subspaces A-B and B-C.
theta = 30; % in degree
% Let us form the subspaces
[A, B, C] = spx.la.spaces.three_disjoint_spaces_at_angle(K, deg2rad(theta));
% Put them together
X = [A B C];
% Put them to bigger dimension
X = spx.la.spaces.k_dim_to_n_dim(X, D);
% Perform a random orthonormal transformation
O = orth(randn(D));
X = O * X;
% Split them again
A = X(:, 1:K);
B = X(:, K + (1:K));
C = X(:, 2*K + (1:K));
fprintf('Spaces after moving to n dimensions and an orthonormal transformation');
spx.la.spaces.describe_three_spaces(A, B, C);
% Number of points per subspace
Ng = 16*K;
% coefficients for Ng vectors chosen randomly in subspace A
coeffs_a = randn(K,Ng);
% avoid small values
coeffs_a = 2*sign(coeffs_a) + coeffs_a;
% coefficients for Ng vectors chosen randomly in subspace B
coeffs_b = randn(K,Ng);
% avoid small values
coeffs_b = 2*sign(coeffs_b) + coeffs_b;
% coefficients for Ng vectors chosen randomly in subspace C
coeffs_c = randn(K,Ng);
% avoid small values
coeffs_c = 2*sign(coeffs_c) + coeffs_c;
% Actual vectors from the three subspaces
XA = A * coeffs_a;
XB = B * coeffs_b;
XC = C * coeffs_c;
% Prepare the overall set of signals
X = [XA XB XC];
% ground through clustering data
true_labels = [1*ones(Ng,1) ; 2*ones(Ng,1) ; 3*ones(Ng,1)];
% All signals are expected to  have a K-sparse representation
if shuffle_indices
    % We also shuffle the signals
    shuffled_indices = randperm(3*Ng);
    X = X(:, shuffled_indices);
    true_labels = true_labels(shuffled_indices);
end
fprintf('Number of signals: %d\n', size(X, 2));

mf = spx.graphics.Figures();

if perform_ssc_omp
    tstart = tic;
    % Application of Sparse subspace clustering
    solver = spx.cluster.ssc.SSC_OMP(X, K, ns);
    result = solver.solve();
    elapsed_time = toc(tstart);
    fprintf('Sparse subspace clustering time spent: %.2f seconds\n', elapsed_time);

    cluster_labels = result.Labels;
    combined_labels = [true_labels cluster_labels]';
    disp(combined_labels);

    % Time to compare the clustering
    comparer = spx.cluster.ClusterComparison(true_labels, cluster_labels);
    result = comparer.fMeasure();
    fprintf('Sparse subspace clustering results:\n');
    comparer.printF1MeasureResult(result);

    mf.new_figure('SSC-OMP Coefficients');
    colormap gray;
    imagesc(abs(solver.Representation));
end


% PART 1: Microchips classification ====================================

% Initialization
clear; close all; clc;

% Load the data --------------------------------------------------------
fprintf('Loading the data...\n\n');

data = load('microchips_tests.csv');

X = data(:, 1:2);
y = data(:, 3);

% Plotting the data ----------------------------------------------------
fprintf('Plotting the data...\n\n');

% Find indices of positive and negative examples.
positiveIndices = find(y == 1);
negativeIndices = find(y == 0);

% Plot examples.
hold on;
plot(X(positiveIndices, 1), X(positiveIndices, 2), 'k+', 'LineWidth', 2, 'MarkerSize', 7);
plot(X(negativeIndices, 1), X(negativeIndices, 2), 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 7);

% Draw labels and Legend
xlabel('Microchip Test 1');
ylabel('Microchip Test 2');
legend('y = 1', 'y = 0');

% Running logistic regression ------------------------------------------
fprintf('Running logistic regression...\n\n');

% Add more polynomial features in order to make decision boundary to have more complex curve form.
polynomial_degree = 6;
X = add_polynomial_features(X(:, 1), X(:, 2), polynomial_degree);

% Run the regression.
lambda = 1;
[theta, J, J_history, exit_flag] = logistic_regression_train(X, y, lambda);

fprintf('- Initial cost: %f\n', J_history(1));
fprintf('- Optimized cost: %f\n\n', J);

% Plotting decision boundaries -----------------------------------------
fprintf('Plotting decision boundaries...\n\n');

% Generate a grid range.
u = linspace(-1, 1, 50);
v = linspace(-1, 1, 50);
z = zeros(length(u), length(v));
% Evaluate z = (x * theta) over the grid.
for i = 1:length(u)
    for j = 1:length(v)
        % Add polinomials.
        x = add_polynomial_features(u(i), v(j), polynomial_degree);
        % Add ones.
        x = [ones(size(x, 1), 1), x];
        z(i, j) = x * theta;
    end
end

% It is mportant to transpose z before calling the contour.
z = z';

% Plot z = 0
% Notice you need to specify the range [0, 0]
contour(u, v, z, [0, 0], 'LineWidth', 2);
title(sprintf('lambda = %g', lambda));
legend('y = 1', 'y = 0', 'Decision boundary');

hold off;

% Trying to predict custom experiments ------------------------------------
fprintf('Trying to predict custom experiments...\n\n');

x = [
    0, 0;
    -0.5, -0.5
];

% Add polinomials.
x = add_polynomial_features(x(:, 1), x(:, 2), polynomial_degree);
% Add ones.
x = [ones(size(x, 1), 1), x];

probabilities = hypothesis(x, theta);
fprintf(' %f \n', probabilities);

fprintf('\nProgram paused. Press enter to train logistic regression to recognize digits.\n');
pause;

% PART 2: Handwritten digits classification ==============================
clear; close all; clc;

% Load training data
fprintf('Loading training data...\n');
load('digits.mat');

% Plotting some training example ----------------------------------------------------
fprintf('Visualizing data...\n');

% Randomly select 100 data points to display
random_digits_indices = randperm(size(X, 1));
random_digits_indices = random_digits_indices(1:100);

display_data(X(random_digits_indices, :));

% Setup the parameters you will use for this part of the exercise
input_layer_size = 400;  % 20x20 input images of digits.
num_labels = 10; % 10 labels, from 1 to 10 (note that we have mapped "0" to label 10).

fprintf('Training One-vs-All Logistic Regression...\n')
lambda = 0.01;
num_iterations = 50;
[all_theta] = one_vs_all(X, y, num_labels, lambda, num_iterations);

fprintf('Predict for One-Vs-All...\n')
pred = one_vs_all_predict(all_theta, X);

fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);


function [rt, f, g] = twodsin(A, u0, v0, M, N)
%TWODSIN Compare for-loops vs. vectorization.
%   The comparison is based on implementing the function f(x, y) =
%   Asin(u0x + v0y) for x = 0, 1, 2,..., M - 1 and y = 0, 1, 2,...,
%   N - 1. The inputs to the function are M and N and the constants
%   in the function.
%
%   Sample M-file used in Chapter 2.

%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.3 $  $Date: 2003/10/13 00:53:47 $

% First implement using for loops.

tic   % Start timing.

for r = 1:M
   u0x = u0*(r - 1);
   for c = 1:N
      v0y = v0*(c - 1);
      f(r, c) = A*sin(u0x + v0y);
   end
end

t1 = toc;   % End timing.

%	Now implement using vectorization.  Call the image g.

tic   % Start timing.

r = 0:M - 1;
c = 0:N - 1;
[C, R] = meshgrid(c, r);
g = A*sin(u0*R + v0*C);

t2 = toc;   % End timing.

%	Compute the ratio of the two times.

rt = t1/(t2 + eps); % Use eps in case t2 is close to 0


function h=pheaviside(L)
%PHEAVISIDE  Periodic Heaviside function
%   Usage: h=pheaviside(L);
%
%   `pheaviside(L)` returns a periodic Heaviside function. The periodic
%   Heaviside function takes on the value 1 for indices corresponding to
%   positive frequencies, 0 corresponding to negative frequencies and the
%   value .5 for the zero and Nyquist frequencies.
%
%   To get a function that weights the negative frequencies by 1 and the
%   positive by 0, use `involute(pheaviside(L))`
%
%   As an example, the `pheaviside` function can be use to calculate the
%   Hilbert transform for a column vector *f*::
%
%     h=2*ifft(fft(f).*pheaviside(length(f)));
%
%   See also: middlepad, involute, fftindex

%   AUTHOR : Peter L. Søndergaard.
%   REFERENCE: OK
%   TESTING: OK

complainif_argnonotinrange(nargin,1,1,mfilename);

h=zeros(L,1);
if L>0
    % First term is .5
    h(1)=.5;

    % Set positive frequencies to 1.
    h(2:ceil(L/2))=1;

    % Last term (Nyquist frequency) is also .5, if it exists.
    if rem(L,2)==0
        h(L/2+1)=.5;
  end;
end;


clear all, close all, clc

% x = ones(500,1);
% t = .1*(1:500)';
% x = cos(t*2*pi);
% y = fft(x);
%
% N = length(x);
%
% plot(real(y),'k')
% hold on
% plot(real(DFT*x),'r--')

%% slow and steady
clear all, close all, clc
N = 256;
w = exp(-i*2*pi/N);
for i=1:N
    for j=1:N
        DFT(i,j) = w^((i-1)*(j-1));
    end
end

imagesc(real(DFT))
colormap jet
axis off
axis equal
box on
colorbar
set(gcf,'Position',[100 100 1000 900])
set(gcf,'PaperPositionMode','auto')
% print('-depsc2', '-loose', '../figures/DFTMatrixreal');
% print('-dpng', '-loose', '../figures/DFTMatrixreal');

%%

imagesc(imag(DFT))
colormap jet
axis off
axis equal
box on
colorbar
set(gcf,'Position',[100 100 1000 900])
set(gcf,'PaperPositionMode','auto')
% print('-depsc2', '-loose', '../figures/DFTMatriximag');
% print('-dpng', '-loose', '../figures/DFTMatriximag');
%% really fast
[I,J] = meshgrid(1:N,1:N);
DFT = w.^((I-1).*(J-1));


function [ pc, normal ] = circle_pppr2imp_3d ( p1, p2, p3, r )

%*****************************************************************************80
%
%% CIRCLE_PPR2IMP_3D converts a circle from PPR to implicit form in 3D.
%
%  Discussion:
%
%    The PPPR form of a circle in 3D is:
%
%      The circle of radius R passing through points P1 and P2,
%      and lying in the plane of P1, P2 and P3.
%
%    The implicit form of a circle in 3D is:
%
%      ( P(1) - PC(1) )**2 + ( P(2) - PC(2) )**2 + ( P(3) - PC(3) )**2 = R**2
%      and the dot product of P - PC with NORMAL is 0.
%
%    There may be zero, one, or two circles that satisfy the
%    requirements of the PPPR form.
%
%    If there is no such circle, then PC(1:2,1) and PC(1:2,2)
%    are set to the midpoint of (P1,P2).
%
%    If there is one circle, PC(1:2,1) and PC(1:2,2) will be equal.
%
%    If there are two circles, then PC(1:2,1) is the first center,
%    and PC(1:2,2) is the second.
%
%    This calculation is equivalent to finding the intersections of
%    spheres of radius R at points P1 and P2, which lie in the plane
%    defined by P1, P2 and P3.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 March 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(3,1), P2(3,1), two points on the circle.
%
%    Input, real P3(3,1), a third point.
%
%    Input, real R, the radius of the circle.
%
%    Output, real PC(3,2), the centers of the two circles.
%
%    Output, real NORMAL(3,1), the normal to the circles.
%
  dim_num = 3;
%
%  Compute the distance from P1 to P2.
%
  dist = sqrt ( sum ( ( p2(1:dim_num,1) - p1(1:dim_num,1) ).^2 ) );
%
%  If R is smaller than DIST, we don't have a circle.
%
  if ( 2.0 * r < dist )
    for j = 1 : 2
      pc(1:dim_num,j) = 0.5 * ( p1(1:dim_num,1) + p2(1:dim_num,1) );
    end
    return
  end
%
%  H is the distance from the midpoint of (P1,P2) to the center.
%
  h = sqrt ( ( r + 0.5 * dist ) * ( r - 0.5 * dist ) );
%
%  Define a unit direction V that is normal to P2-P1, and lying
%  in the plane (P1,P2,P3).
%
%  To do this, subtract from P3-P1 the component in the direction P2-P1.
%
  v(1:dim_num,1) = p3(1:dim_num,1) - p1(1:dim_num,1);
  dot = v(1:dim_num,1)' * ( p2(1:dim_num,1) - p1(1:dim_num,1) );
  dot = dot / dist;

  v(1:dim_num,1) = v(1:dim_num,1) - dot * ( p2(1:dim_num,1) - p1(1:dim_num,1) ) / dist;

  v_length = sqrt ( sum ( v(1:dim_num,1).^2 ) );

  v(1:dim_num,1) = v(1:dim_num,1) / v_length;
%
%  We can go with or against the given normal direction.
%
  pc(1:dim_num,1) = 0.5 * ( p2(1:dim_num,1) + p1(1:dim_num,1) ) + h * v(1:dim_num,1);

  pc(1:dim_num,2) = 0.5 * ( p2(1:dim_num,1) + p1(1:dim_num,1) ) - h * v(1:dim_num,1);

  normal = plane_exp_normal_3d ( p1, p2, p3 );

  return
end


function [x,iflaw]=fmpower(N,k,p1,p2)
%FMPOWER Signal with power-law frequency modulation.
%	[X,IFLAW]=FMPOWER(N,K,P1,P2) generates a signal with a
%	power-law frequency modulation.
%	X(t) = exp(j*2*pi(F0*t + C/(1-K)*abs(t).^(1-K)))
%
%	N  : number of points in time
%	K  : degree of the power-law (K~=1)
%	P1 : if the number of input arguments (NARGIN) is 3, P1 is a
%	    vector containing the two coefficients [F0 C] for a
%	    power-law instantaneous frequency (sampling frequency is set to 1).
%	    If NARGIN=4, P1 (as P2) is a time-frequency point of the
%	    form [Ti Fi]. Ti is in seconds and Fi is a normalized frequency
%	    (between 0 and 0.5). The coefficients F0
%	    and C are then deduced such that the frequency modulation
%	    law fits the points P1 and P2.
%	P2 : same as P1 if NARGIN=4         (optional)
%	X  : time row vector containing the modulated signal samples
%	IFLAW : instantaneous frequency law
%
%	Examples :
%	 [X,IFLAW]=fmpower(128,0.5,[1 0.5],[100 0.1]);
%	 subplot(211);plot(real(X));subplot(212);plot(IFLAW);
%
%	See also GDPOWER, FMCONST, FMLIN, FMHYP, FMPAR, FMODANY, FMSIN.

%	P. Goncalves - October 1995, O. Lemoine - April 1996.
%	Copyright (c) 1995 Rice University, 1996 CNRS (France).
%
%  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

if (nargin <= 2),
 error ( 'The number of parameters must be at least 3.' );
elseif (N <= 0),
 error ('The signal length N must be strictly positive' );
elseif abs(k-1)<sqrt(eps),
  error('K must be different from 1');
elseif nargin == 3
  if length(p1) ~= 2
   error('Bad number of coefficients');
  end
  f0 = p1(1) ; c = p1(2) ;
elseif nargin == 4 ;
  if (length(p1) ~= 2) |(length(p2) ~= 2),
   error('Bad number of coefficients for P1 or P2');
  end
  if p1(1)>N | p1(1)<1,
   error ('P1(1) must be between 1 and N');
  elseif p2(1)>N | p2(1)<1,
   error ('P2(1) must be between 1 and N');
  elseif p1(2)<0,
   error ('P1(2) must be > 0');
  elseif p2(2)<0,
   error ('P2(2) must be > 0');
  end
  c  = (p2(2) - p1(2))/(1/p2(1)^k - 1/p1(1)^k) ;
  f0 = p1(2) - c/p1(1)^k ;
end

t=1:N;

phi = 2*pi*(f0*t + c/(1-k)*abs(t).^(1-k)) ;
iflaw = (f0 + c*abs(t).^(-k)).' ;

aliasing = find(iflaw<0 | iflaw>0.5) ;
if isempty(aliasing) == 0
  disp(['!!! WARNING: signal is undersampled or has negative frequencies']) ;
end

x = exp(i*phi).';


function vol = tetrahedronVolume(vertices, varargin)
%TETRAHEDRONVOLUME Signed volume of a tetrahedron
%
%   VOL = tetrahedronVolume(TETRA)
%   Comptues the siged volume of the tetrahedron TETRA defined by a 4-by-4
%   array representing the polyhedron vertices.
%
%   Example
%     vi = [0 0 0;1 0 0;0 1 0;0 0 1];
%     tetrahedronVolume(vi)
%     ans =
%         0.1667
%
%     [V F] = createTetrahedron;
%     tetrahedronVolume(V)
%     ans =
%         -.3333
%
%   See also
%   meshes3d, createTetrahedron, meshVolume
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2012-04-05,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2012 INRA - Cepia Software Platform.

if nargin == 2
    tetras = varargin{1};
    nTetras = size(tetras, 1);
    vol = zeros(nTetras, 1);
    for i = 1:nTetras
        tetra = tetras(i,:);
        vol(i) = det(bsxfun(@minus, vertices(tetra(2:4),:), vertices(tetra(1),:))) / 6;
    end
    return;
end

% control on inputs
if nargin == 4
    vertices = [vertices ; varargin{1} ; varargin{2} ; varargin{3}];
end

if size(vertices, 1) < 4
    error('Input vertex array requires at least 4 vertices');
end

% compute volume of tetrahedron, using first vertex as origin
vol = det(vertices(2:4,:) - vertices([1 1 1],:)) / 6;


function [U,S,V] = svdsecon(X,k)
% Input:
% X : m x n matrix
% k : extracts the first k singular values
%
% Output:
% X = U*S*V' approximately (up to k)
%
% Description:
% Does equivalent to svds(X,k) but faster
% Requires that k < min(m,n) where [m,n] = size(X)
% This function is useful if k is much smaller than m and n
% or if X is sparse (see doc eigs)
%
% Vipin Vijayan (2014)

%X = bsxfun(@minus,X,mean(X,2));
[m,n] = size(X);
assert(k <= m && k <= n, 'k needs to be smaller than size(X,1) and size(X,2)');

if  m <= n
    C = double(X*X');
    [U,D] = eigs(C,k);
    clear C;
    if nargout > 2
        V = X'*U;
        s = sqrt(abs(diag(D)));
        V = bsxfun(@(x,c)x./c, V, s');
        S = diag(s);
    end
else
    C = double(X'*X);
    [V,D] = eigs(C,k);
    clear C;
    U = X*V; % convert evecs from X'*X to X*X'. the evals are the same.
    %s = sqrt(sum(U.^2,1))';
    s = sqrt(abs(diag(D)));
    U = bsxfun(@(x,c)x./c, U, s');
    S = diag(s);
end


function[nui,om2i]=morlfreq(omi)
%MORLFREQ  Compute Morlet wavelet carrier frequency given peak frequency.
%
%   FNU=MORLFREQ(FMAX), where FMAX is the desired peak frequency of a
%   Morlet wavelet, returns the appropriate carrier wave frequency FNU.
%
%   The Morlet wavelet carrier wave and peak frequency differ on account
%   of the correction term which ensures zero mean.
%
%   Note that FMAX and FNU are both *radian* as in cos(omega t) and not
%   cyclic as in in cos(2 pi f t).
%
%   [FNU,FMIN]=MORLFREQ(FMAX) also returns the (radian) frequency at which
%   the Morlet wavelet obtains a minimum, which occurs for FMIN<0.
%
%   For details see Appendix A of
%
%       Lilly and Olhede (2009).  Higher-order properties of analytic
%          wavelets.  IEEE Trans. Sig. Proc., 57 (1), 146--160.
%
%   'morlfreq --t' runs a test.
%   'morlfreq --f' generates a sample figure.
%
%   Usage: fnu=morlfreq(fmax);
%          [fnu,fmin]=morlfreq(fmax);
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2008--2013 J.M. Lilly --- type 'help jlab_license' for details

if strcmpi(omi, '--t')
    morlfreq_test,return
end
if strcmpi(omi, '--f')
    type makefigs_morlfreq
    makefigs_morlfreq;
    return
end

sizeom=size(omi);
omi=omi(:);

N=10000;

%This gives a tighter spacing near one than near zero
nutilde=log(log(linspace(exp(exp(1./1e9)),exp(exp(1-1./1e9)),N)));
%nutilde=linspace(1./1e9,1-1./1e9,N);

om=(sqrt(-frac((log(1-nutilde)),nutilde)));
nu=nutilde.*om;

bool=(omi>=maxmax(om));
index1=find(bool);
if ~isempty(index1)
    nui(index1)=omi(index1);
end
index2=find(~bool);
if ~isempty(index2)
    nui(index2)=interp1(om,nu,omi(index2),'linear');
end

%I chose this grid via trial and error
nutilde=1./[linspace(1./10,10,N) logspace(log10(10+0.0000001),log10(1000),N)];
om2=-(sqrt(frac((log(1+nutilde)),nutilde)));
nu2=(nutilde).*abs(om2);

om2i=zeros(size(nui));%figure,plot(nui),maxmax(nu2)
bool=(nui>=maxmax(nu2));
index1=find(bool);
if ~isempty(index1)
    om2i(index1)=nan;
end
index2=find(~bool);%length(index2)
if ~isempty(index2)
    om2i(index2)=interp1(nu2,om2,nui(index2),'linear');
end
%x=om2i-nui-om2i.*exp(-om2i.*nui);
%figure,plot(x)

nui=reshape(nui,sizeom);
om2i=reshape(om2i,sizeom);

function[]=morlfreq_test
om=linspace(0,4,1000);
[nu,fneg]=morlfreq(om);

psi1a=exp(-frac(1,2).*(nu-om).^2).*(-(om-nu))+exp(-frac(1,2).*(nu.^2+om.^2)).*om;
reporttest('MORLFREQ first derivative vanishes at peak',aresame(psi1a,0*psi1a,1e-4))

omneg=fneg*2*pi;
psi1b=exp(-frac(1,2).*(nu-omneg).^2).*(-(omneg-nu))+exp(-frac(1,2).*(nu.^2+omneg.^2)).*omneg;

reporttest('MORLFREQ first derivative vanishes at negative peak',aresame(psi1b,0*psi1b,1e-4))


function a=getNextMPartition(param1,m)
%%GETNEXTMPARTITION Get the next partition of the integer n into m
%                   parts. This is m nonzero items such that the sum is n.
%                   The partitions are visited in reverse lexicographic
%                   order (colex order). The function can be called with
%                   two parameters to get the first n,m partition, or with
%                   1 parameter (that being the previous partition) to
%                   get the next partition. The total number of
%                   partitions can be found using the function
%                   numMPartitions(n,m). As combinations are to
%                   permutations, partitions are to compositions: The order
%                   of the terms in an m-partitions do not matter, whereas
%                   they matter in a composition.
%
%INPUTS: param1 If two parameters are passed to the function, then param1
%            is n, the integer to be partitioned. Otherwise, param1 is a,
%            the current partition of the chosen integer n into m parts.
%            This means that a must be length m and its elements must sum
%            to n. The elements must be ordered in decreasing order. The
%            first partition in the series must be a(1)=n-m+1; a(2:m)=1;
%            Note that n>=m>=2 if a is passed, because a size 1 partition
%            only has one value (the initial value).
%          m This parameter is not passed if the next m-partition in the
%            sequence is desired. However, if one wishes to obtain the
%            first value in the sequence, then m is the positive integer
%            number of parts into which the integer n is split, n>=m;
%
%OUTPUTS: a The next partition in the series or the empty matrix if the
%           parition given was the last partition in the series. If the
%           function was called getNextMPartition(n,m), then a is the first
%           parition.
%
%The algorithm is Algorithm H in Chapter 7.2.1.4 of [1].
%
%The function can either be called as
%a=getNextMPartition(n,m);
%to get the first parition of the integer n into m parts or as
%a=getNextMPartition(a);
%to get the next partition.
%
%Often, one might prefer all partitions of m integers that sum to a
%constant value n INCLUDING zeros. This function can be used to produce
%such a modified set of partitions by initializing it as
%a=getNextMPartition(n+m,m);
%and for every composition generated, including the first, the modified
%composition starting from zero is given by a-1.
%
%REFERENCES:
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 4, Fascicle 3:
%    Generating all Combinations and Partitions, Upper Saddle River, NJ:
%    Addison-Wesley, 2009.
%
%October 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Return the first partition in the sequence if two parameters are passed.
if(nargin>1)
    n=param1;
    a(1)=n-m+1;
    a(2:m)=1;
    return;
end

a=param1;

m=length(a);

%Deal with the special case of a 1D partition. In this instance, there is
%only 1 possible solution, so if one is calling this function again, it
%will be past the end of all possible solutions.
if(m==1)
    a=[];
    return;
end

while(a(2)<a(1)-1)
    %Step H3 in Knuth
    a(1)=a(1)-1;
    a(2)=a(2)+1;
    return;
end

%Step H4 in Knuth, with an added check to avoid reading past the end of the
%array if m=2.
j=3;
if(j>m)
    a=[];
    return;
end
s=a(1)+a(2)-1;
while(a(j)>=a(1)-1)
    s=s+a(j);
    j=j+1;
    %If we have passed the last partition
    %(Termination part of step H5)
    if(j>m)
       a=[];
       return;
    end
end

%Step H5 in Knuth.
x=a(j)+1;
a(j)=x;
j=j-1;

%Step H6 in Knuth
while(j>1)
    a(j)=x;
    s=s-x;
    j=j-1;
    a(1)=s;
end

end

%LICENSE:
%
%The source code is in the public domain and not licensed or under
%copyright. The information and software may be used freely by the public.
%As required by 17 U.S.C. 403, third parties producing copyrighted works
%consisting predominantly of the material produced by U.S. government
%agencies must provide notice with such work(s) identifying the U.S.
%Government material incorporated and stating that such material is not
%subject to copyright protection.
%
%Derived works shall not identify themselves in a manner that implies an
%endorsement by or an affiliation with the Naval Research Laboratory.
%
%RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF THE
%SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY THE NAVAL
%RESEARCH LABORATORY FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE ACTIONS
%OF RECIPIENT IN THE USE OF THE SOFTWARE.


function geometry_test062 ( )

%*****************************************************************************80
%
%% TEST062 tests PLANE_NORMAL_TRIANGLE_INT_3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 April 2009
%
%  Author:
%
%    John Burkardt
%
  dim_num = 3;
  ntest = 4;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST062\n' );
  fprintf ( 1, '  PLANE_NORMAL_TRIANGLE_INT_3D finds the\n' );
  fprintf ( 1, '    intersection points of a normal form plane\n' );
  fprintf ( 1, '    and a triangle.\n' );

  normal(1:dim_num) =  [ 1.0, -2.0, -3.0 ];

  pp(1:dim_num) = [ 0.0, 0.0, 2.0 ];

  r8vec_print ( dim_num, pp, '  The point PP:' );

  r8vec_print ( dim_num, normal, '  The normal vector N:' );

  for i = 1 : ntest

    if ( i == 1 )
      t(1:dim_num,1:3) = [ ...
         3.0,  0.0, -7.0; ...
        13.0, -4.0, -1.0; ...
         5.0,  1.0, -2.0 ]';
    elseif ( i == 2 )
      t(1:dim_num,1:3) = [ ...
         3.0,  0.0, -7.0; ...
        13.0, -4.0, -1.0; ...
         9.0,  3.0,  8.0 ]';
    elseif ( i == 3 )
      t(1:dim_num,1:3) = [ ...
        -6.0,  0.0,  0.0; ...
         0.0,  3.0,  0.0; ...
         0.0,  0.0,  2.0 ]';
    elseif ( i == 4 )
      t(1:dim_num,1:3) = [ ...
        -4.0,  1.0,  0.0; ...
         0.0,  6.0, -2.0; ...
         0.0,  0.0,  1.0 ]';
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Case %d\n', i );

    r8mat_transpose_print ( dim_num, 3, t, '  Triangle vertices:' );

    [ num_int, pint ] = plane_normal_triangle_int_3d ( pp, normal, t );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Number of intersection points is %d\n', num_int );

    r8mat_transpose_print ( dim_num, num_int, pint, '  Intersection points:' );

  end

  return
end


function h=smooth_diff(n)
% A smoothed differentiation filter (digital differentiator).
%
% Such a filter has the following advantages:
%
% First, the filter involves both the smoothing operation and differentation operation.
% It can be regarded as a low-pass differention filter (digital differentiator).
% It is well known that the common differentiation operation amplifies the high-frequency noises.
% Therefore, the smoothded differentiation filter would be valuable in experimental (noisy) data processing.
%
% Secondly, the filter coefficients are all convenient integers (simple units) except for an integer scaling factor,
% as may be especially significant in some applications such as those in some single-chip microcomputers
% or digital signal processors.
%
% Usage:
% h=smooth_diff(n)
% n: filter length (positive integer larger no less than 2)
% h: filter coefficients (anti-symmetry)
%
% Examples:
% smooth_demo
%
% Author:
% Jianwen Luo <luojw@bme.tsinghua.edu.cn, luojw@ieee.org> 2004-11-02
% Department of Biomedical Engineering, Department of Electrical Engineering
% Tsinghua University, Beijing 100084, P. R. China
%
% References:
% Usui, S.; Amidror, I.,
% Digital Low-Pass Differentiation for Biological Signal-Processing.
% IEEE Transactions on Biomedical Engineering 1982, 29, (10), 686-693.
% Luo, J. W.; Bai, J.; He, P.; Ying, K.,
% Axial strain calculation using a low-pass digital differentiator in ultrasound elastography.
% IEEE Transactions on Ultrasonics Ferroelectrics and Frequency Control 2004, 51, (9), 1119-1127.

if n>=2 && floor(n)==ceil(n)
    if mod(n,2)==1%is odd
        m=fix((n-1)/2);
        h=[-ones(1,m) 0 ones(1,m)]/m/(m+1);
    else%is even
        m=fix(n/2);
        h=[-ones(1,m) ones(1,m)]/m^2;
    end
else
    error('The input parameter (n) should be a positive integer larger no less than 2.');
end


function [ ] = ml_plot_gmm_pdf(X, Priors, Mu, Sigma )
%ML_PLOT_GMM_PDF Summary of this function goes here
%   Detailed explanation goes here

% Auxiliary Variables
K = length(Priors);

% Contour Function for GMM
xplot = linspace(min(X(1,:)), max(X(1,:)), 100)';
yplot = linspace(min(X(2,:)), max(X(2,:)), 100)';
[X_, Y_] = meshgrid(xplot, yplot);
vals = zeros(size(X_));

for i = 1:length(xplot)
    for j = 1:size(yplot)
        x = [xplot(i);yplot(j)];
        vals(j,i) =  ml_gmm_pdf(x, Priors, Mu, Sigma);
    end
end

% Plot the GMM PDF Contours
figure;
% contour(X_,Y_, vals, 50, 'LineStyle', 'none');hold on;
contour(X_,Y_, vals, 100);hold on;
% surf(X_,Y_, vals, 100);hold on;
colormap jet
colorbar
colors = hsv(K);
ml_plot_centroid(Mu',colors);hold on;
options.class_names = {};
options.labels      = [];
options.points_size = 30;
options.colors      = [0 1 0.5];
options.plot_figure = true;
ml_plot_data(X',options);
title ('GMM-PDF Contours');

end


function submit()
  addpath('./lib');

  conf.assignmentSlug = 'linear-regression';
  conf.itemName = 'Linear Regression with Multiple Variables';
  conf.partArrays = { ...
    { ...
      '1', ...
      { 'warmUpExercise.m' }, ...
      'Warm-up Exercise', ...
    }, ...
    { ...
      '2', ...
      { 'computeCost.m' }, ...
      'Computing Cost (for One Variable)', ...
    }, ...
    { ...
      '3', ...
      { 'gradientDescent.m' }, ...
      'Gradient Descent (for Multiple Variables)', ...
    }, ...
    { ...
      '4', ...
      { 'featureNormalize.m' }, ...
      'Feature Normalization', ...
    }, ...
    { ...
      '5', ...
      { 'computeCostMulti.m' }, ...
      'Computing Cost (for Multiple Variables)', ...
    }, ...
    { ...
      '6', ...
      { 'gradientDescentMulti.m' }, ...
      'Gradient Descent (for Multiple Variables)', ...
    }, ...
    { ...
      '7', ...
      { 'normalEqn.m' }, ...
      'Normal Equations', ...
    }, ...
  };
  conf.output = @output;

  submitWithConfiguration(conf);
end

function out = output(partId)
  % Random Test Cases
  X1 = [ones(20,1) (exp(1) + exp(2) * (0.1:0.1:2))'];
  Y1 = X1(:,2) + sin(X1(:,1)) + cos(X1(:,2));
  X2 = [X1 X1(:,2).^0.5 X1(:,2).^0.25];
  Y2 = Y1.^0.5 + Y1;
  if partId == '1'
    out = sprintf('%0.5f ', warmUpExercise());
  elseif partId == '2'
    out = sprintf('%0.5f ', computeCost(X1, Y1, [0.5 -0.5]'));
  elseif partId == '3'
    out = sprintf('%0.5f ', gradientDescent(X1, Y1, [0.5 -0.5]', 0.01, 10));
  elseif partId == '4'
    out = sprintf('%0.5f ', featureNormalize(X2(:,2:4)));
  elseif partId == '5'
    out = sprintf('%0.5f ', computeCostMulti(X2, Y2, [0.1 0.2 0.3 0.4]'));
  elseif partId == '6'
    out = sprintf('%0.5f ', gradientDescentMulti(X2, Y2, [-0.1 -0.2 -0.3 -0.4]', 0.01, 10));
  elseif partId == '7'
    out = sprintf('%0.5f ', normalEqn(X2, Y2));
  end
end


function [Stat] = VectStat (M)
%
%   [Stat] = VectStat (M)
%
%Purpose:
%   calculates very basic stats of vectors
%
%
%Input Parameters:
%   M : MxN matrix
%      NAN or Inf values are not considered and the user is warned of their existence
%
%Output Parameters:
%
%   Stat is an Mx1 vector of structures with the following fields
%     Each Stat(i) has the following structures
%      .N : the number of elements in M(i,:)
%      .M : the mean of vector M(i,:)
%      .Md: the median of vector M(i,:)
%      .S : the (unbiased) standard deviation of M(i,:)
%      .V : the variance (S^2) of M(i,:)
%      .mx: The maximum value
%      .mn: The minimum value
%
%     if the input vector is empty , NaN values are returned in Stat
%More Info :
%
%
%
%
%     Author : Ziad Saad
%     Date : Tue Apr 20 17:13:23 CDT 1999

%Define the function name for easy referencing
FuncName = 'VectStat';

%Debug Flag
DBG = 1;
Stat.N = NaN;
Stat.M = NaN;
Stat.Md = NaN;
Stat.S = NaN;
Stat.V = NaN;

if (is_row(M) ~= -1),
	sZ = 1;
	sz2 = length(M);
	M = M(:)'; %turn M into a row vector
else
	sZ = size(M,1);
	sz2 = size(M,2);
end

if (sZ == 0 | sz2 ==0),
	ErrEval(FuncName,'Wrn_Empty M returning NaN structure for result');
	return;
end

%initialize, once
	Stat(sZ).N = 0;Stat(sZ).M = 0;Stat(sZ).Md = 0;Stat(sZ).S = 0;Stat(sZ).V = 0; Stat(sZ).mn = 0; Stat(sZ).mx = 0;

for (i=1:1:sZ),
	igood = find(isfinite(M(i,:)));
	N_igood = length(igood);
	if (N_igood < sz2),
		stmp = sprintf ('%s Warning: Inf or Nan ignored in row %g\n', FuncName, i);
	end

	Stat(i).N = N_igood;
	Stat(i).M = mean(M(i,igood));
	Stat(i).Md = median(M(i,igood));
	Stat(i).S = std(M(i,igood),0); %unbiased estimator
	Stat(i).V = Stat(i).S .^ 2;
	Stat(sZ).mn = min(M(i,igood));
	Stat(sZ).mx = max(M(i,igood));
end

return;


function Xsol = nonlinear_eigenspace(L, k, alpha)
% Example of nonlinear eigenvalue problem: total energy minimization.
%
% function Xsol = nonlinear_eigenspace(L, k, alpha)
%
% L is a discrete Laplacian operator,
% alpha is a given constant, and
% k corresponds to the dimension of the least eigenspace sought.
%
% This example demonstrates how to use the Grassmann geometry factory
% to solve the nonlinear eigenvalue problem as the optimization problem:
%
% minimize 0.5*trace(X'*L*X) + (alpha/4)*(rho(X)*L\(rho(X)))
% over X such that X'*X = Identity,
%
% where L is of size n-by-n,
% X is an n-by-k matrix, and
% rho(X) is the diagonal part of X*X'.
%
% This example is motivated in the paper
% "A Riemannian Newton Algorithm for Nonlinear Eigenvalue Problems",
% Zhi Zhao, Zheng-Jian Bai, and Xiao-Qing Jin,
% SIAM Journal on Matrix Analysis and Applications, 36(2), 752-774, 2015.
%

% This file is part of Manopt and is copyrighted. See the license file.
%
% Main author: Bamdev Mishra, June 19, 2015.
% Contributors:
%
% Change log:

    % If no inputs are provided, generate a  discrete Laplacian operator.
    % This is for illustration purposes only.
    % The default example corresponds to Case (c) of Example 6.2 of the
    % above referenced paper.

    if ~exist('L', 'var') || isempty(L)
        n = 100;
        L = gallery('tridiag', n, -1, 2, -1);
    end

    n = size(L, 1);
    assert(size(L, 2) == n, 'L must be square.');

    if ~exist('k', 'var') || isempty(k) || k > n
        k = 10;
    end

    if ~exist('alpha', 'var') || isempty(alpha)
        alpha = 1;
    end

    % Grassmann manifold description
    Gr = grassmannfactory(n, k);
    problem.M = Gr;

    % Cost function evaluation
    problem.cost =  @cost;
    function val = cost(X)
        rhoX = sum(X.^2, 2); % diag(X*X');
        val = 0.5*trace(X'*(L*X)) + (alpha/4)*(rhoX'*(L\rhoX));
    end

    % Euclidean gradient evaluation
    % Note: Manopt automatically converts it to the Riemannian counterpart.
    problem.egrad = @egrad;
    function g = egrad(X)
        rhoX = sum(X.^2, 2); % diag(X*X');
        g = L*X + alpha*diag(L\rhoX)*X;
    end

    % Euclidean Hessian evaluation
    % Note: Manopt automatically converts it to the Riemannian counterpart.
    problem.ehess = @ehess;
    function h = ehess(X, U)
        rhoX = sum(X.^2, 2); %diag(X*X');
        rhoXdot = 2*sum(X.*U, 2);
        h = L*U + alpha*diag(L\rhoXdot)*X + alpha*diag(L\rhoX)*U;
    end

    % Check whether gradient and Hessian computations are correct.
    % checkgradient(problem);
    % pause;
    % checkhessian(problem);
    % pause;

    % Initialization as suggested in above referenced paper.
    X = randn(n, k);
    [U, S, V] = svd(X, 0); %#ok<ASGLU>
    X = U*V';
    [U0, S0, V0] = eigs(L + alpha*diag(L\(sum(X.^2, 2))), k,'sm'); %#ok<NASGU,ASGLU>
    X0 = U0;

    % Call manoptsolve to automatically call an appropriate solver.
    % Note: it calls the trust regions solver as we have all the required
    % ingredients, namely, gradient and Hessian, information.
    Xsol = manoptsolve(problem, X0);

end


function [] = checkNumericalGradient()
% This code can be used to check your numerical gradient implementation
% in computeNumericalGradient.m
% It analytically evaluates the gradient of a very simple function called
% simpleQuadraticFunction (see below) and compares the result with your numerical
% solution. Your numerical gradient implementation is incorrect if
% your numerical solution deviates too much from the analytical solution.

% Evaluate the function and gradient at x = [4; 10]; (Here, x is a 2d vector.)
x = [4; 10];
[value, grad] = simpleQuadraticFunction(x);

% Use your code to numerically compute the gradient of simpleQuadraticFunction at x.
% (The notation "@simpleQuadraticFunction" denotes a pointer to a function.)
numgrad = computeNumericalGradient(@simpleQuadraticFunction, x);

% Visually examine the two gradient computations.  The two columns
% you get should be very similar.
disp([numgrad grad]);
fprintf('The above two columns you get should be very similar.\n(Left-Your Numerical Gradient, Right-Analytical Gradient)\n\n');

% Evaluate the norm of the difference between two solutions.
% If you have a correct implementation, and assuming you used EPSILON = 0.0001
% in computeNumericalGradient.m, then diff below should be 2.1452e-12
diff = norm(numgrad-grad)/norm(numgrad+grad);
disp(diff);
fprintf('Norm of the difference between numerical and analytical gradient (should be < 1e-9)\n\n');
end

function [value,grad] = simpleQuadraticFunction(x)
% this function accepts a 2D vector as input.
% Its outputs are:
%   value: h(x1, x2) = x1^2 + 3*x1*x2
%   grad: A 2x1 vector that gives the partial derivatives of h with respect to x1 and x2
% Note that when we pass @simpleQuadraticFunction(x) to computeNumericalGradients, we're assuming
% that computeNumericalGradients will use only the first returned value of this function.

value = x(1)^2 + 3*x(1)*x(2);

grad = zeros(2, 1);
% 对X1 求偏导
grad(1)  = 2*x(1) + 3*x(2);
% 对X2 求偏导
grad(2)  = 3*x(1);

end


function [X_norm, mu, sigma] = featureNormalize(X)
% FEATURENORMALIZE(X) returns a normalized version of X where
% the mean value of each feature is 0 and the standard deviation
% is 1. This is often a good preprocessing step to do when
% working with learning algorithms.

mu = mean(X);
sigma = std(X);

t = ones(length(X), 1);
X_norm = (X - (t * mu)) ./ (t * sigma); % Vectorized

end