function mean = truncated_normal_ab_mean ( mu, sigma, a, b )

%*****************************************************************************80
%
%% TRUNCATED_NORMAL_AB_MEAN returns the mean of the truncated Normal PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 August 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real MU, SIGMA, the mean and standard deviation of the
%    parent Normal distribution.
%
%    Input, real A, B, the lower and upper truncation limits.
%
%    Output, real MEAN, the mean of the PDF.
%
  alpha = ( a - mu ) / sigma;
  beta = ( b - mu ) / sigma;

  alpha_cdf = normal_01_cdf ( alpha );
  beta_cdf = normal_01_cdf ( beta );

  alpha_pdf = normal_01_pdf ( alpha );
  beta_pdf = normal_01_pdf ( beta );

  mean = mu + sigma * ( alpha_pdf - beta_pdf ) / ( beta_cdf - alpha_cdf );

  return
end


function value = r8vec_distance ( dim_num, v1, v2 )

%*****************************************************************************80
%
%% R8VEC_DISTANCE returns the Euclidean distance between two R8VEC's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 August 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, real V1(DIM_NUM), V2(DIM_NUM), the vectors.
%
%    Output, real VALUE, the Euclidean distance
%    between the vectors.
%
  value = sqrt ( sum ( ( v1(1:dim_num) - v2(1:dim_num) ).^2 ) );

  return
end


function [U, S] = pca(X)
%PCA Run principal component analysis on the dataset X
%   [U, S, X] = pca(X) computes eigenvectors of the covariance matrix of X
%   Returns the eigenvectors U, the eigenvalues (on diagonal) in S
%

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

% You need to return the following variables correctly.
U = zeros(n);
S = zeros(n);

% ====================== YOUR CODE HERE ======================
% Instructions: You should first compute the covariance matrix. Then, you
%               should use the "svd" function to compute the eigenvectors
%               and eigenvalues of the covariance matrix.
%
% Note: When computing the covariance matrix, remember to divide by m (the
%       number of examples).
%
Sigma=(1./m).*X'*X;
[U, S, V]=svd(Sigma);

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

end


function [Q, R] = gs_m(A)
%GS_M    Modified Gram-Schmidt QR factorization.
%        [Q, R] = GS_M(A) uses the modified Gram-Schmidt method to compute the
%        factorization A = Q*R for m-by-n A of full rank,
%        where Q is m-by-n with orthonormal columns and R is n-by-n.

%        Reference:
%        N. J. Higham, Accuracy and Stability of Numerical Algorithms,
%        Second edition, Society for Industrial and Applied Mathematics,
%        Philadelphia, PA, 2002; sec 19.8.

[m, n] = size(A);
Q = zeros(m,n);
R = zeros(n);

for k=1:n
    R(k,k) = norm(A(:,k));
    Q(:,k) = A(:,k)/R(k,k);
    R(k,k+1:n) = Q(:,k)'*A(:,k+1:n);
    A(:,k+1:n) = A(:,k+1:n) - Q(:,k)*R(k,k+1:n);
end


function cdf = gompertz_cdf ( x, a, b )

%*****************************************************************************80
%
%% GOMPERTZ_CDF evaluates the Gompertz CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Johnson, Kotz, and Balakrishnan,
%    Continuous Univariate Distributions, Volume 2, second edition,
%    Wiley, 1994, pages 25-26.
%
%  Parameters:
%
%    Input, real X, the argument of the CDF.
%
%    Input, real A, B, the parameters of the PDF.
%    1 < A, 0 < B.
%
%    Output, real CDF, the value of the CDF.
%
  if ( x <= 0.0 )
    cdf = 0.0;
  else
    cdf = 1.0 - exp ( - b * ( a^x - 1.0 ) / log ( a ) );
  end

  return
end


function v = haar_2d ( u )

%*****************************************************************************80
%
%% HAAR_2D computes the Haar transform of an array.
%
%  Discussion:
%
%    Thanks to Stephen Becker for pointing out that a previous version of
%    the haar_2d code was not inverted by haar_2d_inverse in cases where
%    M and N were not powers of 2, 05 March 2014.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 March 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real U(M,N), the vector to be transformed.
%
%    Output, real V(M,N), the transformed vector.
%
  [ m, n ] = size ( u );

  v = u;

  s = sqrt ( 2.0 );

  w = zeros ( m, n );
%
%  Determine K, the largest power of 2 such that K <= M.
%
  k = 1;
  while ( k * 2 <= m )
    k = k * 2;
  end
%
%  Transform all columns.
%
  while ( 1 < k )

    k = floor ( k / 2 );

    w(  1:  k,:) = ( v(1:2:2*k-1,:) + v(2:2:2*k,:) ) / s;
    w(k+1:k+k,:) = ( v(1:2:2*k-1,:) - v(2:2:2*k,:) ) / s;

    v(1:2*k,:) = w(1:2*k,:);

  end
%
%  Determine K, the largest power of 2 such that K <= N.
%
  k = 1;
  while ( k * 2 <= n )
    k = k * 2;
  end
%
%  Transform all rows.
%
  while ( 1 < k )

    k = floor ( k / 2 );

    w(:,  1:  k) = ( v(:,1:2:2*k-1) + v(:,2:2:2*k) ) / s;
    w(:,k+1:k+k) = ( v(:,1:2:2*k-1) - v(:,2:2:2*k) ) / s;

    v(:,1:2*k) = w(:,1:2*k);

  end

  return
end


function polylogarithm_values_test ( )

%*****************************************************************************80
%
%% POLYLOGARITHM_VALUES_TEST demonstrates the use of POLYLOGARITHM_VALUES.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 November 2005
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'POLYLOGARITHM_VALUES_TEST:\n' );
  fprintf ( 1, '  POLYLOGARITHM_VALUES stores values of\n' );
  fprintf ( 1, '  the polylogarithm.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '       N           Z           FX\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, n, z, fx ] = polylogarithm_values ( n_data );

    if ( n_data == 0 )
      break
    end

    fprintf ( 1, '  %4d  %12f  %24.16f\n',  n, z, fx );

  end

  return
end


function value = ellipse_area_2d ( r1, r2 )

%*****************************************************************************80
%
%% ELLIPSE_AREA_2D returns the area of an ellipse in 2D.
%
%  Discussion:
%
%    The ellipse is defined as points (X,Y) such that
%
%      ( ( X - XC ) / R1 )^2 + ( ( Y - YC ) / R2 )^2 <= 1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R1, R2, the major and minor semi-axes.
%
%    Output, real ELLIPSE_AREA_2D, the area of the ellipse.
%
  value = pi * r1 * r2;

  return
end


function pdf = gamma_pdf ( x, a, b, c )

%*****************************************************************************80
%
%% GAMMA_PDF evaluates the Gamma PDF.
%
%  Discussion:
%
%    PDF(X)(A,B,C) = EXP ( - ( X - A ) / B ) * ( ( X - A ) / B )^(C-1)
%      / ( B * GAMMA ( C ) )
%
%    GAMMA_PDF(A,B,C), where C is an integer, is the Erlang PDF.
%    GAMMA_PDF(A,B,1) is the Exponential PDF.
%    GAMMA_PDF(0,2,C/2) is the Chi Squared PDF with C degrees of freedom.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the PDF.
%    A <= X.
%
%    Input, real A, B, C, the parameters of the PDF.
%    A controls the location of the peak;  A is often chosen to be 0.0.
%    B is the "scale" parameter; 0.0 < B, and is often 1.0.
%    C is the "shape" parameter; 0.0 < C, and is often 1.0.
%
%    Output, real PDF, the value of the PDF.
%
  if ( x <= a )

    pdf = 0.0;

  else

    y = ( x - a ) / b;

    pdf = y^( c - 1.0 ) / ( b * gamma ( c ) * exp ( y ) );

  end

  return
end


function xyz = sphere_cubed_ijk_to_xyz ( n, i, j, k )

%*****************************************************************************80
%
%% SPHERE_CUBED_IJK_TO_XYZ: cubed sphere IJK to XYZ coordinates.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 October 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of sections into which each face of
%    the cube is to be divided.
%
%    Input, integer I, J, K, indices between 0 and N.  Normally,
%    at least one of the indices should have the value 0 or N.
%
%    Output, real XYZ(3,1), coordinates of the point.
%
  if ( i == 0 )
    xc = -1.0;
  elseif ( i == n )
    xc = +1.0;
  else
    xc = tan ( ( 2 * i - n ) * 0.25 * pi / n );
  end

  if ( j == 0 )
    yc = -1.0;
  elseif ( j == n )
    yc = +1.0;
  else
    yc = tan ( ( 2 * j - n ) * 0.25 * pi / n );
  end

  if ( k == 0 )
    zc = -1.0;
  elseif ( k == n )
    zc = +1.0;
  else
    zc = tan ( ( 2 * k - n ) * 0.25 * pi / n );
  end

  xyzn = sqrt ( xc^2 + yc^2 + zc^2 );

  xyz = zeros ( 3, 1 );

  xyz(1) = xc / xyzn;
  xyz(2) = yc / xyzn;
  xyz(3) = zc / xyzn;

  return
end


function variance = r8row_variance ( m, n, x )

%*****************************************************************************80
%
%% R8ROW_VARIANCE returns the variances of an R8ROW.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns in the array.
%
%    Input, real X(M,N), the R8ROW whose row means are desired.
%
%    Output, real VARIANCE(M), the variances of the rows of X.
%
  for i = 1 : m

    mean = sum ( x(i,1:n) ) / n;

    variance(i) = sum ( ( x(i,1:n) - mean ).^2 );

    if ( 1 < n )
      variance(i) = variance(i) / ( n - 1 );
    else
      variance(i) = 0.0;
    end

  end

  return
end


function [Qx,Qy]=CubicBezier1(Px,Py,n)
% Input:
% Px contains x-coordinates of control points [Px0,Px1,Px2,Px3]
% Py contains y-coordinates of control points [Py0,Py1,Py2,Py3]
% n is number of intervals (uniform parameterization)

%Output:
% Qx contains parameteric evaluted x-value
% Qy contains parameteric evaluted y-value

% Equation of Bezier Curve, utilizes Horner's rule for efficient computation.
% Q(t)=(-P0 + 3*(P1-P2) + P3)*t^3 + 3*(P0-2*P1+P2)*t^2 + 3*(P1-P0)*t + Px0

Px0=Px(1);
Py0=Py(1);
Px1=Px(2);
Py1=Py(2);
Px2=Px(3);
Py2=Py(3);
Px3=Px(4);
Py3=Py(4);

cx3=-Px0 + 3*(Px1-Px2) + Px3;
cy3=-Py0 + 3*(Py1-Py2) + Py3;
cx2=3*(Px0-2*Px1+Px2);
cy2=3*(Py0-2*Py1+Py2);
cx1=3*(Px1-Px0);
cy1=3*(Py1-Py0);
cx0=Px0;
cy0=Py0;

dt=1/n;
Qx(1)=Px0; % Qx at t=0
Qy(1)=Py0; % Qy at t=0
for i=1:n
    t=i*dt;
    Qx(i+1)=((cx3*t+cx2)*t+cx1)*t + cx0;
    Qy(i+1)=((cy3*t+cy2)*t+cy1)*t + cy0;
end

% % % --------------------------------
% % % Author: Dr. Murtaza Khan
% % % Email : drkhanmurtaza@gmail.com
% % % --------------------------------


% Minimum volume ellipsoid covering a finite set
% Section 8.4.1, Boyd & Vandenberghe "Convex Optimization"
% Almir Mutapcic - 10/05
% (a figure is generated)
%
% Given a finite set of points x_i in R^2, we find the minimum volume
% ellipsoid (described by matrix A and vector b) that covers all of
% the points by solving the optimization problem:
%
%           maximize     log det A
%           subject to   || A x_i + b || <= 1   for all i
%
% CVX cannot yet handle the logdet function, but this problem can be
% represented in an equivalent way as follows:
%
%           maximize     det(A)^(1/n)
%           subject to   || A x_i + b || <= 1   for all i
%
% The expression det(A)^(1/n) is SDP-representable, and is implemented
% by the MATLAB function det_rootn().

% Generate data
x = [ 0.55  0.0;
      0.25  0.35
     -0.2   0.2
     -0.25 -0.1
     -0.0  -0.3
      0.4  -0.2 ]';
[n,m] = size(x);

% Create and solve the model
cvx_begin
    variable A(n,n) symmetric
    variable b(n)
    maximize( det_rootn( A ) )
    subject to
        norms( A * x + b * ones( 1, m ), 2 ) <= 1;
cvx_end

% Plot the results
clf
noangles = 200;
angles   = linspace( 0, 2 * pi, noangles );
ellipse  = A \ [ cos(angles) - b(1) ; sin(angles) - b(2) ];
plot( x(1,:), x(2,:), 'ro', ellipse(1,:), ellipse(2,:), 'b-' );
axis off


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 f=shah(L,a);
%SHAH  Discrete Shah-distribution
%   Usage: f=shah(L,a);
%
%   `shah(L,a)` computes the discrete, normalized Shah-distribution of
%   length *L* with a distance of *a* between the spikes.
%
%   The Shah distribution is defined by
%
%   .. f(n*a+1)=1/sqrt(L/a)
%
%   .. math:: f(n\cdot a+1)=\frac{1}{\sqrt(L/a)}
%
%   for integer *n*, otherwise *f* is zero.
%
%   This is also known as an impulse train or as the comb function, because
%   the shape of the function resembles a comb. It is the sum of unit
%   impulses ('diracs') with the distance *a*.
%
%   If *a* divides *L*, then the |dft| of `shah(L,a)` is `shah(L,L/a)`.
%
%   The Shah function has an extremely bad time-frequency localization.
%   It does not generate a Gabor frame for any *L* and *a*.
%
%   Examples:
%   ---------
%
%   A simple spectrogram of the Shah function (includes the negative
%   frequencies to display the whole TF-plane):::
%
%     sgram(shah(256,16),'dynrange',80,'nf')
%

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

if nargin~=2
  error('Wrong number of input parameters.');
end;

%if mod(L,a)~=0
%  error('a must divide L.');
%end;

f=zeros(L,1);

f(1:a:L)=1/sqrt(L/a);


function mi = imMutualInformation(img1, img2)
%IMMUTUALINFORMATION  Mutual information between two images
%
%   MI = imMutualInformation(IMG1, IMG2)
%   Computes the mutual information between two images.
%   The mutual information can be related to entropy and joint entropy:
%     MI = H1 + H2 - H12
%   where H1 and H2 are the entropies computed on images IMG1 and IMG2, and
%   H12 is the joint entropy of images IMG1 and IMG2.
%
%   The mutual information between two independant images corresponds to
%   the sum of the entropies computed for each image. The mutual
%   information of an image with itself equals the entropy of this image.
%
%   Example
%   % compute mutual information between an image and a shifted copy of
%   % itself
%     img = imread('cameraman.tif');
%     img2 = circshift(img, [2 3]);
%     MI = imMutualInformation(img, img2)
%     img3 = circshift(img, [5, 7]);
%     MI3 = imMutualInformation(img, img2)
%
%   % Check that we get same results by computing entropies (could be wrong
%   % when computed on double images)
%     img1 = imread('rice.png');
%     img2 = circshift(img1, [3, 4]);
%     imMutualInformation(img1, img2)
%     ans =
%         1.0551
%     h1 = imEntropy(img1);
%     h2 = imEntropy(img2);
%     h12 = imJointEntropy(img1, img2);
%     h1 + h2 - h12
%     ans =
%         1.0551

%   See also
%   imJointEntropy, imJointHistogram, imEntropy
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2010-08-26,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2010 INRA - Cepia Software Platform.

% joint histogram, and reduced hisograms
hist12  = imJointHistogram(img1, img2);
hist1   = sum(hist12, 2);
hist2   = sum(hist12, 1);

% normalisation of histograms
hist12  = hist12(hist12 > 0) / sum(hist12(:));
hist1   = hist1(hist1 > 0) / sum(hist1(:));
hist2   = hist2(hist2 > 0) / sum(hist2(:));

% entropy of each image
h12 = -sum(hist12 .* log2(hist12));
h1  = -sum(hist1  .* log2(hist1));
h2  = -sum(hist2  .* log2(hist2));

% compute mutual information
mi = h1 + h2 - h12;


clear all;
close all;
clc;

targetFolder = './images/';
candidateImages = {'skewed1.gif', 'trapezoid.jpg', 'QR2.jpg', 'QR3.jpg', 'book.jpg', 'square.jpg', 'skewed1.gif' };
candidateChoice = 5;

targetImageFile = strcat(targetFolder , char(candidateImages(candidateChoice )));
targetImageData = imread(targetImageFile);

% 5.1 Undoing Perspective Distortion of Planar Surface
% a)

%book=imread('trapezoid.jpg');
imshow(targetImageData);

% b)
fprintf('Corner selection must be clockwise or anti-clockwise.\n');
[X Y] = ginput(4);

%if ispolycw(X, Y) % if the coordinates are not clockwise, sort them clockwise
%    [X, Y] = poly2cw(X, Y)
%end

%X = uint8(X);
%Y = uint8(Y);
[X Y] = sortPolyFromClockwiseStartingFromTopLeft( X, Y );

x=[1;210;210;1];
y=[1;1;297;297];

% c)
A=zeros(8,8);
A(1,:)=[X(1),Y(1),1,0,0,0,-1*X(1)*x(1),-1*Y(1)*x(1)];
A(2,:)=[0,0,0,X(1),Y(1),1,-1*X(1)*y(1),-1*Y(1)*y(1)];

A(3,:)=[X(2),Y(2),1,0,0,0,-1*X(2)*x(2),-1*Y(2)*x(2)];
A(4,:)=[0,0,0,X(2),Y(2),1,-1*X(2)*y(2),-1*Y(2)*y(2)];

A(5,:)=[X(3),Y(3),1,0,0,0,-1*X(3)*x(3),-1*Y(3)*x(3)];
A(6,:)=[0,0,0,X(3),Y(3),1,-1*X(3)*y(3),-1*Y(3)*y(3)];

A(7,:)=[X(4),Y(4),1,0,0,0,-1*X(4)*x(4),-1*Y(4)*x(4)];
A(8,:)=[0,0,0,X(4),Y(4),1,-1*X(4)*y(4),-1*Y(4)*y(4)];

v=[x(1);y(1);x(2);y(2);x(3);y(3);x(4);y(4)];

u=A\v;
%which reshape

U=reshape([u;1],3,3)';

w=U*[X';Y';ones(1,4)];
w=w./(ones(3,1)*w(3,:));

% d)
%which maketform
T=maketform('projective',U');

%which imtransform
P2=imtransform(targetImageData,T,'XData',[1 210],'YData',[1 297]);

% e)
figure,
imshow(P2)


function [xn, xmean, xstd] = normdata(x,xmean,xstd)
%NORMDATA  Normalize input to zero mean and unit variance
%
%  Description
%    [XN, XMEAN, XSTD] = NORMDATA(X) normalizes X to zero mean and
%    unit variance. Returns normalized XN, mean of X XMEAN and
%    standard deviance of X XSTD.
%
%    XN = NORMDATA(X,XMEAN,XSTD) normalizes X using precomputed
%    XMEAN and XSTD.
%
%  See also DENORMDATA
%
% Copyright (c) 2010 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  if nargin<=1
    xmean=nanmean(x);
    xstd=nanstd(x);
  end
  xn=bsxfun(@rdivide,bsxfun(@minus,x,xmean),xstd);


function r = normal_dataset ( m, n, seed, mu, a )

%*****************************************************************************80
%
%% NORMAL_DATASET generates a multivariate normal dataset and writes it to a file.
%
%  Usage:
%
%    x = normal_dataset ( m, n, seed, mu, a )
%
%    where
%
%    * M the spatial dimension;
%    * N the number of points to generate;
%    * SEED the seed, a positive integer;
%    * MU is the mean vector of dimension M;
%    * A is the MxM positive definite symmetric variance-covariance matrix;
%    * R is the M by N array created.
%
%    The command creates an M by N multivariate normal dataset and writes
%    it to the file "normal_M_N.txt".
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 December 2009
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'NORMAL_DATASET\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Generate a multivariate normal random dataset.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The program requests input values from the user:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  * M, the spatial dimension,\n' );
  fprintf ( 1, '  * N, the number of points to generate,\n' );
  fprintf ( 1, '  * SEED, a seed for the random number generator.\n' );
  fprintf ( 1, '  * MU, the mean vector of length M.\n' );
  fprintf ( 1, '  * A, the MxM positive definite symmetric variance-covariance matrix.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The program generates the data and writes it to the file\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '    normal_M_N.txt\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  where "M" and "N" are the numeric values.\n' );
%
%  Get the spatial dimension.
%
  if ( nargin < 1 )
    fprintf ( 1, '\n' );
    m = input ( '  Enter the spatial dimension M: ' );
  else
    m = str2num ( m );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension M = %d\n', m );
%
%  Get the number of points.
%
  if ( nargin < 2 )
    fprintf ( 1, '\n' );
    n = input ( '  Enter the number of points N: ' );
  else
    n = str2num ( n );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of points N = %d\n', n );
%
%  Get the seed.
%
  if ( nargin < 3 )
    fprintf ( 1, '\n' );
    seed = input ( '  Enter the seed: ' );
  else
    seed = str2num ( seed );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The seed = %d\n', seed );
%
%  Get the mean vector.
%
  if ( nargin < 4 )
    fprintf ( 1, '\n' );
    mu(1:m) = input ( '  Enter the mean vector MU' );
  else
    mu(1:m) = str2num ( mu(1:m) );
  end

  r8vec_print ( m, mu, '  The mean vector MU:' )
%
%  Get the variance-covariance matrix A.
%
  if ( nargin < 5 )
    fprintf ( 1, '\n' );
    a(1:m,1:m) = input ( '  Enter the variance-covariance matrix A' );
  else
    a(1:m,1:m) = str2num ( a(1:m,1:m) );
  end

  r8mat_print ( m, m, a, '  The variance-covariance matrix A:' )
%
%  Compute the data.
%
  r = multinormal_sample ( m, n, a, mu, seed );
%
%  Write it to a file.
%
  output_filename = ...
    strcat ( 'normal_', num2str ( m ), '_', num2str ( n ), '.txt' );

  r8mat_write ( output_filename, m, n, r );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The data was written to the file "%s".\n', ...
    output_filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'NORMAL_DATASET:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function [ x, seed ] = multinormal_sample ( m, n, a, mu, seed )

%*****************************************************************************80
%
%% MULTINORMAL_SAMPLE samples a multivariate normal distribution.
%
%  Discussion:
%
%    The multivariate normal distribution for the M dimensional vector X
%    has the form:
%
%      pdf(X) = (2*pi*det(A))**(-M/2) * exp(-0.5*(X-MU)'*inverse(A)*(X-MU))
%
%    where MU is the mean vector, and A is a positive definite symmetric
%    matrix called the variance-covariance matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 December 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the dimension of the space.
%
%    Input, integer N, the number of points.
%
%    Input, real A(M,M), the variance-covariance
%    matrix.  A must be positive definite symmetric.
%
%    Input, real MU(M), the mean vector.
%
%    Input, integer SEED, the random number seed.
%
%    Output, real X(M), the points.
%
%    Output, integer SEED, the random number seed.
%

%
%  Compute the upper triangular Cholesky factor R of the variance-covariance
%  matrix.
%
  [ r, info ] = r8po_fa ( m, a );

  if ( info ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MULTINORMAL_SAMPLE - Fatal error!\n' );
    fprintf ( 1, ...
      '  The variance-covariance matrix is not positive definite symmetric.\n' );
    error ( 'MULTINORMAL_SAMPLE - Fatal error!' );
  end
%
%  Get an MxN vector of samples of the 1D normal distribution with mean 0
%  and variance 1.
%
  [ x(1:m*n), seed ] = r8vec_normal_01 ( m*n, seed );
%
%  Reshape the vector to an MxN matrix.
%
  x = reshape ( x, m, n );
%
%  Compute MU + R' * X.
%
  for j = 1 : n
    x(1:m,j) = mu(1:m)' + r(1:m,1:m)' * x(1:m,j);
  end

  return
end
function r8mat_print ( m, n, a, title )

%*****************************************************************************80
%
%% R8MAT_PRINT prints an R8MAT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows in A.
%
%    Input, integer N, the number of columns in A.
%
%    Input, real A(M,N), the matrix.
%
%    Input, string TITLE, a title to be printed.
%
  r8mat_print_some ( m, n, a, 1, 1, m, n, title );

  return
end
function r8mat_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% R8MAT_PRINT_SOME prints out a portion of an R8MAT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 September 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns of the matrix.
%
%    Input, real A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, a title.
%
  incx = 5;

  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );

  for j2lo = max ( jlo, 1 ): incx : min ( jhi, n )

    j2hi = j2lo + incx - 1;
    j2hi = min ( j2hi, n );
    j2hi = min ( j2hi, jhi );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col: ' );

    for j = j2lo : j2hi
      fprintf ( 1, '%7d       ', j );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row\n' );

    i2lo = max ( ilo, 1 );
    i2hi = min ( ihi, m );

    for i = i2lo : i2hi

      fprintf ( 1, '%7d  ', i );

      for j = j2lo : j2hi
        fprintf ( 1, '%12g  ', a(i,j) );
      end

      fprintf ( 1, '\n' );

    end

  end

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

%*****************************************************************************80
%
%% R8MAT_WRITE writes an R8MAT file.
%
%  Discussion:
%
%    An R8MAT is an array of R8's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real TABLE(M,N), the points.
%

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

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'R8MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
%  For smaller data files, and less precision, try:
%
%     fprintf ( output_unit, '  %14.6f', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %24.16f', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function [ r, info ] = r8po_fa ( n, a )

%*****************************************************************************80
%
%% R8PO_FA factors a R8PO matrix.
%
%  Discussion:
%
%    The R8PO storage format is appropriate for a symmetric positive definite
%    matrix and its inverse.  (The Cholesky factor of a R8PO matrix is an
%    upper triangular matrix, so it will be in R8GE storage format.)
%
%    Only the diagonal and upper triangle of the square array are used.
%    This same storage scheme is used when the matrix is factored by
%    R8PO_FA, or inverted by R8PO_INVERSE.  For clarity, the lower triangle
%    is set to zero.
%
%    The positive definite symmetric matrix A has a Cholesky factorization
%    of the form:
%
%      A = R' * R
%
%    where R is an upper triangular matrix with positive elements on
%    its diagonal.  This routine overwrites the matrix A with its
%    factor R.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 February 2004
%
%  Author:
%
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Dongarra, Bunch, Moler, Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Input, real A(N,N), the matrix in R8PO storage.
%
%    Output, real R(N,N), the Cholesky factor R in R8GE storage.
%
%    Output, integer INFO, error flag.
%    0, normal return.
%    K, error condition.  The principal minor of order K is not
%    positive definite, and the factorization was not completed.
%
  r(1:n,1:n) = a(1:n,1:n);

  for j = 1 : n

    for k = 1 : j - 1
      t = 0.0;
      for i = 1 : k-1
        t = t + r(i,k) * r(i,j);
      end
      r(k,j) = ( r(k,j) - t ) / r(k,k);
    end

    t = 0.0;
    for i = 1 : j - 1
      t = t + r(i,j)^2;
    end

    s = r(j,j) - t;

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

    r(j,j) = sqrt ( s );

  end

  info = 0;
%
%  Since the Cholesky factor is stored in R8GE format, be sure to
%  zero out the lower triangle.
%
  for i = 1 : n
    for j = 1 : i-1
      r(i,j) = 0.0;
    end
  end

  return
end
function [ x, seed ] = r8vec_normal_01 ( n, seed )

%*****************************************************************************80
%
%% R8VEC_NORMAL_01 returns a unit pseudonormal R8VEC.
%
%  Discussion:
%
%    The standard normal probability distribution function (PDF) has
%    mean 0 and standard deviation 1.
%
%    This routine can generate a vector of values on one call.  It
%    has the feature that it should provide the same results
%    in the same order no matter how we break up the task.
%
%    Before calling this routine, the user may call RANDOM_SEED
%    in order to set the seed of the random number generator.
%
%    The Box-Muller method is used, which is efficient, but
%    generates an even number of values each time.  On any call
%    to this routine, an even number of new values are generated.
%    Depending on the situation, one value may be left over.
%    In that case, it is saved for the next call.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 July 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of values desired.  If N is negative,
%    then the code will flush its internal memory; in particular,
%    if there is a saved value to be used on the next call, it is
%    instead discarded.  This is useful if the user has reset the
%    random number seed, for instance.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real X(N), a sample of the standard normal PDF.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
%  Local parameters:
%
%    Local, integer MADE, records the number of values that have
%    been computed.  On input with negative N, this value overwrites
%    the return value of N, so the user can get an accounting of
%    how much work has been done.
%
%    Local, real R(N+1), is used to store some uniform random values.
%    Its dimension is N+1, but really it is only needed to be the
%    smallest even number greater than or equal to N.
%
%    Local, integer SAVED, is 0 or 1 depending on whether there is a
%    single saved value left over from the previous call.
%
%    Local, integer X_LO_INDEX, X_HI_INDEX, records the range of entries of
%    X that we need to compute.  This starts off as 1:N, but is adjusted
%    if we have a saved value that can be immediately stored in X(1),
%    and so on.
%
%    Local, real Y, the value saved from the previous call, if
%    SAVED is 1.
%
  persistent made;
  persistent saved;
  persistent y;
%
%  I'd like to allow the user to reset the internal data.
%  But this won't work properly if we have a saved value Y.
%  I'm making a crock option that allows the user to signal
%  explicitly that any internal memory should be flushed,
%  by passing in a negative value for N.
%
  if ( n < 0 )
    made = 0;
    saved = 0;
    y = 0.0;
    x = [];
    return
  elseif ( n == 0 )
    x = [];
    return
  end
%
%  Record the range of X we need to fill in.
%
  x_lo_index = 1;
  x_hi_index = n;
%
%  Use up the old value, if we have it.
%
  if ( saved == 1 )
    x(1) = y;
    saved = 0;
    x_lo_index = 2;
  end
%
%  Maybe we don't need any more values.
%
  if ( x_hi_index - x_lo_index + 1 == 0 )
%
%  If we need just one new value, do that here to avoid null arrays.
%
  elseif ( x_hi_index - x_lo_index + 1 == 1 )

    [ r, seed ] = r8vec_uniform_01 ( 2, seed );

    x(x_hi_index) = ...
      sqrt ( -2.0 * log ( r(1) ) ) * cos ( 2.0 * pi * r(2) );
    y =      sqrt ( -2.0 * log ( r(1) ) ) * sin ( 2.0 * pi * r(2) );

    saved = 1;

    made = made + 2;
%
%  If we require an even number of values, that's easy.
%
  elseif ( mod ( x_hi_index - x_lo_index + 1, 2 ) == 0 )

    m = floor ( ( x_hi_index - x_lo_index + 1 ) / 2 );

    [ r, seed ] = r8vec_uniform_01 ( 2*m, seed );

    x(x_lo_index:2:x_hi_index-1) = ...
      sqrt ( -2.0 * log ( r(1:2:2*m-1) ) ) ...
      .* cos ( 2.0 * pi * r(2:2:2*m) );

    x(x_lo_index+1:2:x_hi_index) = ...
      sqrt ( -2.0 * log ( r(1:2:2*m-1) ) ) ...
      .* sin ( 2.0 * pi * r(2:2:2*m) );

    made = made + x_hi_index - x_lo_index + 1;
%
%  If we require an odd number of values, we generate an even number,
%  and handle the last pair specially, storing one in X(N), and
%  saving the other for later.
%
  else

    x_hi_index = x_hi_index - 1;

    m = floor ( ( x_hi_index - x_lo_index + 1 ) / 2 ) + 1;

    [ r, seed ] = r8vec_uniform_01 ( 2*m, seed );

    x(x_lo_index:2:x_hi_index-1) = ...
      sqrt ( -2.0 * log ( r(1:2:2*m-3) ) ) ...
      .* cos ( 2.0 * pi * r(2:2:2*m-2) );

    x(x_lo_index+1:2:x_hi_index) = ...
      sqrt ( -2.0 * log ( r(1:2:2*m-3) ) ) ...
      .* sin ( 2.0 * pi * r(2:2:2*m-2) );

    x(n) = sqrt ( -2.0 * log ( r(2*m-1) ) ) ...
      * cos ( 2.0 * pi * r(2*m) );

    y = sqrt ( -2.0 * log ( r(2*m-1) ) ) ...
      * sin ( 2.0 * pi * r(2*m) );

    saved = 1;

    made = made + x_hi_index - x_lo_index + 2;

  end

  return
end
function r8vec_print ( n, a, title )

%*****************************************************************************80
%
%% R8VEC_PRINT prints a real vector.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 January 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the dimension of the vector.
%
%    Input, real A(N), the vector to be printed.
%
%    Input, string TITLE, a title.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );
  fprintf ( 1, '\n' );
  for i = 1 : n
    fprintf ( 1, '%6d  %12f\n', i, a(i) );
  end

  return
end
function [ r, seed ] = r8vec_uniform_01 ( n, seed )

%*****************************************************************************80
%
%% R8VEC_UNIFORM_01 returns a unit pseudorandom R8VEC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Paul Bratley, Bennett Fox, Linus Schrage,
%    A Guide to Simulation,
%    Second Edition,
%    Springer, 1987,
%    ISBN: 0387964673,
%    LC: QA76.9.C65.B73.
%
%    Bennett Fox,
%    Algorithm 647:
%    Implementation and Relative Efficiency of Quasirandom
%    Sequence Generators,
%    ACM Transactions on Mathematical Software,
%    Volume 12, Number 4, December 1986, pages 362-376.
%
%    Pierre L'Ecuyer,
%    Random Number Generation,
%    in Handbook of Simulation,
%    edited by Jerry Banks,
%    Wiley, 1998,
%    ISBN: 0471134031,
%    LC: T57.62.H37.
%
%    Peter Lewis, Allen Goodman, James Miller,
%    A Pseudo-Random Number Generator for the System/360,
%    IBM Systems Journal,
%    Volume 8, Number 2, 1969, pages 136-143.
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real R(N), the vector of pseudorandom values.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
  i4_huge = 2147483647;

  if ( seed == 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8VEC_UNIFORM_01 - Fatal error!\n' );
    fprintf ( 1, '  Input SEED = 0!\n' );
    error ( 'R8VEC_UNIFORM_01 - Fatal error!' );
  end

  r = zeros ( n, 1 );

  for i = 1 : n

    k = floor ( seed / 127773 );

    seed = 16807 * ( seed - k * 127773 ) - k * 2836;

    if ( seed < 0 )
      seed = seed + i4_huge;
    end

    r(i) = seed * 4.656612875E-10;

  end

  return
end
function timestamp ( )

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

  return
end


% IM = mkSine(SIZE, PERIOD, DIRECTION, AMPLITUDE, PHASE, ORIGIN)
%      or
% IM = mkSine(SIZE, FREQ, AMPLITUDE, PHASE, ORIGIN)
%
% Compute a matrix of dimension SIZE (a [Y X] 2-vector, or a scalar)
% containing samples of a 2D sinusoid, with given PERIOD (in pixels),
% DIRECTION (radians, CW from X-axis, default = 0), AMPLITUDE (default
% = 1), and PHASE (radians, relative to ORIGIN, default = 0).  ORIGIN
% defaults to the center of the image.
%
% In the second form, FREQ is a 2-vector of frequencies (radians/pixel).

% Eero Simoncelli, 6/96.

function [res] = mkSine(sz, per_freq, dir_amp, amp_phase, phase_orig, orig)

%------------------------------------------------------------
%% OPTIONAL ARGS:

if (prod(size(per_freq)) == 2)
  frequency = norm(per_freq);
  direction = atan2(per_freq(1),per_freq(2));
  if (exist('dir_amp') == 1)
    amplitude = dir_amp;
  else
    amplitude = 1;
  end
  if (exist('amp_phase') == 1)
    phase = amp_phase;
  else
    phase = 0;
  end
  if (exist('phase_orig') == 1)
    origin = phase_orig;
  end
  if (exist('orig') == 1)
    error('Too many arguments for (second form) of mkSine');
  end
else
  frequency = 2*pi/per_freq;
  if (exist('dir_amp') == 1)
    direction = dir_amp;
  else
    direction = 0;
  end
  if (exist('amp_phase') == 1)
    amplitude = amp_phase;
  else
    amplitude = 1;
  end
  if (exist('phase_orig') == 1)
    phase = phase_orig;
  else
    phase = 0;
  end
  if (exist('orig') == 1)
    origin = orig;
  end
end

%------------------------------------------------------------

if (exist('origin') == 1)
  res = amplitude*sin(mkRamp(sz, direction, frequency, phase, origin));
else
 res = amplitude*sin(mkRamp(sz, direction, frequency, phase));
end


% IM = mkAngle(SIZE, PHASE, ORIGIN)
%
% Compute a matrix of dimension SIZE (a [Y X] 2-vector, or a scalar)
% containing samples of the polar angle (in radians, CW from the
% X-axis, ranging from -pi to pi), relative to angle PHASE (default =
% 0), about ORIGIN pixel (default = (size+1)/2).

% Eero Simoncelli, 6/96.

function [res] = mkAngle(sz, phase, origin)

sz = sz(:);
if (size(sz,1) == 1)
  sz = [sz,sz];
end

% -----------------------------------------------------------------
% OPTIONAL args:

if (exist('origin') ~= 1)
  origin = (sz+1)/2;
end

% -----------------------------------------------------------------

[xramp,yramp] = meshgrid( [1:sz(2)]-origin(2), [1:sz(1)]-origin(1) );

res = atan2(yramp,xramp);

if (exist('phase') == 1)
  res = mod(res+(pi-phase),2*pi)-pi;
end


function center = polylineCentroid(varargin)
%POLYLINECENTROID Computes the centroid of a curve defined by a series of points.
%
%   PT = polylineCentroid(POINTS);
%   Computes center of mass of a polyline defined by POINTS. POINTS is a
%   N-by-D array of double, representing a set of N points in a
%   D-dimensional space.
%
%   PT = polylineCentroid(PTX, PTY);
%   PT = polylineCentroid(PTX, PTY, PTZ);
%   Specifies points as separate column vectors
%
%   PT = polylineCentroid(..., TYPE);
%   Specifies if the last point is connected to the first one. TYPE can be
%   either 'closed' or 'open'.
%
%   Example
%   poly = [0 0;10 0;10 10;20 10];
%   polylineCentroid(poly)
%   ans =
%       [10 5]
%
%   See also
%     polygons2d, centroid, polygonCentroid, polylineLength
%

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2006-05-22
% Copyright 2006-2022 INRA - TPV URPOI - BIA IMASTE

%% process input arguments

% check whether the curve is closed
closed = false;
var = varargin{end};
if ischar(var)
    if strcmpi(var, 'closed')
        closed = true;
    end
    % remove last argument
    varargin(end) = [];
end

% extract point coordinates
if length(varargin)==1
    points = varargin{1};
elseif length(varargin)==2
    points = [varargin{1} varargin{2}];
end

%% Main computation

% compute centers and lengths composing the curve
if closed
    centers = (points + points([2:end 1],:))/2;
    lengths = sqrt(sum(diff(points([1:end 1],:)).^2, 2));
else
    centers = (points(1:end-1,:) + points(2:end,:))/2;
    lengths = sqrt(sum(diff(points).^2, 2));
end

% centroid of edge centers weighted by edge length
%weigths = repmat(lengths/sum(lengths), [1 size(points, 2)]);
center = sum(centers .* repmat(lengths, [1 size(points, 2)]), 1) / sum(lengths);


function cdf = sech_cdf ( x, a, b )

%*****************************************************************************80
%
%% SECH_CDF evaluates the Hyperbolic Secant CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the PDF.
%
%    Input, real A, B, the parameter of the PDF.
%    0.0 < B.
%
%    Output, real CDF, the value of the CDF.
%
  y = ( x - a ) / b;

  cdf = 2.0 * atan ( exp ( y ) ) / pi;

  return
end


function [xn, xmean, xstd] = normdata(x,xmean,xstd)
%NORMDATA  Normalize input to zero mean and unit variance
%
%  Description
%    [XN, XMEAN, XSTD] = NORMDATA(X) normalizes X to zero mean and
%    unit variance. Returns normalized XN, mean of X XMEAN and
%    standard deviance of X XSTD.
%
%    XN = NORMDATA(X,XMEAN,XSTD) normalizes X using precomputed
%    XMEAN and XSTD.
%
%  See also DENORMDATA
%

% Copyright (c) 2010 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

  if nargin<=1
    xmean=nanmean(x);
    xstd=nanstd(x);
  end
  xn=bsxfun(@rdivide,bsxfun(@minus,x,xmean),xstd);


function [FisoInd]=faceIsotropyIndex(F,V)
%% function for computing  triangular faces isotropy index.
% This is an index of the  "regularity" of the triangle. Equilateral triangle (perfectly regular)
%
% INPUTS:
% * F: nFaces-by-3 array representing the list of vertices for triangular faces
% * V: nVertices-by-3 array representing the 3d positions of the vertices of F in the reference positions
%
% OUTPUTS:
% * FisoInd: isotropy index for each face. value of 1 means perfectly
% equilateral. value of 0 means vertices are aligned (on a line)
%
%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
%%

FisoInd=zeros(size(F,1),1);
for iface=1:size(F,1)

    x1=V(F(iface,1),:)';
    x2=V(F(iface,2),:)';
    x3=V(F(iface,3),:)';

    if any(any(isnan([x1 x2 x3]))) % if any nan, iso index=nan
        FisoInd(iface)=NaN;
    else
        xa=(x1+x2+x3)/3;
        X=[x1-xa,x2-xa,x3-xa]; %cluster position model
        K=X*X'/3;
        Keig=real(eig(K)); %eigenvalues of X
        FisoInd(iface)=2*Keig(2)/(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>


%% Example of clustering with RSS, AIC and BIC
clear all; close all;

%% Generate Random Clusters from GMM
clear all; close all;
num_samples         = 400;
num_classes         = 4;
dim                 = 2;
[X,labels,gmm]      = ml_clusters_data(num_samples,dim,num_classes);
options.title       = '2D Mixture of Gaussians Dataset';
options.labels      = labels;
[N,D]               = size(X);

if exist('h1','var') && isvalid(h1), delete(h1);end
h1 = ml_plot_data(X,options);
axis equal;

%% Generate Perfect circle
clear all; clc;
nb_samples  = 100;
phi         = linspace(0,2 * pi,nb_samples);
r           = 10;
X           = [r .* cos(phi(:)), r .* sin(phi(:))];
% Plot circle points

plot_options                = [];
plot_options.title          = 'Circle';

if exist('h1','var') && isvalid(h1), delete(h1);end
h1  = ml_plot_data(X,plot_options);
axis square;

%% Find optimal K  for K-means according to metrics
[N,D]                       = size(X);
cluster_options             = [];
cluster_options.method_name = 'kmeans';
repeats                     = 1;
Ks                          = 1:N;
[mus, stds]                 = ml_clustering_optimise(X,Ks,repeats,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);

RSS_curve = mus(1,:);
AIC_curve = mus(2,:);
BIC_curve = mus(3,:);

%% Plot RSS curve
clc;
if exist('h_rss','var')     && isvalid(h_rss),     delete(h_rss);    end
h_rss = figure;hold on;

plot(RSS_curve,'--', 'LineWidth', 1); hold on;

% Find optimal value on RSS curve
[opt_RSS_vals, opt_Ks_RSS] = ml_curve_opt(RSS_curve,'line');
plot(opt_Ks_RSS, RSS_curve(opt_Ks_RSS) ,'s','Color',[1 0 0]); hold on;
[opt_RSS_vals, opt_Ks_RSS] = ml_curve_opt(RSS_curve,'derivatives');
plot(opt_Ks_RSS, RSS_curve(opt_Ks_RSS) ,'s','Color',[1 0 0]); hold on;
grid on;
box on;
legend('RSS','Location','northeast')
xlabel('K')
title('K-means Evaluation Metrics')

disp(['(RSS) Optimal K: ', num2str(opt_Ks_RSS(1))])

%% Find optimal value on AIC/BIC curve
clc;
if exist('h_rss','var')     && isvalid(h_rss),     delete(h_rss);    end
h_rss = figure;hold on;

plot(RSS_curve,'--', 'LineWidth', 1); hold on;
plot(AIC_curve,'--', 'LineWidth', 1); hold on;
plot(BIC_curve,'--', 'LineWidth', 1); hold on;

% Find optimal value on RSS curve
[opt_RSS_vals, opt_Ks_RSS] = ml_curve_opt(RSS_curve,'derivatives');
plot(opt_Ks_RSS, RSS_curve(opt_Ks_RSS) ,'s','Color',[1 0 0]); hold on;

% Find optimal value on AIC curve
[~, opt_Ks_AIC] = min(AIC_curve);
plot(opt_Ks_AIC, AIC_curve(opt_Ks_AIC) ,'s','Color',[1 0 0]); hold on;

% Find optimal value on BIC curve
[~, opt_Ks_BIC] = min(BIC_curve);
plot(opt_Ks_BIC, BIC_curve(opt_Ks_BIC) ,'s','Color',[1 0 0]); hold on;

grid on;
box on;
legend('RSS', 'AIC', 'BIC','Location','northwest')
xlabel('K')
title('K-means Evaluation Metrics')

disp(['(RSS) Optimal K: ', num2str(opt_Ks_RSS)])
disp(['(AIC) Optimal K: ', num2str(opt_Ks_AIC)])
disp(['(BIC) Optimal K: ', num2str(opt_Ks_BIC)])

%% K-means

cluster_options             = [];
cluster_options.method_name = 'kmeans';
cluster_options.K           = opt_Ks_RSS(1);

result1                     = ml_clustering(X,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);
result1.lambda              = 2;
[rss,aic,bic]               = ml_clustering_eval(X,result1);

% Plot decision boundary

if exist('hd','var') && isvalid(hd), delete(hd);end
hd = ml_plot_class_boundary(X,result1);
%% Search for optimal \lambda value in AIC(RSS)
clc;
cluster_options             = [];
cluster_options.method_name = 'kmeans';

% Compute Maximum RSS values (when K=1,\alpha)
[N,D]       = size(X);
alpha       = N/4;
repeats     = 1;
K           = 1:alpha;
[mus, stds] = ml_clustering_optimise(X,K,repeats,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);

% Compute lower/upper bounds of \lambda values according to limits derived
% in slide 9,12,13 of TP2-Metrics-Recap
rss_k1         = mus(1,1);
rss_k2         = mus(1,alpha);
upper_lambda   = (rss_k1 - rss_k2) / (alpha*D);
lower_lambda   = (rss_k1) / (D*N);
lambda_range   = [ceil(lower_lambda):1:ceil(upper_lambda)+1];

% Plot AIC(RSS) with a constrained range of lambda's
clc;
if exist('h_aic','var')     && isvalid(h_aic),     delete(h_aic);    end
h_aic = figure;hold on;
leg_names = [];
aic_mins = [];
for l=1:length(lambda_range)
    cluster_options.lambda    = lambda_range(l); %Magic number
    repeats                   = 1;
    Ks                        = 1:N;
    [mus, stds]               = ml_clustering_optimise(X,Ks,repeats,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);
    plot(mus(2,:),'-');
    hold on;
    [min_aic, min_k] = min(mus(2,:));
    leg_names = [leg_names; {strcat('\lambda= ',num2str(lambda_range(l)))}];
    aic_mins = [aic_mins; [min_aic, min_k]];
end
legend(leg_names);
grid on;
box on;
xlabel('K');
title('AIC(RSS) for K-means')

if exist('h_bic','var')     && isvalid(h_bic),     delete(h_bic);    end
h_bic = figure;hold on;
plot(mus(3,:),'-');
grid on;
box on;
xlabel('K');
title('BIC(RSS) for K-means')


% Find the Least Root Mean Square distance
% between two sets of N points in D dimensions
% and the rigid transformation (i.e. translation and rotation)
% to employ in order to bring one set that close to the other,
% Using the Kabsch (1976) algorithm.
% Note that the points are paired, i.e. we know which point in one set
% should be compared to a given point in the other set.
%
% References:
% 1) Kabsch W. A solution for the best rotation to relate two sets of vectors. Acta Cryst A 1976;32:9223.
% 2) Kabsch W. A discussion of the solution for the best rotation to relate two sets of vectors. Acta Cryst A 1978;34:8278.
% 3) http://cnx.org/content/m11608/latest/
% 4) http://en.wikipedia.org/wiki/Kabsch_algorithm
%
% We slightly generalize, allowing weights given to the points.
% Those weights are determined a priori and do not depend on the distances.
%
% We work in the convention that points are column vectors;
% some use the convention where they are row vectors instead.
%
% Input  variables:
%  P : a D*N matrix where P(a,i) is the a-th coordinate of the i-th point
%      in the 1st representation
%  Q : a D*N matrix where Q(a,i) is the a-th coordinate of the i-th point
%      in the 2nd representation
%  m : (Optional) a row vector of length N giving the weights, i.e. m(i) is
%      the weight to be assigned to the deviation of the i-th point.
%      If not supplied, we take by default the unweighted (or equal weighted)
%      m(i) = 1/N.
%      The weights do not have to be normalized;
%      we divide by the sum to ensure sum_{i=1}^N m(i) = 1.
%      The weights must be non-negative with at least one positive entry.
% Output variables:
%  U : a proper orthogonal D*D matrix, representing the rotation
%  r : a D-dimensional column vector, representing the translation
%  lrms: the Least Root Mean Square
%
% Details:
% If p_i, q_i are the i-th point (as a D-dimensional column vector)
% in the two representations, i.e. p_i = P(:,i) etc., and for
% p_i' = U p_i + r      (' does not stand for transpose!)
% we have p_i' ~ q_i, that is,
% lrms = sqrt(sum_{i=1}^N m(i) (p_i' - q_i)^2)
% is the minimal rms when going over the possible U and r.
% (assuming the weights are already normalized).
%
function[U, r, lrms] = Kabsch(P, Q, m)
	sz1 = size(P) ;
	sz2 = size(Q) ;
	if (length(sz1) ~= 2 || length(sz2) ~= 2)
		error 'P and Q must be matrices' ;
	end
	if (any(sz1 ~= sz2))
		error 'P and Q must be of same size' ;
	end
	D = sz1(1) ;         % dimension of space
	N = sz1(2) ;         % number of points
	if (nargin >= 3)
		if (~isvector(m) || any(size(m) ~= [1 N]))
			error 'm must be a row vector of length N' ;
		end
		if (any(m < 0))
			error 'm must have non-negative entries' ;
		end
		msum = sum(m) ;
		if (msum == 0)
			error 'm must contain some positive entry' ;
		end
		m = m / msum ;     % normalize so that weights sum to 1
	else                 % m not supplied - use default
		m = ones(1,N)/N ;
	end

	p0 = P*m' ;          % the centroid of P
	q0 = Q*m' ;          % the centroid of Q
	v1 = ones(1,N) ;     % row vector of N ones
	P = P - p0*v1 ;      % translating P to center the origin
	Q = Q - q0*v1 ;      % translating Q to center the origin

	% C is a covariance matrix of the coordinates
	% C = P*diag(m)*Q'
	% but this is inefficient, involving an N*N matrix, while typically D << N.
	% so we use another way to compute Pdm = P*diag(m),
	% which is equivalent to, but more efficient than,
	% Pdm = zeros(D,N) ;
	% for i=1:N
	% 	Pdm(:,i) = m(i)*P(:,i) ;
	% end
	Pdm = bsxfun(@times,m,P) ;
	C = Pdm*Q' ;
%	C = P*Q' / N ;       % (for the non-weighted case)
	[V,S,W] = svd(C) ;   % singular value decomposition
	I = eye(D) ;
	if (det(V*W') < 0)   % more numerically stable than using (det(C) < 0)
		I(D,D) = -1 ;
	end
	U = W*I*V' ;

	r = q0 - U*p0 ;

	Diff = U*P - Q ;     % P, Q already centered
%	lrms = sqrt(sum(sum(Diff.*Diff))/N) ; % (for the non-weighted case)
	% to compute the lrms, we employ an efficient method, equivalent to:
	% lrms = 0 ;
	% for i=1:N
	% 	lrms = lrms + m(i)*Diff(:,i)'*Diff(:,i) ;
	% end
	% lrms = sqrt(lrms) ;
	lrms = sqrt(sum(sum(bsxfun(@times,m,Diff).*Diff))) ;
end


function [J, grad] = costFunction(theta, X, y)
%COSTFUNCTION Compute cost and gradient for logistic regression
%   J = COSTFUNCTION(theta, X, y) computes the cost of using theta as the
%   parameter for logistic regression and the gradient of the cost
%   w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%
% Note: grad should have the same dimensions as theta
%
h_theta = sigmoid(X*theta);
J = (1 / m) * ((-y' * log(h_theta)) - (1 - y)' * log(1 - h_theta));

grad = (1 / m) * (h_theta - y)' * X;

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

end


% gerschdisc.m
%
% This function plots the Gershgorin Discs for the matrix A passed as an argument.
% It will also plot the centers of such discs, and the actual eigenvalues
% of the matrix.

function gershdisc(A)

error(nargchk(nargin,1,1));
if size(A,1) ~= size(A,2)
    error('Matrix should be square');
    return;
end

% For each row, we say:
for i=1:size(A,1)
    % The circle has center in (h,k) where h is the real part of A(i,i) and
    % k is the imaginary part of A(i,i)   :
    h=real(A(i,i)); k=imag(A(i,i));

    % Now we try to compute the radius of the circle, which is nothing more
    % than the sum of norm of the elements in the row where i != j
    r=0;
    for j=1:size(A,1)
       if i ~= j
           r=r+(norm(A(i,j)));
       end
    end

    % We try to make a vector of points for the circle:
    N=256;
    t=(0:N)*2*pi/N;

    % Now we're able to map each of the elements of this vector into a
    % circle:
    plot( r*cos(t)+h, r*sin(t)+k ,'-');

    % We also plot the center of the circle for better undesrtanding:
    hold on;
    plot( h, k,'+');
end

% For the circles to be better graphed, we would like to have equal axis:
axis equal;

% Now we plot the actual eigenvalues of the matrix:
ev=eig(A);
for i=1:size(ev)
    rev=plot(real(ev(i)),imag(ev(i)),'ro');
end
hold off;
legend(rev,'Actual Eigenvalues');

end


function chi2 = chi_squared(y,fit,P,eb)

% returns *reduced* chi^2 value for use in data modelling
% "y" is a vector of data, "fit" is a vector of model values (size(fit)=size(y)), P is the number of
% parameters fit in the model, and eb is a vector of error bars (1-to-1 correspondnce with y)
% Ref: John R. Taylor, "An Introduction to Error Analysis", (2nd ed., 1997)
% 11/11/01 Mike Scarpulla.  Please direct questions or comments to scarps@uclink.berkeley.edu
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin<3
    error('Wrong number of arguments passed to "chi_squared"')
end

% if error bars are not availible, evaluate chi^2 by normalizing deviation^2 by magnitude of data.
% This assumes that the STDEV of a value scales as SQRT(value).  USE WITH THIS CAVEAT IN MIND
if nargin==3
    N = max(size(y));
    terms = ((y-fit).^2)./abs(y);
    chi2 = 1/(N-P)*sum(terms);
end

%if error bars are availible, normalize the deviation to the expectred error
if nargin==4
    N = max(size(y));
    terms = ((y-fit)./eb).^2;
    chi2 = 1/(N-P)*sum(terms);
end


function y = r8vec_sqctf ( n, x )

%*****************************************************************************80
%
%% R8VEC_SQCTF computes a "slow" quarter cosine transform forward of an R8VEC.
%
%  Discussion:
%
%    This routine is provided for illustration and testing.  It is inefficient
%    relative to optimized routines that use fast Fourier techniques.
%
%    For 0 <= I <= N-1,
%
%      Y(I) = (1/N) Sum ( 0 <= J <= N-1 ) X(J) * cos ( PI * I * (J+1/2) / N )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    William Briggs, Van Emden Henson,
%    The Discrete Fourier Transform,
%    SIAM, 1995,
%    QA403.5 B75
%
%  Parameters:
%
%    Input, integer N, the number of data values.
%
%    Input, real X(N), the data sequence.
%
%    Output, real Y(N), the transformed data.
%
  y(1:n) = 0.0;

  for i = 1 : n
    for j = 1 : n
      theta = 0.5 * pi * ( i - 1 ) * ( 2 * j - 1 ) / n;
      y(i) = y(i) + x(j) * cos ( theta  );
    end
  end

  y(1:n) = y(1:n) / n;

  return
end


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

%*****************************************************************************80
%
%% LOG_SERIES_SAMPLE samples the Logarithmic Series PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 March 1999
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Luc Devroye,
%    Non-Uniform Random Variate Generation,
%    Springer-Verlag, New York, 1986, page 547.
%
%  Parameters:
%
%    Input, real A, the parameter of the PDF.
%    0.0 < A < 1.0.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, integer X, a sample of the PDF.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
  [ u, seed ] = r8_uniform_01 ( seed );
  [ v, seed ] = r8_uniform_01 ( seed );

  x = floor ( 1.0 + log ( v ) / ( log ( 1.0 - ( 1.0 - a )^u ) ) );

  return
end


%DECOMPOSEHOMOGRAPHYMAT  Decompose a homography matrix to rotation(s), translation(s) and plane normal(s)
%
%     [motions, nsols] = cv.decomposeHomographyMat(H, K)
%
% ## Input
% * __H__ The input homography matrix between two images, 3x3.
% * __K__ The input intrinsic camera calibration matrix, 3x3.
%
% ## Output
% * __motions__ Decomposed `H`. A scalar struct with the following fields:
%   * __R__ Array of rotation matrices. Cell array of 3x3 rotations.
%   * __t__ Array of translation matrices. Cell array of 3x1 translations.
%   * __n__ Array of plane normal matrices. Cell array of 3x1 normals.
% * __nsols__ number of solutions.
%
% This function extracts relative camera motion between two views observing a
% planar object from the homography `H` induced by the plane. The intrinsic
% camera matrix `K` must also be provided. The function may return up to four
% mathematical solution sets. At least two of the solutions may further be
% invalidated if point correspondences are available by applying positive
% depth constraint (all points must be in front of the camera). The
% decomposition method is described in detail in [Malis]:
%
%     H = s * K * (R{i} + t{i} * n{i}') * inv(K),  for i=1:nsols
%
% `s` is a scaling factor approximated as:
%
%     s = median(svd(inv(K) * H * K))
%
% ## References
% [Malis]:
% > Ezio Malis, Manuel Vargas, and others. "Deeper understanding of the
% > homography decomposition for vision-based control". 2007.
%
% See also: cv.findHomography, cv.decomposeEssentialMat
%


function vout=nextchoose(v,w)
%NEXTCHOOSE  find the next choice of k elements from a vector (with possible repeats)
% usage: vout = nextchoose(v,w)
%
% NEXTCHOOSE(V,W), where V is a row or column vector of integers in W,
% returns the next choice of length(V) elements from W by lexical ordering
% (see below) or [] if there is none.  W can also be specified as a
% positive integer N, in which case W=1:N.
%
% NEXTCHOOSE can be used to iterate through all unique k-combinations in
% 1:N but keep in mind that the number is nchoosek(N,length(V))
%
% In the set of all k-combinations of W, with lexical order:
% - V is equivalent to sort(V)
% - pairs are ordered according to the first sorted elements that differ
% - the "first" choice is V0=W(1:k) (if W is sorted)
% - the "last" choice is V1=W(N-k+1:N) (if W is sorted, and N=numel(W))
% - the successor of V is determined according to the rightmost elements
%   such that V(i)=W(j) and j < N-(k-i). Then V(i:k) -> W(j+1:j+k-i+1)
%
% Example 1:
%   nextchoose([1,2,3],4)       % returns [1,2,4]
%   nextchoose([1,2,4],4)       % returns [1,3,4]
%   nextchoose([1,3,4],4)       % returns [2,3,4]
%   nextchoose([2,3,4],4)       % returns []
%
% Example 2: choose 2 elements from a vector with repeats
%   nextchoose([1,2],[1,2,2,3]) % returns [1,3]
%   nextchoose([1,3],[1,2,2,3]) % returns [2,2]
%   nextchoose([2,2],[1,2,2,3]) % returns [2,3]
%   nextchoose([2,3],[1,2,2,3]) % returns []
%
% Example 3: determine all 4-combinations of 1:8
%   n=8;
%   k=4;
%   v=1:k;
%   M=zeros(nchoosek(n,k),k);
%   i=0;
%   while ~isempty(v),
%     i=i+1;
%     M(i,:)=v;
%     v=nextchoose(v,n);
%   end;
%   isequal(M,sortrows(nchoosek(1:n,k))) % =1

% Author: Ben Petschel 25/6/2009
%
% Change history:
%  25/6/2009 - first release (modelled after nextperm.m)
%  29/6/2009 - added support for general choice vectors

vout = sort(v);
k = length(v);

if isscalar(w),
  W = 1:w;
else
  W = sort(w);
end;

% find the rightmost element that can be increased
ind = find(vout<W(end-k+1:end),1,'last');

if isempty(ind),
  % v is the last vector
  vout = [];
else
  % increment vout(ind) and update the tail elements
  j = find(vout(ind)==W,1,'last');
  if isempty(j),
    error('an element of V is not in W');
  end;
  vout(ind:k) = W(j+1:j+k-ind+1);
end;


function [U S] = performPCA(X)

% This function calculates the covariance matrix (Sigma) and then performs
% svd on it to get the eigen vectors and eigen values

[m n] = size(X); % m - no of egs; n - no of features

Sigma = (1/m)*(X')*(X); % Covariance matrix

[U S V] = svd(Sigma); % Perform Singular Value Decomposition


function [x,y] = intline(x1,x2,y1,y2)
%INTLINE Integer-coordinate line drawing algorithm.
%   [X,Y] = INTLINE(X1,X2,Y1,Y2) computes an approximation to the line
%   segment joining (X1,Y1) and (X2,Y2) with integer coordinates. X1,
%   X2, Y1, and Y2 should be integers. INTLINE is reversible; that is,
%   INTLINE(X1,X2,Y1,Y2) produces the same results as
%   FLIPUD(INTLINE(X2,X1,Y2,Y1)).

%   Copyright 1993-2019 The MathWorks, Inc.
%   License: https://github.com/mathworks/matlab-color-tools/blob/master/license.txt

dx = abs(x2 - x1);
dy = abs(y2 - y1);

% Check for degenerate case.
if ((dx == 0) && (dy == 0))
   x = x1;
   y = y1;
  return;
end

flip = 0;
if (dx >= dy)
   if (x1 > x2)
      % Always "draw" from left to right.
      t = x1; x1 = x2; x2 = t;
      t = y1; y1 = y2; y2 = t;
      flip = 1;
   end
   m = (y2 - y1)/(x2 - x1);
   x = (x1:x2).';
   y = round(y1 + m*(x - x1));
else
   if (y1 > y2)
      % Always "draw" from bottom to top.
      t = x1; x1 = x2; x2 = t;
      t = y1; y1 = y2; y2 = t;
      flip = 1;
   end
   m = (x2 - x1)/(y2 - y1);
   y = (y1:y2).';
   x = round(x1 + m*(y - y1));
end

if (flip)
   x = flipud(x);
   y = flipud(y);
end


function value = bmi_metric ( w_kg, h_m )

%*****************************************************************************80
%
%% BMI_METRIC computes the body mass index given metric measurements.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real W_KG, the body weight in kilograms.
%
%    Input, real H_M, the body height in meters.
%
%    Output, real VALUE, the body mass index.
%
  value = w_kg / ( h_m * h_m );

  return
end


function p = prime_ge ( n )

%*****************************************************************************80
%
%% PRIME_GE returns the smallest prime greater than or equal to N.
%
%  Discussion:
%
%    The MATLAB version of this program is made much simpler
%    because of the availability of the IS_PRIME logical function.
%
%  Example:
%
%    N     PRIME_GE
%
%    -10    2
%      1    2
%      2    2
%      3    3
%      4    5
%      5    5
%      6    7
%      7    7
%      8   11
%      9   11
%     10   11
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 March 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number to be bounded.
%
%    Output, integer P, the smallest prime number that is greater
%    than or equal to N.
%
  p = max ( ceil ( n ), 2 );

  while ( ~ isprime ( p ) )
      p = p + 1;
  end

  return
end


function intVal=monomialIntCrossPolytope(alpha)
%%MONOMIALINTCROSSPOLYTOPE Evaluate the integral of
%          prod_{i=1}^N x(i)^alpha(i) over the space defined by
%          sum(abs(x))=1. That is, this function gives the value of the
%          desired monomial integral taken over an N-dimensional cross
%          polytope. The region is designated as G_n in [1]. In two
%          dimensions, this shape is a square, in three an octohedron, in
%          N, a cross polytope (or N-dimensional hyperoctahedron).
%
%INPUTS: alpha An NX1 or 1XN vector of the integer exponents of the
%              monomial term. All elements must be >=0.
%
%OUTPUTS: intVal The value of the specified integral.
%
%The formula is taken from Chapter 7.7 of [1]. These types of explicit
%moment formulae are useful for testing cubature integration points.
%
%EXAMPLE:
%Here we verify that the moment value produced here equals that obtained
%using cubature points of an appropriate order.
% [xi,w]=fifthOrderCrossPolyCubPoints(3);
% alpha=[0;2;2];
% theMoment=findMomentFromSamp(alpha,xi,w)
% intVal=monomialIntCrossPolytope(alpha)
%One will find that theMoment and intVal are both near 0.0063.
%
%REFERENCES:
%[1] A.H. Stroud, Approximate Calculation of Multiple Integrals. Cliffs,
%    NJ: Prentice-Hall, Inc., 1971.
%
%February 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(all(mod(alpha,2)==0))
    n=length(alpha);

    intVal=exp(n*log(2)+sum(gammaln(alpha+1))-gammaln(n+sum(alpha)+1));
else
    intVal=0;
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 mask = maskEllipse( mRows, nCols, varargin )
% Creates a binary image of an ellipse.
%
% Creates a binary image of size (mRows x nCols), with all pixels set to 0
% outside the ellipse and 1 inside.  The ellipse is given by 5 parameters,
% a semimajor axis of ra, a semminor axis of radius rb, angle phi (in
% radians), and center (cRow,cCol). An alternative method of specifying the
% ellipse parameters is in terms of a 2D Gaussian. For more info on how a
% Gaussian relates to an ellipse see gauss2ellipse.
%
% USAGE
%  mask = maskEllipse( mRows, nCols, cRow, cCol, ra, rb, phi )
%  mask = maskEllipse( mRows, nCols, mu, C, [rad] )
%
% INPUTS [version 1]
%  mRows   - number of rows in mask
%  nCols   - number of columns in mask
%  cRow    - the row location of the center of the ellipse
%  cCol    - the column location of the center of the ellipse
%  ra      - semi-major axis length (in pixels) of the ellipse
%  rb      - semi-minor axis length (in pixels) of the ellipse
%  phi     - rotation angle (in radians) of semimajor axis to x-axis
%
% INPUTS [version 2]
%  mRows   - number of rows in mask
%  nCols   - number of columns in mask
%  mu      - 1x2 vector representing the center of the ellipse
%  C       - 2x2 cov matrix
%  rad     - [2] Number of std to create the ellipse to
%
% OUTPUTS
%  mask    - created image mask
%
% EXAMPLE
%  mask = maskEllipse(  200, 200, 40, 100,  20, 15, pi/4 );
%  figure(1); im(mask); [mu,C] = imMlGauss( mask, 0, 2 );
%
% See also PLOTELLIPSE, GAUSS2ELLIPSE, MASKCIRCLE, MASKGAUSSIANS, IMMLGAUSS
%
% Piotr's Computer Vision Matlab Toolbox      Version 2.40
% Copyright 2014 Piotr Dollar.  [pdollar-at-gmail.com]
% Licensed under the Simplified BSD License [see external/bsd.txt]

if( nargin==7 )
  [cRow, cCol, ra, rb, phi] = deal( varargin{:} );
elseif( nargin==4 )
  [mu, C] = deal( varargin{:} );
  [cRow, cCol, ra, rb, phi] = gauss2ellipse( mu, C );
elseif( nargin==5 )
  [mu, C, rad] = deal( varargin{:} );
  [cRow, cCol, ra, rb, phi] = gauss2ellipse( mu, C, rad );
else
  error( ['Incorrect number of input arguments: ' int2str(nargin)] );
end;

% compute the leftmost and rightmost points of the ellipse
raCos=ra*cos(pi-phi); rbCos=rb*cos(pi-phi);
raSin=ra*sin(pi-phi); rbSin=rb*sin(pi-phi);
d = sqrt(raCos*raCos + rbSin*rbSin);
cRad = abs(raCos*raCos/d + rbSin*rbSin/d);
c0 = max( ceil(cCol-cRad), 1 );
c1 = min( floor(cCol+cRad), nCols );
B = rbSin / raCos; B2=B*B;

% compute and add the top/bottom points for each c
mask = zeros( mRows, nCols );
for c=c0:c1
  A=(c-cCol)/raCos; C=sqrt(max(0,B2-A*A+1));
  r0 = cRow - raSin*(A-B*C)/(B2+1) + rbCos*(A*B+C)/(B2+1);
  r1 = cRow - raSin*(A+B*C)/(B2+1) + rbCos*(A*B-C)/(B2+1);
  if(r0>r1), tmp=r0; r0=r1; r1=tmp; end
  r0 = max( ceil(r0-.0001), 1 );
  r1 = min( floor(r1+.0001), mRows );
  mask( r0:r1, c ) = 1;
end


function vn = normalizeVector3d(v)
%NORMALIZEVECTOR3D Normalize a 3D vector to have norm equal to 1.
%
%   V2 = normalizeVector3d(V);
%   Returns the normalization of vector V, such that ||V|| = 1. Vector V is
%   given as a row vector.
%
%   If V is a N-by-3 array, normalization is performed for each row of the
%   input array.
%
%   See also:
%   vectors3d, vectorNorm3d
%

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

% HISTORY
% 2005-11-30 correct a bug
% 2009-06-19 rename as normalizeVector3d
% 2010-11-16 use bsxfun (Thanks to Sven Holcombe)

vn   = bsxfun(@rdivide, v, sqrt(sum(v.^2, 2)));


function [out] = meanangle(in,dim,sens);

% MEANANGLE will calculate the mean of a set of angles (in degrees) based
% on polar considerations.
%
% Usage: [out] = meanangle(in,dim)
%
% in is a vector or matrix of angles (in degrees)
% out is the mean of these angles along the dimension dim
%
% If dim is not specified, the first non-singleton dimension is used.
%
% A sensitivity factor is used to determine oppositeness, and is how close
% the mean of the complex representations of the angles can be to zero
% before being called zero.  For nearly all cases, this parameter is fine
% at its default (1e-12), but it can be readjusted as a third parameter if
% necessary:
%
% [out] = meanangle(in,dim,sensitivity)
%
% Written by J.A. Dunne, 10-20-05
%

if nargin<3
    sens = 1e-12;
end

if nargin<2
    ind = min(find(size(in)>1));
    if isempty(ind)
        %This is a scalar
        out = in;
        return
    end
    dim = ind;
end

in = in * pi/180;

in = exp(i*in);
mid = mean(in,dim);
out = atan2(imag(mid),real(mid))*180/pi;
out(abs(mid)<sens) = nan;


function f=lorenz_ext(t,X)
%
%  Lorenz equation
%
%               dx/dt = SIGMA*(y - x)
%               dy/dt = R*x - y -x*z
%               dz/dt= x*y - BETA*z
%
%        In demo run SIGMA = 10, R = 28, BETA = 8/3
%        Initial conditions: x(0) = 0, y(0) = 1, z(0) = 0;
%        Reference values for t=10 000 :
%              L_1 = 0.9022, L_2 = 0.0003, LE3 = -14.5691
%
%        See:
%    K. Ramasubramanian, M.S. Sriram, "A comparative study of computation
%    of Lyapunov spectra with different algorithms", Physica D 139 (2000) 72-86.
%
% --------------------------------------------------------------------
% Copyright (C) 2004, Govorukhin V.N.

% Values of parameters
SIGMA = 10;
R = 28;
BETA = 8/3;

x=X(1); y=X(2); z=X(3);

Y= [X(4), X(7), X(10);
    X(5), X(8), X(11);
    X(6), X(9), X(12)];

f=zeros(9,1);

%Lorenz equation
f(1)=SIGMA*(y-x);
f(2)=-x*z+R*x-y;
f(3)=x*y-BETA*z;

%Linearized system

 Jac=[-SIGMA, SIGMA,     0;
         R-z,    -1,    -x;
           y,     x, -BETA];

%Variational equation
f(4:12)=Jac*Y;

%Output data must be a column vector


function val=secDerivVal(z,n)
%%SECDERIVVAL Return the value of the nth derivative of sec(x) with respect
%             to x evaluated at x=z.
%
%INPUTS: z A matrix of real or complex values at which the nth derivative
%          of the secant function is desired.
%        n The number of derivatives to take. n>=0.
%
%OUTPUTS: val The value of the nth derivative of the secant function taken
%             at all of the points in z. val has the same dimensions as z.
%
%This function implements the algorithm of [1].
%
%REFERENCES:
%[1] M. E. Hoffman, "Derivative polynomials for tangent and secant," The
%    American Mathematical Monthly, vol. 102, no. 1, pp. 23-30, Jan. 1995.
%
%October 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numEls=numel(z);

val=zeros(size(z));
for curEl=1:numEls
    x=z(curEl);
    u=tan(x);

    P=zeros(n+1,1);
    Q=zeros(n+1,1);
    P(1)=u;
    Q(1)=1;

    for k=1:n
        %The loop implements Equation 5.
        sumValP=0;
        sumValQ=0;
        for i=0:(k-1)
            binomVal=binomial(k-1,i);
            sumValP=sumValP+binomVal*P(i+1)*P(k-1-i+1);
            sumValQ=sumValQ+binomVal*P(i+1)*Q(k-1-i+1);
        end
        if(k==1)
            sumValP=sumValP+1;
        end
        P(k+1)=sumValP;
        Q(k+1)=sumValQ;
    end
    val(curEl)=Q(end)*sec(x);
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 pdf = geometric_pdf ( x, a )

%*****************************************************************************80
%
%% GEOMETRIC_PDF evaluates the Geometric PDF.
%
%  Discussion:
%
%    PDF(X)(A) = A * ( 1 - A )**(X-1)
%
%    PDF(X)(A) is the probability that exactly X Bernoulli trials, each
%    with probability of success A, will be required to achieve
%    a single success.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer X, the number of trials.
%    0 < X
%
%    Input, real A, the probability of success on one trial.
%    0.0 <= A <= 1.0.
%
%    Output, real PDF, the value of the PDF.
%

%
%  Special cases.
%
  if ( x < 1 )

    pdf = 0.0;

  elseif ( a == 0.0 )

    pdf = 0.0;

  elseif ( a == 1.0 )

    if ( x == 1 )
      pdf = 1.0;
    else
      pdf = 0.0;
    end

  else

    pdf = a * ( 1.0 - a )^( x - 1 );

  end

  return
end


function glopts = loc2glob_3d ( cospitch, cosroll, cosyaw, sinpitch, sinroll, ...
  sinyaw, globas, locpts )

%*****************************************************************************80
%
%% LOC2GLOB_3D converts from a local to global coordinate system in 3D.
%
%  Discussion:
%
%    A global coordinate system is given.
%
%    A local coordinate system has been translated to the point with
%    global coordinates GLOBAS, and rotated through a yaw, a pitch, and
%    a roll.
%
%    A point has local coordinates LOCPTS, and it is desired to know
%    the point's global coordinates GLOPTS.
%
%    The transformation may be written as
%
%      GLOB = GLOBAS + N_YAW * N_PITCH * N_ROLL * LOC
%
%    where
%
%               (  cos(Yaw)   -sin(Yaw)        0      )
%    N_YAW    = (  sin(Yaw)    cos(Yaw)        0      )
%               (      0           0           1      )
%
%               (  cos(Pitch)      0       sin(Pitch) )
%    N_PITCH =  (      0           1           0      )
%               ( -sin(Pitch)      0       cos(Pitch) )
%
%               (      1           0           0      )
%    N_ROLL =   (      0       cos(Roll)  -sin(Roll)  )
%               (      0       sin(Roll)   cos(Roll)  )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real COSPITCH, COSROLL, COSYAW, the cosines of the
%    pitch, roll and yaw angles.
%
%    Input, real SINPITCH, SINROLL, SINYAW, the sines of the pitch,
%    roll and yaw angles.
%
%    Input, real GLOBAS(3,1), the global coordinates of the base
%    vector.
%
%    Input, real LOCPTS(3,1), the local coordinates of the point.
%
%    Output, real GLOPTS(3,1), the global coordinates of the point.
%
  glopts(1,1) = globas(1,1) + (  cosyaw * cospitch ) * locpts(1,1) ...
    + (  cosyaw * sinpitch * sinroll - sinyaw * cosroll ) * locpts(2,1) ...
    + (  cosyaw * sinpitch * cosroll + sinyaw * sinroll ) * locpts(3,1);

  glopts(2,1) = globas(2,1) + (  sinyaw * cospitch ) * locpts(1,1) ...
    + (  sinyaw * sinpitch * sinroll + cosyaw * cosroll ) * locpts(2,1) ...
    + (  sinyaw * sinpitch * cosroll - cosyaw * sinroll ) * locpts(3,1);

  glopts(3,1) = globas(3,1) + ( -sinpitch ) * locpts(1,1) ...
    + (  cospitch * sinroll ) * locpts(2,1) ...
    + (  cospitch * cosroll ) * locpts(3,1);

  return
end


function show3DModel(faces,vertices,showNormal)
%
% this function draws a 3D CG model with the normal of their faces
% the normal is computed by left-hand-rule
% http://stackoverflow.com/questions/1516296/find-the-normal-angle-of-the-face-of-a-triangle-in-3d-given-the-co-ordinated-of
% i.e. vertices are ordered clockwise with respect to its outward normal
%
% input:
% faces is Nx3 matrix for vertex index
% vertices is Kx3 matrix
%
% demo:
% load model;
% show3DModel(faces,vertices);

X = reshape(vertices(faces(:),1),size(faces))';
Y = reshape(vertices(faces(:),2),size(faces))';
Z = reshape(vertices(faces(:),3),size(faces))';

fill3(X,Y,Z,[160,160,160]/255);

cX = mean(X(1:3,:));
cY = mean(Y(1:3,:));
cZ = mean(Z(1:3,:));

p21= [X(2,:) - X(1,:); Y(2,:) - Y(1,:); Z(2,:) - Z(1,:)];
p31= [X(3,:) - X(1,:); Y(3,:) - Y(1,:); Z(3,:) - Z(1,:)];

nXYZ = cross(p21,p31);
lXYZ = sqrt(sum(nXYZ.^2,1));
nXYZ = nXYZ ./ repmat(lXYZ,3,1);

hold on;
if ~exist('showNormal','var') || showNormal
    quiver3(cX,cY,cZ,nXYZ(1,:),nXYZ(2,:),nXYZ(3,:));
end
axis equal


function [p alpha] = circ_vmpdf(alpha, thetahat, kappa)

% [p alpha] = circ_vmpdf(alpha, w, p)
%   Computes the circular von Mises pdf with preferred direction thetahat
%   and concentration kappa at each of the angles in alpha
%
%   The vmpdf is given by f(phi) =
%   (1/(2pi*I0(kappa))*exp(kappa*cos(phi-thetahat)
%
%   Input:
%     alpha     angles to evaluate pdf at, if empty alphas are chosen to
%               100 uniformly spaced points around the circle
%     [thetahat preferred direction, default is 0]
%     [kappa    concentration parameter, default is 1]
%
%   Output:
%     p         von Mises pdf evaluated at alpha
%     alpha     angles at which pdf was evaluated
%
%
%   References:
%     Statistical analysis of circular data, Fisher
%
% Circular Statistics Toolbox for Matlab

% By Philipp Berens and Marc J. Velasco, 2009
% velasco@ccs.fau.edu

% if no angles are supplied, 100 evenly spaced points around the circle are
% chosen
if nargin < 1 || isempty(alpha)
    alpha = linspace(0, 2*pi, 101)';
    alpha = alpha(1:end-1);
end
if nargin < 3
    kappa = 1;
end
if nargin < 2
    thetahat = 0;
end

alpha = alpha(:);

% evaluate pdf
C = 1/(2*pi*besseli(0,kappa));
p = C * exp(kappa*cos(alpha-thetahat));


function p = he_polynomial_value ( m, n, x )

%*****************************************************************************80
%
%% HE_POLYNOMIAL_VALUE evaluates He(i,x).
%
%  Discussion:
%
%    He(i,x) represents the probabilist's Hermite polynomial.
%
%  Differential equation:
%
%    ( exp ( - 0.5 * x^2 ) * He(n,x)' )' + n * exp ( - 0.5 * x^2 ) * He(n,x) = 0
%
%  First terms:
%
%   1
%   X
%   X^2  -  1
%   X^3  -  3 X
%   X^4  -  6 X^2 +   3
%   X^5  - 10 X^3 +  15 X
%   X^6  - 15 X^4 +  45 X^2 -   15
%   X^7  - 21 X^5 + 105 X^3 -  105 X
%   X^8  - 28 X^6 + 210 X^4 -  420 X^2 +  105
%   X^9  - 36 X^7 + 378 X^5 - 1260 X^3 +  945 X
%   X^10 - 45 X^8 + 630 X^6 - 3150 X^4 + 4725 X^2 - 945
%
%  Recursion:
%
%    He(0,X) = 1,
%    He(1,X) = X,
%    He(N,X) = X * He(N-1,X) - (N-1) * He(N-2,X)
%
%  Orthogonality:
%
%    Integral ( -oo < X < +oo ) exp ( - 0.5 * X^2 ) * He(M,X) He(N,X) dX
%    = sqrt ( 2 * pi ) * N! * delta ( N, M )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz, Irene Stegun,
%    Handbook of Mathematical Functions,
%    National Bureau of Standards, 1964,
%    ISBN: 0-486-61272-4,
%    LC: QA47.A34.
%
%    Frank Olver, Daniel Lozier, Ronald Boisvert, Charles Clark,
%    NIST Handbook of Mathematical Functions,
%    Cambridge University Press, 2010,
%    ISBN: 978-0521192255,
%    LC: QA331.N57.
%
%  Parameters:
%
%    Input, integer M, the number of evaluation points.
%
%    Input, integer N, the highest order polynomial to compute.
%    Note that polynomials 0 through N will be computed.
%
%    Input, real X(M,1), the evaluation points.
%
%    Output, real P(M,N+1), the values of the probabilist's Hermite polynomials
%    of index 0 through N.
%
  p = zeros ( m, n + 1 );

  p(1:m,1) = 1.0;

  if ( n == 0 )
    return
  end

  p(1:m,2) = x(1:m,1);

  for j = 2 : n
    p(1:m,j+1) = x(1:m,1) .* p(1:m,j) - ( j - 1 ) * p(1:m,j-1);
  end

  return
end


function value = angle_rad_2d ( p1, p2, p3 )

%*****************************************************************************80
%
%% ANGLE_RAD_2D returns the angle swept out between two rays in 2D.
%
%  Discussion:
%
%    Except for the zero angle case, it should be true that
%
%      ANGLE_RAD_2D(P1,P2,P3) + ANGLE_RAD_2D(P3,P2,P1) = 2 * PI
%
%        P1
%        /
%       /
%      /
%     /
%    P2--------->P3
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(2), P2(2), P3(2), define the rays
%    P1 - P2 and P3 - P2 which in turn define the angle.
%
%    Output, real VALUE, the angle swept out by the rays, measured
%    in radians.  0 <= VALUE < 2*PI.  If either ray has zero length,
%    then VALUE is set to 0.
%
  p(1) = ( p3(1) - p2(1) ) * ( p1(1) - p2(1) ) ...
       + ( p3(2) - p2(2) ) * ( p1(2) - p2(2) );

  p(2) = ( p3(1) - p2(1) ) * ( p1(2) - p2(2) ) ...
       - ( p3(2) - p2(2) ) * ( p1(1) - p2(1) );

  if ( p(1) == 0.0 & p(2) == 0.0 )
    value = 0.0;
    return
  end

  value = atan2 ( p(2), p(1) );

  if ( value < 0.0 )
    value = value + 2.0 * pi;
  end

  return
end


function [x,y] = circlePoints(radSpacing)
%Make samples on a circle
%
%  [x,y] = circlePoints(radSpacing)
%
% Example
%    radSpacing = 0.11;
%    [x,y] = circlePoints(radSpacing);
%    plot(x,y,'o'); axis equal
%

theta = (0:radSpacing:2*pi);
x = cos(theta); y = sin(theta);

return;


function pdf = semicircular_pdf ( x, a, b )

%*****************************************************************************80
%
%% SEMICIRCULAR_PDF evaluates the Semicircular PDF.
%
%  Formula:
%
%    PDF(X)(A,B) = ( 2 / ( B * PI ) ) * SQRT ( 1 - ( ( X - A ) / B )**2 )
%    for A - B <= X <= A + B
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the PDF.
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Output, real PDF, the value of the PDF.
%
  if ( x < a - b )

    pdf = 0.0;

  elseif ( x <= a + b )

    y = ( x - a ) / b;

    pdf = 2.0 / ( b * pi ) * sqrt ( 1.0 - y * y );

  elseif ( a + b < x )

    pdf = 0.0;

  end

  return
end


% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni
%
%
% Partial fraction expansion of a rational function
%
%

%        s^2+3s+1
% X(s)=----------------
%       s^3+5s^2+2s-8

A=[1 5 2 -8];
rt=roots(A)
syms s
X=(s^2+3*s+1)/(s^3+5*s^2+2*s-8);

c1=limit((s-rt(1))*X,s,rt(1))
c2=limit( (s-rt(2))*X,s,rt(2))
c3=limit( (s-rt(3))*X,s,rt(3))

X1=simplify( (s-rt(1))*X );
X2=simplify( (s-rt(2))*X );
X3=simplify( (s-rt(3))*X );
c1=subs(X1,s,rt(1))
c2=subs(X2,s,rt(2))
c3=subs(X3,s,rt(3))

%alternative conversion
num=[ 1 3 1];
den=[ 1 5 2 -8];
[R,P,K]=residue(num,den)
syms s
X=R(1)/(s-P(1))+R(2)/(s-P(2))+R(3)/(s-P(3))
pretty(X)

%
%        s^2+3s+1
% X(s)=------------
%       s^3-3s+2

A=[1 0 -3 2];
rt=roots(A)
syms s
X=(s^2+3*s+1)/(s^3-3*s+2);

c1=limit((s-rt(1))*X,s,rt(1))

r=2;
i=1;
f= ((s-1)^r )*X;
d=diff(f,s,r-i);
fact=1/factorial(r-i);
c2=limit(fact*d,s,1)

i=2;
d=diff(f,s,r-i);
fact=1/factorial(r-i);
c3=limit(fact*d,s,1)

%alternative conversion
num=[ 1 3 1];
den=[1 0 -3 2];
[R,P,K]=residue(num,den)

%
%        s^2-12s+11
% X(s)=------------
%        s^2+4s+3

num=[1 -12 11];
den=[ 1 4 3];
[k,g]=deconv(num,den)
rt=roots(den)

syms s
GA=(-16*s+8)/(s^2+4*s+3);
c1=limit((s-rt(1))*GA,s,rt(1))
c2=limit((s-rt(2))*GA,s,rt(2))

%alternative conversion
num=[ 1 -12 11];
den=[ 1 4 3];
[R,P,K]=residue(num,den)


function [ G ] = gsp_erdos_renyi( N,p,param )
%GSP_ERDOS_RENYI Create a random Erdos Renyi graph
%   Usage:  G = gsp_erdos_renyi( N,p,param );
%           G = gsp_erdos_renyi( N,p );
%
%   Input parameters:
%         N     : Number of nodes
%         p     : Probability of connection of a node with another
%         param : Structure of optional parameter
%   Output parameters:
%         G     : Graph structure.
%
%   'gsp_erdos_renyi( N,p,param )' initializes create a graph structure
%   containing the weighted adjacency matrix (G.W), the number of vertices
%   (G.N) for an Erdos Renyi graph. All edge weights are equal to 1.
%
%   The Erdos Renyi graph is constructed by connecting nodes randomly. Each
%   edge is included in the graph with probability p independent from every
%   other edge.
%
%   *param* a Matlab structure containing the following fields:
%
%     * *param.connected* : flag to force the graph to be connected. By
%       default, it is 0.
%
%     * *param.maxit* : is the maximum number of try to connect the graph.
%       By default, it is 10.
%
%     * *param.verbose* : 0 no log, 1 print main steps, 2 print all steps.
%       By default, it is 1.
%
%   Example::
%
%        G = gsp_erdos_renyi(100,0.05)

% Author : Nathanael Perraudin

% Optional input arguments
if nargin<3, param=struct; end

if ~isfield(param, 'connected'), param.connected=0; end
if ~isfield(param, 'maxit'), param.maxit=10; end
if ~isfield(param, 'verbose'), param.verbose=1 ; end

% Check if the user didn't put silly parameter
if param.connected
    if N*p<3
        if param.verbose
            fprintf(['The model has very low chance to create a '...
                ,'connected graph. Increase N, p or disable '...
                ,'param.connected \n']);
        end
    end
end

if p>1
   error('The probability p cannot be above 1');
end

if p<0
    error('The probability p cannot be negative');
end

% Create the graph structure
G=struct;
G.graph_type='erdos_renyi';
G.connected=param.connected;

% Create the graph
if param.connected
    bool=0;
    iter=1;
    if param.verbose>1
        fprintf('Entering the iteration process\n')
    end
    while ~bool

        G.W = sprandsym(N, p)>0;
        G.W(1:N+1:end) = 0;

        bool=gsp_check_connectivity(G.W);
        if iter==param.maxit
            warning('The graph is not strongly connected.');
            break;
        elseif ~bool
            if param.verbose>1
                fprintf('Iteration %i failed. Trying again \n',iter)
            end
            iter=iter+1;
        end
    end
    if param.verbose>1
        if bool
            fprintf('A connected graph has been created in %i iteration\n',iter);
        else
            fprintf('The iterative process has failed.\n');
        end
    end
else
   G.W = sprandsym(N,p)>0;
   G.W(1:N+1:end) = 0;
end

% try to create point to be associated with the points of the graph

% [x, y] = draw_dot(G.W);
%
%
% G.coords=[x',y'];
% G.limits=[-1e-4,1.01*max(x),-1e-4,1.01*max(y)];

G.type = 'erdos_renyi';

G = gsp_graph_default_parameters(G);

end


function p = gam_cdf(x,a,b)
%GAM_CDF Cumulative of Gamma probability density function (cdf).
%
%   P = GAM_CDF(X,A,B) Returns the gamma cdf with
%   shape A and inverse scale B, at the values in X.
%
%   The size of X is the common size of the input arguments. A
%   scalar input functions as a constant matrix of the same size as
%   the other inputs.
%
%   The parameterization is as in Gelman et al. (2004). Bayesian Data
%   Analysis (second edition)

% Copyright (c) 1998-2004 Aki Vehtari

% This software is distributed under the GNU General Public
% License (version 3 or later); please refer to the file
% License.txt, included with the software, for details.

if nargin < 3,
  error('Requires three input arguments.');
end

p=gammainc(b*x,a);


function a = rectangle_adj ( row_num, col_num, n )

%*****************************************************************************80
%
%% RECTANGLE_ADJ returns the RECTANGLE_ADJ matrix.
%
%  Discussion:
%
%    This is the adjacency matrix for a set of points arranged in
%    a ROW_NUM by COL_NUM grid.
%
%  Diagram:
%
%     1---5---9
%     |   |   |
%     2---6--10
%     |   |   |
%     3---7--11
%     |   |   |
%     4---8--12
%
%  Example:
%
%    ROW_NUM = 4
%    COL_NUM = 3
%
%    0  1  0  0    1  0  0  0    0  0  0  0
%    1  0  1  0    0  1  0  0    0  0  0  0
%    0  1  0  1    0  0  1  0    0  0  0  0
%    0  0  1  0    1  0  0  1    0  0  0  0
%
%    1  0  0  0    0  1  0  0    1  0  0  0
%    0  1  0  0    1  0  1  0    0  1  0  0
%    0  0  1  0    0  1  0  1    0  0  1  0
%    0  0  0  1    0  0  1  0    0  0  0  1
%
%    0  0  0  0    1  0  0  0    0  1  0  0
%    0  0  0  0    0  1  0  0    1  0  1  0
%    0  0  0  0    0  0  1  0    0  1  0  1
%    0  0  0  0    0  0  0  1    0  0  1  0
%
%  Properties:
%
%    A is integral, therefore det ( A ) is integral, and
%    det ( A ) * inverse ( A ) is integral.
%
%    A is a zero/one matrix.
%
%    A is block tridiagonal.
%
%    A is an adjacency matrix.
%
%    A is related to the "LIGHTS_OUT" matrix.
%
%    A is symmetric: A' = A.
%
%    Because A is symmetric, it is normal.
%
%    Because A is normal, it is diagonalizable.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 July 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer ROW_NUM, COL_NUM, the number of rows and
%    columns in the rectangle.
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  for j_block = 1 : col_num

    j = ( j_block - 1 ) * row_num + 1;

    for i_block = 1 : col_num

      i = ( i_block - 1 ) * row_num + 1;

      if ( j_block == i_block )
        a(i:i+row_num-1,j:j+row_num-1) = line_adj ( row_num );
      elseif ( abs ( j_block - i_block ) == 1 )
        a(i:i+row_num-1,j:j+row_num-1) = identity ( row_num, row_num );
      else
        a(i:i+row_num-1,j:j+row_num-1) = zero ( row_num, row_num );
      end

    end
  end

  return
end


function [X_norm, mu, sigma] = featureNormalize(X)
%FEATURENORMALIZE Normalizes the features in 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);
X_norm = bsxfun(@minus, X, mu);

sigma = std(X_norm);
X_norm = bsxfun(@rdivide, X_norm, sigma);

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

end


function a = tri_upper_inverse ( alpha, n )

%*****************************************************************************80
%
%% TRI_UPPER_INVERSE returns the inverse of the TRI_UPPER matrix.
%
%  Formula:
%
%    if ( I = J )
%      A(I,J) = 1
%    elseif ( I = J - 1 )
%      A(I,J) = -ALPHA
%    elseif ( I < J )
%      A(I,J) = - ALPHA * ( 1-ALPHA)^(J-I-1)
%    else
%      A(I,J) = 0
%
%  Example:
%
%    ALPHA = 3, N = 5
%
%    1 -3  6 -12  24
%    0  1 -3   6 -12
%    0  0  1  -3   6
%    0  0  0   1  -3
%    0  0  0   0   1
%
%  Properties:
%
%    A is generally not symmetric: A' /= A.
%
%    A is nonsingular.
%
%    A is upper triangular.
%
%    A is Toeplitz: constant along diagonals.
%
%    A is persymmetric: A(I,J) = A(N+1-J,N+1-I).
%
%    det ( A ) = 1.
%
%    A is unimodular.
%
%    LAMBDA(1:N) = 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real ALPHA, value used on the superdiagonals.
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  for i = 1 : n
    for j = 1 : n

      if ( i == j )
        a(i,j) = 1.0;
      elseif ( i == j - 1 )
        a(i,j) = - alpha;
      elseif ( i < j )
        a(i,j) = - alpha * ( 1.0 - alpha )^(j-i-1);
      else
        a(i,j) = 0.0;
      end

    end
  end

  return
end