function sim = gaussianKernel(x1, x2, sigma)
%RBFKERNEL returns a radial basis function kernel between x1 and x2
%   sim = gaussianKernel(x1, x2) returns a gaussian kernel between x1 and x2
%   and returns the value in sim

% Ensure that x1 and x2 are column vectors
x1 = x1(:); x2 = x2(:);

% You need to return the following variables correctly.
sim = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the similarity between x1
%               and x2 computed using a Gaussian kernel with bandwidth
%               sigma
%
%
diff = x1 - x2;
sqDiff = diff.^2;
sim = exp(-sum(sqDiff)/(2*sigma*sigma));

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

end


%EoM_Single_Pendulum.m

% This script derives the equations of motion for a single pendulum using
% the lagrange equations and the matlab symbolic toolbox.

% Model: Single Pendulum, with a point mass bob. Theta is measured from the
% -j axis. Gravity points in the -j direction. The pendulum is a fixed
% length, and there is no friction.

% The lagrangian (L) is defined as:
%
%       L = T - U
%
% where
%       T = system's kinetic energy
%       U = system's potential energy

% How we go about expressing the equations of motion:
%
%       dL      d  / dL \         * Note that some of those 'd' should be
%       ---  =  -- | -- |           curvy 'd' to represent partial
%       dth     dt \ dw /           derivatives

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
%                        set up variables                                 %
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%

syms th w a 'real';
% th == angle from -j axis
% w  == angular rate w = d(th)/dt
% a  == angular acceleration a = d(w)/dt

% Note that in the standard notation we would have:
%    th == "q"  --  generalized coordinate
%    w  == "q dot"
%    a  == "q double dot"

syms m g l 'real';
% m == (point) mass of the pendulum bob
% g == acceleration due to gravity
% l == length of the pendulum

T = (1/2)*m*(l^2)*(w^2);  % kinetic energy of the pendulum
U = m*g*l*(1-cos(th));  % potential energy of the pendulum
L = T - U;  % lagrangian

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
%                  evaluate partial derivatives                           %
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%

%              dL
%  dL_dth  ==  ---      Note that 'd' is partial derivative here
%              dth
%
dL_dth = jacobian(L,th);

%              dL
%  dL_dw   ==  ---      Note that 'd' is partial derivative here
%              dw
%
dL_dw = jacobian(L,w);

%               d  / dL \         * Note that some of those 'd' should be
% ddL_dtdw  ==  -- | -- |           curvy 'd' to represent partial
%               dt \ dw /           derivatives
%
% Note the application of the chain rule:
%
ddL_dtdw = jacobian(dL_dw,[th, w]) * [w, a]';

%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%
%                  solve equations and write files                        %
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~%

% Equations of motion:
eqn = ddL_dtdw - dL_dth;

% Solve for acceleration:
soln = solve(eqn,a);

% Write dynamics function:
filename = 'singlePendulumDynamics.m';
matlabFunction(soln,'file',filename,'vars',{th,g,l},'output',{'ddth'});

% Write energy function:
filename = 'singlePendulumEnergy.m';
totalEnergy = T+U;
energy = [totalEnergy;T;U];
matlabFunction(totalEnergy,T,U,'file',filename,'vars',{th,w,m,g,l},'output',{'energy','kinetic','potential'});


function number = comp_enum ( n, k )

%*****************************************************************************80
%
%% COMP_ENUM returns the number of compositions of the integer N into K parts.
%
%  Discussion:
%
%    A composition of the integer N into K parts is an ordered sequence
%    of K nonnegative integers which sum to N.  The compositions (1,2,1)
%    and (1,1,2) are considered to be distinct.
%
%    The 28 compositions of 6 into three parts are:
%
%      6 0 0,  5 1 0,  5 0 1,  4 2 0,  4 1 1,  4 0 2,
%      3 3 0,  3 2 1,  3 1 2,  3 0 3,  2 4 0,  2 3 1,
%      2 2 2,  2 1 3,  2 0 4,  1 5 0,  1 4 1,  1 3 2,
%      1 2 3,  1 1 4,  1 0 5,  0 6 0,  0 5 1,  0 4 2,
%      0 3 3,  0 2 4,  0 1 5,  0 0 6.
%
%    The formula for the number of compositions of N into K parts is
%
%      Number = ( N + K - 1 )! / ( N! * ( K - 1 )! )
%
%    Describe the composition using N '1's and K-1 dividing lines '|'.
%    The number of distinct permutations of these symbols is the number
%    of compositions.  This is equal to the number of permutations of
%    N+K-1 things, with N identical of one kind and K-1 identical of another.
%
%    Thus, for the above example, we have:
%
%      Number = ( 6 + 3 - 1 )! / ( 6! * (3-1)! ) = 28
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 December 2013
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Albert Nijenhuis, Herbert Wilf,
%    Combinatorial Algorithms for Computers and Calculators,
%    Second Edition,
%    Academic Press, 1978,
%    ISBN: 0-12-519260-6,
%    LC: QA164.N54.
%
%  Parameters:
%
%    Input, integer N, the integer whose compositions are desired.
%
%    Input, integer K, the number of parts in the composition.
%
%    Output, integer NUMBER, the number of compositions of N
%    into K parts.
%
  number = i4_choose ( n + k - 1, n );

  return
end


function sim = gaussianKernel(x1, x2, sigma)
%RBFKERNEL returns a radial basis function kernel between x1 and x2
%   sim = gaussianKernel(x1, x2) returns a gaussian kernel between x1 and x2
%   and returns the value in sim

% Ensure that x1 and x2 are column vectors
x1 = x1(:); x2 = x2(:);

% You need to return the following variables correctly.
sim = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the similarity between x1
%               and x2 computed using a Gaussian kernel with bandwidth
%               sigma
%
%

sim = exp(-sumsq(x1 - x2) / (2 * sigma^2));

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

end


%DEMGAUSS Demonstrate sampling from Gaussian distributions.
%
%	Description
%
%	DEMGAUSS provides a simple illustration of the generation of data
%	from Gaussian distributions. It first samples from a one-dimensional
%	distribution using RANDN, and then plots a normalized histogram
%	estimate of the distribution using HISTP together with the true
%	density calculated using GAUSS.
%
%	DEMGAUSS then demonstrates sampling from a Gaussian distribution in
%	two dimensions. It creates a mean vector and a covariance matrix, and
%	then plots contours of constant density using the function GAUSS. A
%	sample of points drawn from this distribution, obtained using the
%	function GSAMP, is then superimposed on the contours.
%
%	See also
%	GAUSS, GSAMP, HISTP
%

%	Copyright (c) Ian T Nabney (1996-2001)

clc
mean = 2; var = 5; nsamp = 3000;
xmin = -10; xmax = 10; nbins = 30;
disp('Demonstration of sampling from a uni-variate Gaussian with mean')
dstring = [num2str(mean), ' and variance ', num2str(var), '.  ', ...
    num2str(nsamp), ' samples are taken.'];
disp(dstring);
x = mean + sqrt(var)*randn(nsamp, 1);
fh1 = figure;
histp(x, xmin, xmax, nbins);
hold on;
axis([xmin xmax 0 0.2]);
plotvals = linspace(xmin, xmax, 200)';
probs = gauss(mean, var, plotvals);
plot(plotvals, probs, '-r');
xlabel('X')
ylabel('Density')

disp(' ')
disp('Press any key to continue')
pause;
mu = [3 2];
lam1 = 0.5;
lam2 = 5.0;
Sigma = lam1*[1,1]'*[1,1] + lam2*[1,-1]'*[1,-1];
disp(' ')
disp('Demonstration of sampling from a bi-variate Gaussian.  The mean is')
dstring = ['[', num2str(mu(1)), ', ', num2str(mu(2)), ...
      '] and the covariance matrix is'];
disp(dstring)
disp(Sigma);
ngrid = 40;
cmin = -5; cmax = 10;
cvals = linspace(cmin, cmax, ngrid);
[X1, X2] = meshgrid(cvals, cvals);
XX = [X1(:), X2(:)];
probs = gauss(mu, Sigma, XX);
probs = reshape(probs, ngrid, ngrid);

fh2 = figure;
contour(X1, X2, probs, 'b');
hold on

nsamp = 300;
dstring = [num2str(nsamp), ' samples are generated.'];
disp('The plot shows the sampled data points with a contour plot of their density.')
samples = gsamp(mu, Sigma, nsamp);
plot(samples(:,1), samples(:,2), 'or');
xlabel('X1')
ylabel('X2')
grid off;

disp(' ')
disp('Press any key to end')
pause;
close(fh1);
close(fh2);
clear all;


function pdf = normal_pdf ( x, a, b )

%*****************************************************************************80
%
%% NORMAL_PDF evaluates the Normal PDF.
%
%  Discussion:
%
%    The normal PDF is also known as the Gaussian PDF.
%
%  Formula:
%
%    PDF(X)(A,B) = EXP ( - 0.5 * ( ( X - A ) / B )^2 ) / SQRT ( 2 * PI * B^2 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X(), the argument of the PDF.
%
%    Input, real A, a parameter of the PDF.
%    A represents the mean value of the variables.
%
%    Input, real B, a parameter of the PDF.
%    B represents the standard deviation of the variables.
%
%    Output, real PDF(), the value of the PDF.
%
  pdf = exp ( - 0.5 * ( ( x - a ) / b ).^2 )  / sqrt ( 2.0 * pi * b^2 );

  return
end


% gauss2d() - generate a 2-dimensional gaussian matrix
%
% Usage:
%   >> [ gaussmatrix ] = gauss2d( rows, columns, ...
%                              sigmaR, sigmaC, peakR, peakC, mask)
%
% Example:
%   >> imagesc(gauss2d(50, 50)); % image a size (50,50) 2-D gaussian matrix
%
% Inputs:
%   rows    - number of rows in matrix
%   columns - number of columns in matrix
%   sigmaR  - width of standard deviation in rows (default: rows/5)
%   sigmaC  - width of standard deviation in columns (default: columns/5)
%   peakR   - location of the peak in each row (default: rows/2)
%   peakC   - location of the peak in each column (default: columns/2)
%   mask    - (0->1) portion of the matrix to mask with zeros (default: 0)
%
% Ouput:
%   gaussmatrix - 2-D gaussian matrix
%
% Author: Arnaud Delorme, CNL/Salk Institute, 2001

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

function mat = gauss2d( sizeX, sizeY, sigmaX, sigmaY, meanX, meanY, cut);

if nargin < 2
	help gauss2d
	return;
end;
if nargin < 3
	sigmaX = sizeX/5;
end;
if nargin < 4
	sigmaY = sizeY/5;
end;
if nargin < 5
	meanX = (sizeX+1)/2;
end;
if nargin < 6
	meanY = (sizeY+1)/2;
end;
if nargin < 7
	cut = 0;
end;

X = linspace(1, sizeX, sizeX)'* ones(1,sizeY);
Y = ones(1,sizeX)'   		  * linspace(1, sizeY, sizeY);
%[-sizeX/2:sizeX/2]'*ones(1,sizeX+1);
%Y = ones(1,sizeY+1)'   *[-sizeY/2:sizeY/2];

mat = exp(-0.5*(  ((X-meanX)/sigmaX).*((X-meanX)/sigmaX)...
				+((Y-meanY)/sigmaY).*((Y-meanY)/sigmaY)))...
            			/((sigmaX*sigmaY)^(0.5)*pi);

if cut > 0
	maximun = max(max(mat))*cut;
	I = find(mat < maximun);
	mat(I) = 0;
end;

return;


clear; close all; clc;

%% 1. Create a CSV file to contain the data

my_mtx = [0,0; 3, 1.4; 6, 2.5; 9 3.1; 12 3.2; 15 1.7; 18 0];

writematrix(my_mtx, 'my_file.csv')

%%%%%%%%%%% 2. Produce a MATLAB script and functions to do the following %%%%%%%%%%%

%% a. Read the CSV file

A = xlsread('my_file.csv');

%% b. Plot the depth of the calanal along the cross-section
plot(my_mtx(:,1), my_mtx(:,2));
axis ij % this command will let the figure plot reverse the y-dir so that the graph can represent the "DEPTH" of canal.

%% c. Numerically estimate the average depth of the canal using different methods and implementations

%% i. Your own implementation ofh te trapezium method, using a loop to
% iterate over the measurement data

total_depth_trapz = 0;
x = my_mtx(:,1);
fx = my_mtx(:,2);

for i = 1:length(x)-1
    total_depth_trapz = total_depth_trapz + (x(i+1)-x(i))*(fx(i+1)+fx(i))/2;
end
% ref: https://en.wikipedia.org/wiki/Trapezoidal_rule

%% ii. Your own implementation of the Simpson's Rule, using a loop to
% iterate over the measurement data

% coef of Simpson's rule
% ref: https://www.math24.net/simpsons-rule/#example1
coef = ones(1, length(x));
coef(2:2:end-1) = 4;
coef(3:2:end-2) = 2;

delta_x = x(2)-x(1);
total_depth_Simpson = 0;
for i = 1:length(x)
    total_depth_Simpson = total_depth_Simpson + delta_x/3*coef(i)*fx(i);
end

%% iii. Your own implementation of Simpson's rule, avoiding the use of a loop by using
% operations on vectors

total_depth_Simpson_vec = delta_x/3*(coef*fx); % vectorized summation using inner product

%% iv. MATLAB's built-in trapz() function
total_depth_MATLAB_trapz = trapz(x, fx);


% CORRCOEF Correlation coefficients.
%    R=CORRCOEF(X) calculates a matrix R of correlation coefficients for
%    an array X, in which each row is an observation and each column is a
%    variable.
%
%    R=CORRCOEF(X,Y), where X and Y are column vectors, is the same as
%    R=CORRCOEF([X Y]).  CORRCOEF converts X and Y to column vectors if they
%    are not, i.e., R=CORRCOEF(X,Y) is equivalent to R=CORRCOEF([X(:) Y(:)])
%    in that case.
%
%    If C is the covariance matrix, C = COV(X), then CORRCOEF(X) is
%    the matrix whose (i,j)'th element is
%
%           C(i,j)/SQRT(C(i,i)*C(j,j)).
%
%    [R,P]=CORRCOEF(...) also returns P, a matrix of p-values for testing
%    the hypothesis of no correlation.  Each p-value is the probability
%    of getting a correlation as large as the observed value by random
%    chance, when the true correlation is zero.  If P(i,j) is small, say
%    less than 0.05, then the correlation R(i,j) is significant.
%
%    [R,P,RLO,RUP]=CORRCOEF(...) also returns matrices RLO and RUP, of
%    the same size as R, containing lower and upper bounds for a 95%
%    confidence interval for each coefficient.
%
%    [...]=CORRCOEF(...,'PARAM1',VAL1,'PARAM2',VAL2,...) specifies additional
%    parameters and their values.  Valid parameters are the following:
%
%        Parameter  Value
%        'Alpha'    A number between 0 and 1 to specify a confidence
%                   level of 100*(1-ALPHA)%.  Default is 0.05 for 95%
%                   confidence intervals.
%        'Rows'     Either 'all' (default) to use all rows, 'complete' to
%                   use rows with no NaN values, or 'pairwise' to compute
%                   R(i,j) using rows with no NaN values in column i or j.
%                   The 'pairwise' option potentially uses different sets
%                   of rows to compute different elements of R, and can
%                   produce a matrix that is indefinite.
%
%    The p-value is computed by transforming the correlation to create a t
%    statistic having N-2 degrees of freedom, where N is the number of rows
%    of X.  The confidence bounds are based on an asymptotic normal
%    distribution of 0.5*log((1+R)/(1-R)), with an approximate variance equal
%    to 1/(N-3).  These bounds are accurate for large samples when X has a
%    multivariate normal distribution.
%
%    Example:  Generate random data having correlation between column 4
%              and the other columns.
%        x = randn(30,4);       % uncorrelated data
%        x(:,4) = sum(x,2);     % introduce correlation
%        [r,p] = corrcoef(x)    % compute sample correlation and p-values
%        [i,j] = find(p<0.05);  % find significant correlations
%        [i,j]                  % display their (row,col) indices
%
%    Class support for inputs X,Y:
%       float: double, single
%
%    See also COV, VAR, STD, PLOTMATRIX.
%
%    Reference page in Doc Center
%       doc corrcoef
%
%    Other functions named corrcoef
%
%       codistributed/corrcoef    gpuArray/corrcoef    ts/corrcoef
%       fints/corrcoef
%


function y=expSlope1(x)
%%EXPSLOPE1  Evaluate the function (exp(x)-1)/x avoiding problems at the
%            point x=0, where the limit equals 1. This function arises in
%            range enclosure algorithms for interval arithmetic.
%
%INPUTS: x A vector of matrix of real values at which the function should
%          be evaluated.
%
%OUTPUTS: y The value(s) of the function (exp(x)-1)/x at the point(s) in x.
%
%For values of x below 0.1, a Taylor series expansion about x=0 is used.
%For values of x above 0.1, the function is implemented as in Chapter
%1.14.1 of [2]. Though the method in [2] can go to lower values of x, it
%still has a singularity at x=0. The Taylor series does not.
%
%This is one of the slope function in Table 10.6 of Section 10.6.2 of [1].
%
%REFERENCES:
%[1] IEEE Standard for Interval Arithmetic," in IEEE Std 1788-2015,
%    pp.1-97, June 30 2015.
%[2] N. J. Higham, Accuracy and Stability of Numerical Algorithms.
%    Philadelphia: SIAM, 1996.
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

y=zeros(size(x));

selSmall=x<0.1;
xSmall=x(selSmall);
xLarge=x(~selSmall);

if(~isempty(xSmall))
    %Use a Taylor-series approximation about x=0. THis avoud the
    %singularity.
    expanOrder=20;
    ySmall=ones(size(xSmall));

    xPow=xSmall;
    kFactorial=1;
    for k=1:expanOrder
       kFactorial=kFactorial*k;

       ySmall=ySmall+xPow/((k+1)*kFactorial);

       xPow=xPow.*xSmall;
    end
else
    ySmall=[];
end

if(~isempty(xLarge))
    yLarge=exp(xLarge);
    yLarge=(yLarge-1)/log(yLarge);
else
    yLarge=[];
end

y(selSmall)=ySmall;
y(~selSmall)=yLarge;
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 [P,N,check]=plane_intersect(N1,A1,N2,A2)
%plane_intersect computes the intersection of two planes(if any)
% Inputs:
%       N1: normal vector to Plane 1
%       A1: any point that belongs to Plane 1
%       N2: normal vector to Plane 2
%       A2: any point that belongs to Plane 2
%
%Outputs:
%   P    is a point that lies on the interection straight line.
%   N    is the direction vector of the straight line
% check is an integer (0:Plane 1 and Plane 2 are parallel'
%                              1:Plane 1 and Plane 2 coincide
%                              2:Plane 1 and Plane 2 intersect)
%
% Example:
% Determine the intersection of these two planes:
% 2x - 5y + 3z = 12 and 3x + 4y - 3z = 6
% The first plane is represented by the normal vector N1=[2 -5 3]
% and any arbitrary point that lies on the plane, ex: A1=[0 0 4]
% The second plane is represented by the normal vector N2=[3 4 -3]
% and any arbitrary point that lies on the plane, ex: A2=[0 0 -2]
%[P,N,check]=plane_intersect([2 -5 3],[0 0 4],[3 4 -3],[0 0 -2]);

%This function is written by :
%                             Nassim Khaled
%                             Wayne State University
%                             Research Assistant and Phd candidate
%If you have any comments or face any problems, please feel free to leave
%your comments and i will try to reply to you as fast as possible.
P=[0 0 0];
N=cross(N1,N2);

%  test if the two planes are parallel
if norm(N) < 10^-7                % Plane 1 and Plane 2 are near parallel
    V=A1-A2;
        if (dot(N1,V) == 0)
            check=1;                    % Plane 1 and Plane 2 coincide
           return
        else
            check=0;                   %Plane 1 and Plane 2 are disjoint
            return
        end
end

 check=2;

% Plane 1 and Plane 2 intersect in a line
%first determine max abs coordinate of cross product
maxc=find(abs(N)==max(abs(N)));

%next, to get a point on the intersection line and
%zero the max coord, and solve for the other two

d1 = -dot(N1,A1);   %the constants in the Plane 1 equations
d2 = -dot(N2, A2);  %the constants in the Plane 2 equations

switch maxc
    case 1                   % intersect with x=0
        P(1)= 0;
        P(2) = (d2*N1(3) - d1*N2(3))/ N(1);
        P(3) = (d1*N2(2) - d2*N1(2))/ N(1);
    case 2                    %intersect with y=0
        P(1) = (d1*N2(3) - d2*N1(3))/ N(2);
        P(2) = 0;
        P(3) = (d2*N1(1) - d1*N2(1))/ N(2);
    case 3                    %intersect with z=0
        P(1) = (d2*N1(2) - d1*N2(2))/ N(3);
        P(2) = (d1*N2(1) - d2*N1(1))/ N(3);
        P(3) = 0;
end


function [B,Lambda,CLS,exitCode]=jointMatDiagLS(A,w,maxIter,CLSTol,RelTol,AbsTol)
%%JOINTMATDIAGLS Given K real or complex Hermitian or symmetric matrices in
%              A, try to find a common diagonalizing matrix B and sets of
%              values Lambda such that A(:,:,k)=B*diag(Lambda(:,k))*B' for
%              all k. An exact solution is only guaranteed for positive
%              (semi-)definite matrices with K=2. However, for general
%              problems the B and Lambda values are chosen trying to
%              minimize the least squares cost function
%              CLS=\sum_{k=1}^K w(k)*norm(A_k-B*diag(lambda_k)*B','fro')^2
%              when the matrices A are Hermitian, lambda_k is an NX1 vector
%              and
%              CLS=\sum_{k=1}^K w(k)*norm(A_k-B*diag(lambda_k)*B.','fro')^2
%              when the matrices A re symmetric. Real matrices count as
%              Hermitian; one cannot mix Hermitian and Symmetric complex
%              matrices in a single A.
%
%INPUTS: A An NXNXK set of K NXN Hermitian or symmetric matrices. This
%          cannot contain Inf or NaN values.
%        w An optional set of positive that go into the cost function.
%          These do not need to sum to any particular value. The default if
%          omitted or an empty matrix is passed is ones(K,1).
%  maxIter The maximum number of iterations to perform. The default if
%          omitted or an empty matrix is passed is 10000.
%   CLSTol If the least squares cost is <= this threshold, then the
%          algorithm will terminate early. This value is checked every 10
%          iterations. The default if omitted or an empty matrix is passed
%          is 1e-6.
% RelTol, AbsTol Absolute and relative tolerances on the parameters being
%          estimated. let theta=[B(:);Lambda(:)] and thetaPrev the estimate
%          from the previous step. Say that diff=abs(theta-thetaPrev).
%          Convergence is declared if
%          all((diff<=AbsTol)|diff<=RelTol*abs(theta))
%          The default values if omitted or empty matrices are passed are
%          1e-9 and 1e-12.
%
%OUTPUTS: B The NXN matrix that approximately turns the Lambda values into
%           A. These are the diagonalizer values. B is generally not
%           an orthonormal matrix.
%    Lambda The NXK set of the diagonals of the K diagonal matrices.
%       CLS The value of the cost function on termination.
%  exitCode A parameter indicating how the function terminated. Possible
%           values are:
%           -1 The RelTol and/or AbsTol criteria were satisfied.
%            0 The CLSTol criterion was satisfied.
%            1 The maximum number of iterations was reached.
%
%This function implements the algorithm of [1]. Though exact solutions are
%possible for pairs of positive semidefinite matrices, note that
%convergence is often faster for pairs of positive definite matrices than
%for pairs of positive semidefinite matrices, particularly when the
%matrices are complex.
%
%EXAMPLE 1:
%Here, we show that we can obtain an exact solution for a pair of positive
%definite real, symmetric (Hermitian) matrices where one is positive
%semi-definite.
% C1=[57,  7, 12, 17;
%      7, 47, 17, 22;
%     12, 17, 37, 27;
%     17, 22, 27, 27];
% [V,D,U] = svd(C1);
% D(2,2)=0;%Make uninformative.
% D(3,3)=0;%Make uninformative.
% C1=V*D*U';
% C2=[87, 25, 18, 31;
%     25, 63, 20, 17;
%     18, 20, 65, 29;
%     31, 17, 29, 65];
% A=zeros(4,4,2);
% A(:,:,1)=C1;
% A(:,:,2)=C2;
% [B,Lambda,CLS,exitCode]=jointMatDiagLS(A)
% %The CLS is verified as:
% CLSCheck=norm(A(:,:,1)-B*diag(Lambda(:,1))*B','fro')^2+norm(A(:,:,2)-B*diag(Lambda(:,2))*B','fro')^2
%One will see that convergence is by the CLS bound.
%
%EXAMPLE 2:
%Here, we have two positive definite complex Hermitian matrices. Again, an
%exact solution is found rapidly. If the additive identity matrices to C1
%and C2 are removed, then the matrices are no longer positive definite and
%only a least-squares approximation can be found. In such an instance, the
%algorithm is much slower.
% C1=[  9+  0*1i,   -65+  0*1i,  -11-153*1i,  -91-173*1i;
%     -65+  0*1i,    83+  0*1i,   54- 38*1i,   31+ 28*1i;
%     -11+153*1i,    54+ 38*1i,  130+  0*1i,   16- 47*1i;
%     -91+173*1i,    31- 28*1i,   16+ 47*1i,   22+  0*1i]+215*eye(4);
%
% C2=[-16+  0*1i,  -32- 56*1i,  -12-128*1i,   16+114*1i;
%     -32+ 56*1i,   79+  0*1i,  -87- 67*1i,  -48+ 51*1i;
%     -12+128*1i,  -87+ 67*1i,   76+  0*1i,   -7- 96*1i;
%      16-114*1i,  -48- 51*1i,   -7+ 96*1i, -147+  0*1i]+259*eye(4);
% A=zeros(4,4,2);
% A(:,:,1)=C1;
% A(:,:,2)=C2;
% [B,Lambda,CLS,exitCode]=jointMatDiagLS(A)
% %The CLS is verified as:
% CLSCheck=norm(A(:,:,1)-B*diag(Lambda(:,1))*B','fro')^2+norm(A(:,:,2)-B*diag(Lambda(:,2))*B','fro')^2
%Again, convergence is due to satisfying the cost function criterion.
%
%EXAMPLE 3:
%Though only approximations can be obtained for more than two matrices in
%general, here we show that if three matrices originate from a common set
%of basis vectors, then this function will find the correct
%diagonalization.
% [V,D]=eig(magic(4));
% C1=V*D*V';
% C2=V*diag([1;2;3;5])*V';
% C3=V*diag([12;1;0;8])*V';
% A=zeros(4,4,3);
% A(:,:,1)=C1;
% A(:,:,2)=C2;
% A(:,:,3)=C3;
% [B,Lambda,CLS,exitCode]=jointMatDiagLS(A)
%Convergence of the cost function is quickly achieved for the three
%matrices. Note, however, that B is not the same as V.
%
%REFERENCES:
%[1] A. Yeredor, "Non-orthogonal joint diagonalization in the least-squares
%    sense with application in blind source separation," IEEE Transactions
%    on Signal Processing, vol. 50, no. 7, pp. 1545-1553, Jul. 2002.
%
%July 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

    K=size(A,3);
    N=size(A,1);

    if(nargin<6||isempty(AbsTol))
        AbsTol=1e-12;
    end

    if(nargin<5||isempty(RelTol))
        RelTol=1e-9;
    end

    if(nargin<4||isempty(CLSTol))
        CLSTol=1e-6;
    end

    if(nargin<3||isempty(maxIter))
        maxIter=10000;
    end

    if(nargin<2||isempty(w))
        w=ones(K,1);
    end

    %Check whether all (assume symmetric) matrices are Hermitian. If so,
    %then a different algorithm can be used.
    isHermitian=true;
    if(~isreal(A))
        for k=1:K
            if(any(any(A(:,:,k)~=A(:,:,k)')))
                isHermitian=false;
                break;
            end
        end
    end

    w=w(:);

    %Initial values. This doesn't necessarily help speed up the
    %convergence, but it will work even if the matrices in A are singular.
    B=eye(N,N);
    Lambda=ones(N,K);

    exitCode=1;
    if(isHermitian)
        for curIter=1:maxIter
            thetaPrev=[B(:);Lambda(:)];

            for iter=1:4
                for l=1:N
                    B=ACPhase(A,Lambda,w,B,l);
                end
            end
            Lambda=DCPhase(A,B);

            %Check for convergence.
            if(mod(curIter,10))
                %Cost criterion.
                CLS=0;
                for k=1:K
                    CLS=CLS+w(k)*norm(A(:,:,k)-B*diag(Lambda(:,k))*B','fro')^2;
                end
                if(CLS<=CLSTol)
                    exitCode=0;
                    return;
                end

                %Parameter change criterion.
                theta=[B(:);Lambda(:)];

                diff=abs(theta-thetaPrev);
                if(all((diff<=AbsTol)|diff<=RelTol*abs(theta)))
                    exitCode=-1;
                    break;
                end
            end
        end
    else%Assume it is symmetric, not Hermitian.
        for curIter=1:maxIter
            thetaPrev=[B(:);Lambda(:)];

            for iter=1:4
                for l=1:N
                    B=ACPhaseSym(A,Lambda,w,B,l);
                end
            end
            Lambda=DCPhaseSym(A,B);

            %Check for convergence.
            if(mod(curIter,10))
                %Cost criterion.
                CLS=0;
                for k=1:K
                    CLS=CLS+w(k)*norm(A(:,:,k)-B*diag(Lambda(:,k))*B.','fro')^2;
                end
                if(CLS<=CLSTol)
                    exitCode=0;
                    return;
                end

                %Parameter change criterion.
                theta=[B(:);Lambda(:)];

                diff=abs(theta-thetaPrev);
                if(all((diff<=AbsTol)|diff<=RelTol*abs(theta)))
                    exigtCode=-1;
                    break;
                end
            end
        end
    end

    %If the algorithm did not convergence, compute the current CLS if it should
    %be returned.
    if(nargout>2)
        CLS=0;
        if(isHermitian)
            for k=1:K
                CLS=CLS+w(k)*norm(A(:,:,k)-B*diag(Lambda(:,k))*B','fro')^2;
            end
        else
            for k=1:K
                CLS=CLS+w(k)*norm(A(:,:,k)-B*diag(Lambda(:,k))*B.','fro')^2;
            end
        end
    end
end

function B=ACPhase(A,Lambda,w,B,l)

    N=size(A,1);
    K=size(A,3);

    %Step 1
    P=zeros(N,N);
    for k=1:K
        innerSum=B*diag(Lambda(:,k))*B'-Lambda(l,k)*(B(:,l)*B(:,l)');

        P=P+w(k)*Lambda(l,k)*(A(:,:,k)-innerSum);
    end

    %Step 2
    [V,D]=eig(P);
    d=diag(D);
    [~,idx]=max(d);
    mu=d(idx);
    betaVec=V(:,idx);

    %The paper suggests using the first nonzero index of betaVec. We just
    %use the index having the largest magnitude value. in it.
    [~,nonZeroIdx]=max(abs(betaVec));

    %Force the first nonzero element of the unit eigenvector to be real and
    %positive.
    if(isreal(betaVec))
        if(betaVec(nonZeroIdx)<0)
            betaVec=-betaVec;
        end
    else
        betaVec=exp(-angle(betaVec(nonZeroIdx))*1i)*betaVec;
        %betaVec(nonZeroIdx) should be real and positive, but this line
        %deals avoids any possible finite precision issues.
        betaVec(nonZeroIdx)=abs(betaVec(nonZeroIdx));
    end

    if(mu<0)
        B(:,l)=zeros(N,1);
    else
        B(:,l)=betaVec*sqrt(mu)/sqrt(sum(w.*(Lambda(l,:).^2).'));
    end
end

function Lambda=DCPhase(A,B)

    N=size(A,1);
    K=size(A,3);

    %Step 1
    prodVal=B'*B;
    prodVal=conj(prodVal).*prodVal;
    %Use a pseudoinverse for poorly conditioned problems.
    if(rcond(prodVal)<=1e-14)
        G=pinv(prodVal);
    else
        G=inv(prodVal);
    end

    %Step 2
    Lambda=zeros(N,K);
    for k=1:K
        Lambda(:,k)=G*diag(B'*A(:,:,k)*B);
    end
end

function B=ACPhaseSym(A,Lambda,w,B,l)

    N=size(A,1);
    K=size(A,3);

    %Step 1
    P=zeros(N,N);
    for k=1:K
        innerSum=A(:,:,k);
        for n=1:N
            if(n~=l)
                innerSum=innerSum-Lambda(n,k)*(B(:,n)*B(:,n).');
            end
        end

        P=P+w(k)*Lambda(l,k)*conj(innerSum);
    end

    %Step 2
    [V,D]=eig([real(P), -imag(P);
              -imag(P), -real(P)]);

    %D should be real. This line is just in case some finite precision
    %issue in matlab makes it not real.
    D=real(D);

    d=diag(D);
    [~,idx]=max(d);
    mu=d(idx);
    xi=V(:,idx);

    %Step 3
    if(mu<0)
        B(:,l)=zeros(N,1);
    else
        gammaVal=xi(1:N);
        delta=xi((N+1):(2*N));

        B(:,l)=(gammaVal+1j*delta)*sqrt(mu)/sqrt(sum(w.*(abs(Lambda(l,:)).^2).'));
    end
end

function Lambda=DCPhaseSym(A,B)

    N=size(A,1);
    K=size(A,3);

    %Step 1
    prodVal=B'*B;
    prodVal=prodVal.*prodVal;
    %Use a pseudoinverse for poorly conditioned problems.
    if(rcond(prodVal)<=1e-14)
        G=pinv(prodVal);
    else
        G=inv(prodVal);
    end

    %Step 2
    Lambda=zeros(N,K);
    for k=1:K
        Lambda(:,k)=G*diag(B'*A(:,:,k)*conj(B));
    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 randOrthoMat=randOrthoMat(numDim)
%RANDORTHOMAT Generate a random orthogonal matrix of the desired
%             dimensionality (with respect to the Haar distribution over
%             the orthogonal group --kind of a "uniform" distribution).
%             This means that the dot product of any two columns is zero.
%             The orthogonal matrices generated have determinants of +1 or
%             -1.
%
%INPUTS: numDim The scalar number of dimensions that the random orthogonal
%               matrix should have.
%
%OUTPUTS: randOrthoMat A numDimXnumDim random orthogonal matrix with a
%                     determinant of either +1 or -1.
%
%As noted in [1], random orthogonal matrices can be obtained by first
%gennerating a matrix of independent standard normal random variables, then
%takign the QR decomposition of the matrix such that R has all positive
%elements along the diagonal. However, since Matlab's QR command can
%produce R matrices with negative diagonal elements, we have to effectively
%transfer the sign of R onto Q to make the elements of the diagonal of R
%all positive. This means multiplying Q by diag(sign(diag(R))).
%
%EXAMPLE:
%We will plot the random directions in 2D on the unit circle to show that
%this produces a relatively uniform set of rotation matrices.
% numPoints=500;
% figure(1)
% clf
% hold on
% for curPoint=1:numPoints
%     thePoint=randOrthoMat(2)*[1;0];
%     scatter(thePoint(1),thePoint(2),'.k','linewidth',2)
% end
%
%REFERENCE:
%[1] G. W. Stewart, "The efficient generation of random orthogonal matrices
%    with an application to condition estimators," SIAM Journal on
%    Numerical Analysis, vol. 17, no. 3, pp. 403-409, Jun. 1980.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

X=randn(numDim,numDim);
[Q,R]=qr(X);

randOrthoMat=Q*diag(sign(diag(R)));

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 points = intersectCircles(circle1, circle2)
%INTERSECTCIRCLES Intersection points of two circles.
%
%   POINTS = intersectCircles(CIRCLE1, CIRCLE2)
%   Computes the intersetion point of the two circles CIRCLE1 and CIRCLE1.
%   Both circles are given with format: [XC YC R], with (XC,YC) being the
%   coordinates of the center and R being the radius.
%   POINTS is a 2-by-2 array, containing coordinate of an intersection
%   point on each row.
%   In the case of tangent circles, the intersection is returned twice. It
%   can be simplified by using the 'unique' function.
%
%   Example
%     % intersection points of two distant circles
%     c1 = [0  0 10];
%     c2 = [10 0 10];
%     pts = intersectCircles(c1, c2)
%     pts =
%         5   -8.6603
%         5    8.6603
%
%     % intersection points of two tangent circles
%     c1 = [0  0 10];
%     c2 = [20 0 10];
%     pts = intersectCircles(c1, c2)
%     pts =
%         10    0
%         10    0
%     pts2 = unique(pts, 'rows')
%     pts2 =
%         10    0
%
%   References
%   http://local.wasp.uwa.edu.au/~pbourke/geometry/2circle/
%   http://mathworld.wolfram.com/Circle-CircleIntersection.html
%
%   See also
%   circles2d, intersectLineCircle, radicalAxis
%

% ------
% Author: David Legland
% E-mail: david.legland@grignon.inra.fr
% Created: 2011-01-20, using Matlab 7.9.0.529 (R2009b)
% Copyright 2011-2022 INRA - Cepia Software Platform

% adapt sizes of inputs
n1 = size(circle1, 1);
n2 = size(circle2, 1);
if n1 ~= n2
    if n1 > 1 && n2 == 1
        circle2 = repmat(circle2, n1, 1);
    elseif n2 > 1 && n1 == 1
        circle1 = repmat(circle1, n2, 1);
    else
        error('Both input should have same number of rows');
    end
end

% extract center and radius of each circle
center1 = circle1(:, 1:2);
center2 = circle2(:, 1:2);
r1 = circle1(:,3);
r2 = circle2(:,3);

% allocate memory for result
nPoints = length(r1);
points = NaN * ones(2*nPoints, 2);

% distance between circle centers
d12 = distancePoints(center1, center2, 'diag');

% get indices of circle couples with intersections
inds = d12 >= abs(r1 - r2) & d12 <= (r1 + r2);

if sum(inds) == 0
    return;
end

% angle of line from center1 to center2
angle = angle2Points(center1(inds,:), center2(inds,:));

% position of intermediate point, located at the intersection of the
% radical axis with the line joining circle centers
d1m  = d12(inds) / 2 + (r1(inds).^2 - r2(inds).^2) ./ (2 * d12(inds));
tmp = polarPoint(center1(inds, :), d1m, angle);

% distance between intermediate point and each intersection point
h   = sqrt(r1(inds).^2 - d1m.^2);

% indices of valid intersections
inds2 = find(inds)*2;
inds1 = inds2 - 1;

% create intersection points
points(inds1, :) = polarPoint(tmp, h, angle - pi/2);
points(inds2, :) = polarPoint(tmp, h, angle + pi/2);


function val=numMPartitions(n,m,getUpToM)
%%NUMMPARTITIONS Get the number of ways of partitioning the integer n into
%                m parts, where order does not matter (unlike compositions,
%                where order matters). That is the number of ways of
%                getting m nonzero integers that sum to n. The amount of
%                memory for this implementation is proportional to n*m and
%                thus the solution becomes slow for very large n and m
%                values.
%
%INPUTS: n The positive n>0 integer to be partitioned.
%        m The number of parts into which the integer is to be partitioned.
% getUpToM This parameter changes what is returned. If false (the default
%          if omitted or an empty matrix is passed), the number of
%          ways of partitioning n into m parts is returned. If true, then
%          the total number of ways of partitioning n into m or fewer parts
%          is returned.
%
%OUTPUTS: val The number of ways of partitioning the integer n into m
%             parts or if getUpToM=true, then this is the total number of
%             ways of partitioning n into m or fewer parts.
%
%The counting method is based on the recurrence relation in Chapter 7.2.1.4
%of [1]. The algorithm could be implemented to use less memory. However,
%that would require shifting rows in a table up (to reuse memory) and would
%make the code a lot more complicated.
%
%REFERENCES:
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 4, Fascicle 3:
%    Generating all Combinations and Partitions, Upper Saddle River, NJ:
%    Addison-Wesley, 2009.
%
%October 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<3||isempty(getUpToM))
    getUpToM=false;
end

P=eye(n+1,m+1);
P(:,1+1)=1;

for curN=2:n
    for curK=1:min(curN,m)
        P(curN+1,curK+1)=P(curN-1+1,curK-1+1)+P(curN-curK+1,curK+1);
    end
end
if(getUpToM)
    val=sum(P(end,:));
else
    val=P(end,end);
end
end

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


%% COMPARISON OF CONVERGENCE RATE OF VARIOUS FINITE ELEMENT METHODS
%
% This example is to compare the rate of convergence of various finite
% element approximation of the Poisson equation on the unit square:
%
% $$- \Delta u = f \; \hbox{in } (0,1)^2$$
%
% for the Dirichlet boundary condition. Results holds for other boundary
% conditions.

%% Problem
clear all; close all; clc;
[node,elem] = squaremesh([0,1,0,1],0.25);
pde = sincosdata;
bdFlag = setboundary(node,elem,'Dirichlet');
% pde = sincosNeumanndata;
% bdFlag = setboundary(node,elem,'Neumann');
option.L0 = 2;
option.maxIt = 5;
option.printlevel = 1;
option.plotflag = 0;

%% P1 element
err = femPoisson(node,elem,pde,bdFlag,option);

%%
% The optimal rate of convergence of the H1-norm (1st order), L2-norm (2nd
% order), and discrte maximum norm is observed. The 2nd order convergent
% rate between two discrete functions ||DuI-Duh|| is known as
% superconvergence.

%% CR nonconforming P1 element
option.elemType = 'CR';
err = femPoisson(node,elem,pde,bdFlag,option);

%%
% The optimal rate of convergence of the H1-norm (1st order), L2-norm (2nd
% order), and discrte maximum norm is observed. But no superconvergence of
% ||DuI-Duh||.

%% P2 element
option.elemType = 'P2';
err = femPoisson(node,elem,pde,bdFlag,option);

%% P3 element
option.elemType = 'P3';
err = femPoisson(node,elem,pde,bdFlag,option);

%% Conclusion


function fd_predator_prey ( p0, tspan, step_num )

%*****************************************************************************80
%
%% FD_PREDATOR_PREY solves a pair of predator-prey ODE's.
%
%  Discussion:
%
%    The physical system under consideration is a pair of animal populations.
%
%    The PREY reproduce rapidly; for each animal alive at the beginning of the
%    year, two more will be born by the end of the year.  The prey do not have
%    a natural death rate; instead, they only die by being eaten by the predator.
%    Every prey animal has 1 chance in 1000 of being eaten in a given year by
%    a given predator.
%
%    The PREDATORS only die of starvation, but this happens very quickly.
%    If unfed, a predator will tend to starve in about 1/10 of a year.
%    On the other hand, the predator reproduction rate is dependent on
%    eating prey, and the chances of this depend on the number of available prey.
%
%    The resulting differential equations can be written:
%
%      PREY(0) = 5000
%      PRED(0) =  100
%
%      d PREY / dT =    2 * PREY(T) - 0.001 * PREY(T) * PRED(T)
%      d PRED / dT = - 10 * PRED(T) + 0.002 * PREY(T) * PRED(T)
%
%    Here, the initial values (5000,100) are a somewhat arbitrary starting point.
%
%    The pair of ordinary differential equations that result have an interesting
%    behavior.  For certain choices of the interaction coefficients (such as
%    those given here), the populations of predator and prey will tend to
%    a periodic oscillation.  The two populations will be out of phase; the number
%    of prey will rise, then after a delay, the predators will rise as the prey
%    begins to fall, causing the predator population to crash again.
%
%    In this program, the pair of ODE's is solved with a simple finite difference
%    approximation using a fixed step size.  In general, this is NOT an efficient
%    or reliable way of solving differential equations.  However, this program is
%    intended to illustrate the ideas of finite difference approximation.
%
%    In particular, if we choose a fixed time step size DT, then a derivative
%    such as dPREY/dT is approximated by:
%
%      d PREY / dT = approximately ( PREY(T+DT) - PREY(T) ) / DT
%
%    which means that the first differential equation can be written as
%
%      PREY(T+DT) = PREY(T) + DT * ( 2 * PREY(T) - 0.001 * PREY(T) * PRED(T) ).
%
%    We can rewrite the equation for PRED as well.  Then, since we know the
%    values of PRED and PREY at time 0, we can use these finite difference
%    equations to estimate the values of PRED and PREY at time DT.  These values
%    can be used to get estimates at time 2*DT, and so on.  To get from time
%    T_START = 0 to time T_STOP = 5, we simply take STEP_NUM steps each of size
%    DT = ( T_STOP - T_START ) / STEP_NUM.
%
%    Because finite differences are only an approximation to derivatives, this
%    process only produces estimates of the solution.  And these estimates tend
%    to become more inaccurate for large values of time.  Usually, we can reduce
%    this error by decreasing DT and taking more, smaller time steps.
%
%    In this example, for instance, taking just 100 steps gives nonsensical
%    answers.  Using STEP_NUM = 1000 gives an approximate solution that seems
%    to have the right kind of oscillatory behavior, except that the amplitude
%    of the waves increases with each repetition.  Using 10000 steps, the
%    approximation begins to become accurate enough that we can see that the
%    waves seem to have a fixed period and amplitude.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    George Lindfield, John Penny,
%    Numerical Methods Using MATLAB,
%    Second Edition,
%    Prentice Hall, 1999,
%    ISBN: 0-13-012641-1,
%    LC: QA297.P45.
%
%  Parameters:
%
%    Input, real P0(2), the initial number of prey and predators.
%
%    Input, real TSPAN(2), the initial and final times.
%
%    Input, integer STEP_NUM, the number of steps.
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD_PREDATOR_PREY\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  A finite difference approximate solution of a pair\n' );
  fprintf ( 1, '  of ordinary differential equations for a population\n' );
  fprintf ( 1, '  of predators and prey.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The exact solution shows wave behavior, with a fixed\n' );
  fprintf ( 1, '  period and amplitude.  The finite difference approximation\n' );
  fprintf ( 1, '  can provide a good estimate for this behavior if the stepsize\n' );
  fprintf ( 1, '  DT is small enough.\n' );

  t_start = tspan(1);
  t_stop =  tspan(2);
  dt = ( t_stop - t_start ) / step_num;

  trf = zeros (3,step_num+1);

  trf(1,1) = t_start;
  trf(2,1) = p0(1);
  trf(3,1) = p0(2);

  for i = 1 : step_num
    trf(1,i+1) = trf(1,i) + dt;
    trf(2,i+1) = trf(2,i) + dt * (    2 * trf(2,i) - 0.004 * trf(2,i) * trf(3,i) );
    trf(3,i+1) = trf(3,i) + dt * ( - 10 * trf(3,i) + 0.003 * trf(2,i) * trf(3,i) );
  end
%
%  Time plots.
%
  figure ( 1 )
  plot ( trf(1,:), trf(2,:), 'g-', ...
         trf(1,:), trf(3,:), 'r-', 'LineWidth', 3 )
  filename = sprintf ( 'trf_%d_time.png', step_num );
  title ( 'Predator Prey System Solved by Finite Differences' );
  grid on
  xlabel ( 'Time' );
  ylabel ( 'Populations' );
  print ( '-dpng', filename );
%
%  Phase plot.
%
  figure ( 2 )
  plot ( trf(2,:), trf(3,:), 'b-', 'LineWidth', 3 )
  filename = sprintf ( 'trf_%d_phase.png', step_num );
  title ( 'Predator Prey System Solved by Finite Differences' );
  grid on
  xlabel ( 'Rabbits' );
  ylabel ( 'Foxes' );
  print ( '-dpng', filename );
%
%  Write data to files.
%
  filename = sprintf ( 'trf_%d.txt', step_num );
  r8mat_write ( filename, 3, step_num + 1, trf );
  fprintf ( 1, '  T, R, F values written to "%s".\n', filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FD_PREDATOR_PREY\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  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:
%
%    08 February 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, 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.6e', table(i,j) );
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %24.16e', table(i,j) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function timestamp ( )

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

  return
end


function [A,B,C]=triAngles4Sides(a,b,c)
%%TRIANGLES4SIDES Given the sides of a triangle, find the angles of the
%         triangle. This just applies the law of cosines.
%
%INPUTS: a, b, c The scalar lengths of the sides of the triangle in any
%                order.
%
%OUTPUTS: A, B, C The angles of the triangle in radians. A is the angle
%                 opposite side a, B the angle opposite side b and C the
%                 angle opposite side C.
%
%The law of cosines is given in [1], among many other places.
%
%EXAMPLE:
%This recovers the angles of a 30-60-90 traingle.
% a=1;
% b=sqrt(3);
% c=2;
% [A,B,C]=triAngles4Sides(a,b,c);
% ADeg=rad2deg(A)
% BDeg=rad2deg(B)
% CDeg=rad2deg(C)
%
%REFERENCES:
%[1] Weisstein, Eric W. "Law of Cosines." From MathWorld--A Wolfram Web
%    Resource. https://mathworld.wolfram.com/LawofCosines.html
%
%October 2022 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

a2=a.*a;
b2=b.*b;
c2=c.*c;

A=acos((-a2+b2+c2)./(2*b.*c));
B=acos((a2-b2+c2)./(2*a.*c));
C=pi-A-B;
%We could have used:
%C=acos((a2+b2-c2)./(2*a.*b));
%But we know that the angles in a triangle in Euclidean geometry sum to 180
%degrees.

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 x=lincon(a,b,n)
%System of linear congruences
%   X = LINCON(A,B,N) solves the system of linear congruences
%
%       A(1) * X == B(1)  (mod N(1))
%       A(2) * X == B(2)  (mod N(2))
%       ...
%       A(m) * X == B(m)  (mod N(m))
%
%   The solution, X, will be given as a vector [x1 x2]
%   representing the general solution
%
%              X == x1  (mod x2)
%
%   Any specific answer can be found by letting
%   X = x1 + x2 * k  for any integer value of k.
%
%   If no solution exists [NaN NaN] will be returned.
%
%   A scalar input functions as a constant vector of the
%   same size as the other inputs.
%
%   Program is compatible with Variable Precision Integer
%   Arithmetic Toolbox available on File Exchange (#22725)
%   Use of VPI is recommended for large magnitude inputs
%   or outputs. If VPI is not used and internal calculations
%   exceed largest consecutive flint a warning will be given
%   that results may be inaccurate, along with [NaN NaN].
%
%   Example #1:
%   Solve the following system of linear congruences
%      2x == 2  (mod 6)
%      3x == 2  (mod 7)
%      2x == 4  (mod 8)
%
%   Solution:
%      a=[2 3 2]; b=[2 2 4]; n=[6 7 8];
%      x=lincon(a,b,n)
%
%   Verify:
%      isequal( mod(a*x(1),n) , b)
%
%
%   Example #2:
%   Use of VPI for large magnitude numbers. Solve the following
%   system of linear congruences
%         (1234567)x == 89       (mod 2^32)
%         (9876543)x == 21       (mod 3^50)
%            (5555)x == 62830211 (mod 7^10)
%
%   Solution:
%     a=[1234567 9876543 5555]; b=[89 21 62830211];
%     n=[vpi(2)^32 vpi(3)^50 vpi(7)^10];
%     x=lincon(a,b,n)
%
%   Verify:
%     isequal( mod(a*x(1),n) , b)
%

%   Mike Sheppard
%   Last Modified 11-Sep-2011

%Check Inputs
[a,b,n,isvpi]=LinConCheckInputs(a,b,n);

%Initialize
b=mod(b,n);  % Make all positive for consistency
m=length(a); % Number of congruences
x=[0 1];     % Initialize to x==0  (mod 1)
k=0;         % line number

while k<m

  k=k+1;

  % Go line by line, using previous solutions of X
  % as starting points for each line

  % Original k'th Equation, shown as scalar valued:
  %    a * X == b  (mod n)
  % However, X == x1  (mod x2), substituting in for X
  %    a * (x1 + x2*V) == b  (mod n)
  % Simplifying
  %    a * x2 * V == (b - a*x1)  (mod n)
  % Relabel, and now solve for V for the modified equation
  %    ak * V == bk  (mod n)

  ak=a(k)*x(2);
  bk=mod(b(k)-a(k)*x(1),n(k)); %Positive for consistency
  nk=n(k);

  % Use Linear congruence theorem
  % Solving ak * V = bk  (mod n) for V

  if isvpi
      [gk,ck,dk]=vpigcd2(ak,nk); %Subfunction below
  else
      [gk,ck,dk]=gcd(ak,nk);
  end

  % GK = CK*[AK] + DK*[NK]
  % (Extended Euclidean algorithm)

  if mod(bk,gk)==0 % Solution exists
      % V == v1  (mod v2)
      v2=nk/gk;
      v1=mod(ck*bk/gk,v2); %Positive for consistency
      v=[v1 v2];
  else % No valid solution
      v=[NaN NaN];
      k=Inf; %Terminate loop
  end

  % Solution to modified equation is
  %    V == v1  (mod v2)
  % From before, X is given by
  %    X = x1 + x2*V
  % Substituting in for V yields
  %    X == (x1+x2*v1) (mod x2*v2)
  % Redefine new solution for X for use in next iteration

  if isfinite(k)
      x=[x(1)+x(2)*v(1) x(2)*v(2)];
  else
      x=[NaN NaN]; %No valid solution
  end

end

% Solution is found
%    X == x1  (mod x2)

end

%SUBFUNCTIONS
%------------
function [a,b,n,isvpi]=LinConCheckInputs(a,b,n)

%Make column vectors
a=a(:); b=b(:); n=n(:);

%Check to see if all are integer valued
if any(a~=round(a)) || any(b~=round(b)) || any(n~=round(n))
   error('LINCON : Input vectors must be same size')
end

%Check sizes, they can either be scalar or same-sized vectors
na=length(a); nb=length(b); nn=length(n); m=max([na nb nn]);
if ~all([na nb nn]==m | [na nb nn]==1)
   error('LINCON : Non-scalar arguments must match in size.')
end

%If scalar, redefine as vectors of same size as other inputs
if na==1, a=a*ones(m,1); end
if nb==1, b=b*ones(m,1); end
if nn==1, n=n*ones(m,1); end

%Check to see if using VPI (Variable Precision Integers)
%Toolbox is available here:
%http://www.mathworks.com/matlabcentral/fileexchange/22725
isvpi=any(strcmp({class(a) class(b) class(n)},'vpi'));

end

function [g,c,d] = vpigcd2(a,b)
% Built-in GCD code given in VPI Toolbox solves
% for just the GCD; however, the coefficients for
% G = C*[A] + D*[B]
% are needed. This subfunction replaces the
% built-in GCD algorithm in VPI with one that
% uses the Extended Euclidean Algorithm
% (Simplified version of Matlab's built-in GCD)

c = 0; d = 0; g = 0;
u = [1 0 abs(a)];
v = [0 1 abs(b)];

while v(3)~=0
    q = quotient(u(3),v(3));
    t = u - v*q;
    u = v;
    v = t;
end

c = u(1) * sign(a);
d = u(2) * sign(b);
g = u(3);

end


function [p] = linortfit2(xdata, ydata)
% LINORTFIT2  Fit a line to data by ORTHOGONAL least-squares.
%    P = LINORTFIT2(X,Y) finds the coefficients of a 1st-order polynomial
%    that best fits the data (X,Y) in an ORTHOGONAL least-squares sense.
%    Consider the line P(1)*t + P(2), and the minimum (Euclidean) distance
%    between this line and each datapoint [X(i) Y(i)] -- LINORTFIT2 finds
%    P(1) and P(2) such that the sum of squared distances is minimized.

if ~isequal(size(xdata), size(ydata))
    error('linortfit2:XYSizeMismatch',...
          'X and Y vectors must be the same size.');
end

[N,C] = linortfitn([xdata(:) ydata(:)]);

% The hyperplane given by N * [x; y] + C == 0 is optimal.
% Convert to the form  y = p(1)*x + p(2), just like polyfit(xdata,ydata,1).
p = - [N(1)  C] / N(2);


function sim = gaussianKernel(x1, x2, sigma)
%RBFKERNEL returns a radial basis function kernel between x1 and x2
%   sim = gaussianKernel(x1, x2) returns a gaussian kernel between x1 and x2
%   and returns the value in sim

% Ensure that x1 and x2 are column vectors
x1 = x1(:); x2 = x2(:);

% You need to return the following variables correctly.
sim = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the similarity between x1
%               and x2 computed using a Gaussian kernel with bandwidth
%               sigma
%
%
temp = (x1-x2)'*(x1-x2);

sim = exp(-temp/(2*(sigma^2)));

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

end


function P = principalComponents(X,q)
%principalComponents Principal components of a vector population.
%   P = principalComponents(X,Q) computes the principal-component
%   vectors of the vector population contained in the rows of X, a
%   matrix of size K-by-n where K (assumed to be > 1) is the number of
%   vectors and n is their dimensionality. Q, with values in the range
%   [0,n], is the number of eigenvectors used in constructing the
%   principal-components transformation matrix. P is a structure with
%   the following fields:
%
%     P.Y      K-by-Q matrix whose columns are the principal-
%              component vectors.
%     P.A      Q-by-n principal components transformation matrix
%              whose rows are the Q eigenvectors of Cx corresponding
%              to the Q largest eigenvalues.
%     P.X      K-by-n matrix whose rows are the vectors
%              reconstructed from the principal-component vectors.
%              P.X and P.Y are identical if Q = n.
%     P.ems    The mean square error incurred in using only the Q
%              eigenvectors corresponding to the largest
%              eigenvalues. P.ems is 0 if Q = n.
%     P.Cx     The n-by-n covariance matrix of the population in X.
%     P.mx     The n-by-1 mean vector of the population in X.
%     P.Cy     The Q-by-Q covariance matrix of the population in
%              Y. The main diagonal contains the eigenvalues (in
%              descending order) corresponding to the Q
%              eigenvectors.
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

K = size(X,1);
X = double(X);

% Obtain the mean vector and covariance matrix of the vectors in X.
[P.Cx,P.mx] = covmatrix(X);
% Convert mean vector to a row vector.
P.mx = P.mx';

% Obtain the eigenvectors and corresponding eigenvalues of Cx.  The
% eigenvectors are the columns of n-by-n matrix V.  D is an n-by-n
% diagonal matrix whose elements along the main diagonal are the
% eigenvalues corresponding to the eigenvectors in V, so that X*V =
% D*V.
[V,D] = eig(P.Cx);

% Sort the eigenvalues in decreasing order. Rearrange the eigenvectors
% to match.
d = diag(D);
[d,idx] = sort(d);
d = flipud(d);
idx = flipud(idx);
D = diag(d);
V = V(:,idx);

% Now form the q rows of A from the first q columns of V.
P.A = V(:,1:q)';

% Compute the principal component vectors.
P.Y = P.A*(X - P.mx)'; % q-by-K matrix.

% Obtain the reconstructed vectors.
P.X = (P.A'*P.Y)' + P.mx;

% Convert P.Y to a K-by-q array and P.mx to an n-by-1 vector.
P.Y = P.Y';
P.mx = P.mx';

% The mean square error is the sum of all the eigenvalues minus the sum
% of the q largest eigenvalues.
d = diag(D);
P.ems = sum(d(q + 1:end));

% Covariance matrix of the Y's.
P.Cy = P.A*P.Cx*P.A';


function [A,B,C]=spherTriAngles4Sides(a,b,c,r)
%%SPHERTRIANGLES4SIDES Given the lengths of the sides of a spherical
%       triangle, find the angles of the triangle. Note that the angles of
%       a spherical triangle do not sum to pi. This is just an application
%       of the spherical law of cosines. Note that unlike with a EUclidean
%       triangle, one cannot just enter arbitrary distances for a, b, and c
%       (even if much smaller than the circumference of the sphere),
%       because certain distance relations are not possible and will result
%       in non-real solutions.
%
%INPUTS: a, b, c The lengths of the sides of the spherical triangle
%                in any order. If one wishes to convert multiple triangles
%                at once, these can be matrices.
%              r The scalar radius of the sphere on which the distances are
%                measured. If omitted or an empty matrix is passed, the
%                default of 1 is used.
%
%OUTPUTS: A, B, C The angles of the spherical triangle in radians. A is the
%                 angle opposite side a, B the angle opposite side b and C
%                 the angle opposite side C. The dimensions correspond to
%                 those of the inputs.
%
%The spherical law of cosines for the sides of a spherical triangle is
%stated in [1].
%
%EXAMPLE:
%First, we choose 3 points on the sphere, find the distances between them
%and then show that we can get the angles. Then, we just set some arbitrary
%distances that do not form a possible triangle on the spehre and we see
%that the angular results are complex.
%Choose 3 points in term of latitude-longitude on a sphere.
% llPoints=deg2rad([19,  21, 27;
%                 -158,-147,-152]);
% r=1;
% a=greatCircleDistance(llPoints(:,1),llPoints(:,2),r);
% b=greatCircleDistance(llPoints(:,2),llPoints(:,3),r);
% c=greatCircleDistance(llPoints(:,3),llPoints(:,1),r);
% [A,B,C]=spherTriAngles4Sides(a,b,c,r);
% ADeg=rad2deg(A)
% BDeg=rad2deg(B)
% CDeg=rad2deg(C)
% a=1;
% b=2;
% c=3;
% [A,B,C]=spherTriAngles4Sides(a,b,c,r)
%
%REFERENCES:
%[1] Weisstein, Eric W. "Law of Cosines." From MathWorld--A Wolfram Web
%    Resource. https://mathworld.wolfram.com/LawofCosines.html
%
%October 2022 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<4||isempty(r))
    r=1;
end

a=a./r;
b=b./r;
c=c./r;

cosa=cos(a);
sina=sin(a);
cosb=cos(b);
sinb=sin(b);
cosc=cos(c);
sinc=sin(c);

A=acos((cosa-cosb.*cosc)./(sinb.*sinc));
B=acos((cosb-cosa.*cosc)./(sina.*sinc));
C=acos((cosc-cosa.*cosb)./(sina.*sinb));

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 diffVal=angCircDiff(ang)
%%ANGCIRCDIFF Given two angles (in radians) on a unit circle, take their
%         difference in radians. The difference can only span +/-pi. For
%         example the difference between 0 and 2*pi should be zero as both
%         represent the same point.
%
%INPUTS: angs A 2XnumAng matrix of angles in radians. The differences
%               angs(1,:)-angs(2,:) in each column will be taken.
%
%OUTPUTS: diffVal A 1XnumAng vector of the differences on the unit circle
%                 of the angles. The shortest way around the circle is
%                 chosen. This goes from -pi to pi.
%
%This function simple takes the difference and wraps it to the range of -pi
%to pi with the wrapRange function.
%
%EXAMPLE:
%One can verify that for an angle of 0.1
% angCircDiff([0;0.1])-angCircDiff([0;0.1+2*pi])
%the difference is around machine precision. Similarly,
% angCircDiff([0;2*pi])
% is exactly zero
%
%January 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

diffVal=wrapRange(ang(1,:)-ang(2,:),-pi,pi);

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 result = is_orthonormal_set(A)
%
% Orthonormal Sets
%
% is_orthonormal_set(A) determines if a set of vectors in Euclidean n-space
% is orthonormal. The matrix A is formed from these vectors as its columns.
% That is, the subspace spanned by the set of vectors is the column space
% of A. The value 1 is returned if the set is orthonormal. The value 0 is
% returned if the set is not orthonormal. An error is returned if a set
% containing only zero vectors is attempted to be determined for
% orthonormality.
%
% For example, if the set of row vectors (u1,u2,...} is to be determined
% for orthonormality, set A to be equal to [u1' u2' ...].
%
%  Function written by Anthony Russo, downloaded from MatlabCentral.
%

matrix_size = size(A);

m = matrix_size(1,1);
n = matrix_size(1,2);

tolerance = 10^-10;

if A == zeros(m,n)
    error('The set that contains just zero vectors cannot be orthonormal.');
elseif n == 1
    if norm(A(1:m,1)) == 1
        result = 1;
    else
        result = 0;
    end
else
    if is_orthogonal_set(A) == 1
        length_counter = 0;

        for i = 1:n
            if abs(norm(A(1:m,i)) - 1) <= tolerance
                length_counter = length_counter + 1;
            end
        end

        if length_counter == n
            result = 1;
        else
            result = 0;
        end
    else
        result = 0;
    end
end


function v = logdet(A, op)
%LOGDET Computation of logarithm of determinant of a matrix
%
%   v = logdet(A);
%       computes the logarithm of determinant of A.
%
%       Here, A should be a square matrix of double or single class.
%       If A is singular, it will returns -inf.
%
%       Theoretically, this function should be functionally
%       equivalent to log(det(A)). However, it avoids the
%       overflow/underflow problems that are likely to
%       happen when applying det to large matrices.
%
%       The key idea is based on the mathematical fact that
%       the determinant of a triangular matrix equals the
%       product of its diagonal elements. Hence, the matrix's
%       log-determinant is equal to the sum of their logarithm
%       values. By keeping all computations in log-scale, the
%       problem of underflow/overflow caused by product of
%       many numbers can be effectively circumvented.
%
%       The implementation is based on LU factorization.
%
%   v = logdet(A, 'chol');
%       If A is positive definite, you can tell the function
%       to use Cholesky factorization to accomplish the task
%       using this syntax, which is substantially more efficient
%       for positive definite matrix.
%
%   Remarks
%   -------
%       logarithm of determinant of a matrix widely occurs in the
%       context of multivariate statistics. The log-pdf, entropy,
%       and divergence of Gaussian distribution typically comprises
%       a term in form of log-determinant. This function might be
%       useful there, especially in a high-dimensional space.
%
%       Theoretially, LU, QR can both do the job. However, LU
%       factorization is substantially faster. So, for generic
%       matrix, LU factorization is adopted.
%
%       For positive definite matrices, such as covariance matrices,
%       Cholesky factorization is typically more efficient. And it
%       is STRONGLY RECOMMENDED that you use the chol (2nd syntax above)
%       when you are sure that you are dealing with a positive definite
%       matrix.
%
%   Examples
%   --------
%       % compute the log-determinant of a generic matrix
%       A = rand(1000);
%       v = logdet(A);
%
%       % compute the log-determinant of a positive-definite matrix
%       A = rand(1000);
%       C = A * A';     % this makes C positive definite
%       v = logdet(C, 'chol');
%

%   Copyright 2008, Dahua Lin, MIT
%   Email: dhlin@mit.edu
%
%   This file can be freely modified or distributed for any kind of
%   purposes.
%

%% argument checking

assert(isfloat(A) && ndims(A) == 2 && size(A,1) == size(A,2), ...
    'logdet:invalidarg', ...
    'A should be a square matrix of double or single class.');

if nargin < 2
    use_chol = 0;
else
    assert(strcmpi(op, 'chol'), ...
        'logdet:invalidarg', ...
        'The second argument can only be a string ''chol'' if it is specified.');
    use_chol = 1;
end

%% computation

if use_chol
    v = 2 * sum(log(diag(chol(A))));
else
    [L, U, P] = lu(A);
    du = diag(U);
    c = det(P) * prod(sign(du));
    v = log(c) + sum(log(abs(du)));
end


function x=findQuadraticFitVertex(x1,x2,param1,param2,param3)
%%FINDQUADRATICFIRVERTEX Find the minimum of a parabola that fits given
%           scalar data when presented with one of two parameterizations.
%           the first parameterization uses two function values and one
%           derivaitve value. The second parameterization uses just two
%           derivative values.
%
%INPUTS: x1, x2 The two points at which the values are taken.
% param1,param2,param3 These thee values can be given in two ways, which
%               determine their meaning. The first is:
%               f1 The value of the function at x1.
%               f2 The value of the function at x2.
%               g1 The derivative of the function at x1.
%               The other parameterization is
%               g1 The gradient at x1.
%               g2 The gradient at x2.
%               param3 is either omitted or an empty matrix is passed when
%               using the second formulation.
%
%OUTPUTS: x The interpolated critical point (minimum or maximum) of the
%           fitted parabola.
%
%For the first formulation of the problem, we are given equations with
%unknown coefficients (a,b,c):
% f1==a*x1^2+b*x1+c
% f2==a*x2^2+b*x2+c
% gl==b+2*a*x1
%Solving for (a,b,c) one gets
%a=(-f1+f2+g1*(x1-x2))/(x1-x2)^2
%b=(2*f1*x1-x1*(2*f2+g1*x1)+g1*x2^2)/(x1-x2)^2
%c=(f2*x1^2+g1*x1*(x1-x2)*x2+f1*x2*(-2*x1+x2))/(x1-x2)^2
%Substitutign into the expression for the derivative and setting the
%derivative equal to zero, one gets a value of x of
%x=x1+(g1*(x2-x1)^2)/(2*(f1-f2+g1*(x2-x1)))
%
%For the second formulation of the problem, we are given equations with
%unknown coefficients (a,b,c):
% f1==a*x1^2+b*x1+c
% g1==b+2*a*x1
% g2==b+2*a*x2
%Solving for (a,b,c) one gets
% a=(g1-g2)/(2*x1-2*x2)
% b=(g2*x1-g1*x2)/(x1-x2)
% c=f1+(x1*(-(g1+g2)*x1+2*g1*x2))/(2*(x1-x2))
%Substituting into the expression for the derivative and setting the
%derivative equal to zero, one gets a value of x of
% x=x2+g2*(x1-x2)/(g2-g1);
%which does not require the value f1.
%
%EXAMPLE:
%Here, we use the function f=3*(x-12)*(x-14)=3*x^2-78*x+504;
% x1=-10;
% x2=24;
% f1=3*x1^2-78*x1+504;
% f2=3*x2^2-78*x2+504;
% g1=2*3*x1-78;
% g2=2*3*x2-78;
% xSol1=findQuadraticFitVertex(x1,x2,f1,f2,g1)
% xSol2=findQuadraticFitVertex(x1,x2,g1,g2)
%One will find that both xSol1 and xSol2 =13, which is the minimum point of
%the parabola.
%
%February 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin>4&&~isempty(param3))
    %Given the first type of parameterization.
    f1=param1;
    f2=param2;
    g1=param3;

    diff=x2-x1;
    x=x1+(g1*diff^2)/(2*(f1-f2+g1*diff));
else
    %Given the second type of parameterization.
    g1=param1;
    g2=param2;

    x=x2+g2*(x1-x2)/(g2-g1);
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 [hz,hprimez] = cnnactivate(z,type)
%CNNACTIVATE Activation function for CNNs.
%   [HZ,HPRIMEZ] = CNNACTIVATE(Z,TYPE) outputs activation values, HZ =
%   h(z), and its derivative, HPRIMEZ = h'(z), evaluated at each element
%   of z, where z is a vector or matrix (see Sections 14.5 and 14.6 in
%   DIPUM3E). The type of activation function used is specified in
%   string TYPE, valid values of which are:
%
%   TYPE                            EQUATION IMPLEMENTED
%
%   'sigmoid' (the default)         h(z) = 1./(1 + exp(-z))
%                                   hprime(z) = h.*(1 - h)
%
%   'tanh'                          h(z) = tanh(z)
%                                   hprime(z) = 1 - h.^2
%
%   'ReLU'                          h(z) = max(0,z)
%                                   hprime(z) = 1 for z > 0
%                                             = 0 otherwise
%
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

% Set default.
if nargin == 1
    type = 'sigmoid';
end

% Set to lower case to reduce possible user case typo errors.
type = lower(type);

% Compute h and hprime as functions of z.
switch type
    case 'sigmoid'
        hz = 1./(1 + exp(-z));
        hprimez = hz.*(1 - hz);
    case 'tanh'
        hz = tanh(z);
        hprimez = 1 - hz.^2;
    case 'relu'
       % Original based on the definition of ReLU. Works well provided
       % that alpha is small enough.
        hz = max(0,z);
        hprimez = zeros(size(z));
        hprimez(z > 0) = 1;
end


%--- help for norm ---
%
% NORM   Matrix or vector norm.
%      NORM(X,2) returns the 2-norm of X.
%
%      NORM(X) is the same as NORM(X,2).
%
%      NORM(X,1) returns the 1-norm of X.
%
%      NORM(X,Inf) returns the infinity norm of X.
%
%      NORM(X,'fro') returns the Frobenius norm of X.
%
%    In addition, for vectors...
%
%      NORM(V,P) returns the p-norm of V defined as SUM(ABS(V).^P)^(1/P).
%
%      NORM(V,Inf) returns the largest element of ABS(V).
%
%      NORM(V,-Inf) returns the smallest element of ABS(V).
%
%    By convention, NaN is returned if X or V contains NaNs.
%
%    See also COND, RCOND, CONDEST, NORMEST, HYPOT.
%
%    Reference page in Doc Center
%       doc norm
%
%


function [gm samc] = mcurvature_vec(x,y,z)
% Description: The function calculates mean curvature and
% Surface Avg Mean Curvature (SAMC) of a surface formed by x, y & z.
% The input are the coordinate matrices x, y & z. The
% matrices can be formed using meshgrid or similar functions.
% This code is a vectorized form of original code (mcurvature) posted
% on Matlab File Exchange.

% The mean curvature is calculated according to the formula:

% If x:U->R^3 is a regular patch, then the mean curvature is given by
%
%         H = (eG-2fF+gE)/(2(EG-F^2)),
%
% where E, F, and G are coefficients of the first fundamental form and
% e, f, and g are coefficients of the second fundamental form

% Reference: Gray, A. "The Gaussian and Mean Curvatures." §16.5 in
% Modern Differential Geometry of Curves and Surfaces with Mathematica,
% 2nd ed. Boca Raton, FL: CRC Press, pp. 373-380, 1997 (p. 377).

% Inspired by:
% Title:  	Mean Curvature
% Author: 	Ahmed Elnaggar
% Summary: 	Calculate the Mean curvature of a given surface (x,y,z).

gm = zeros(size(z));
[xu,xv]     =   gradient(x);
[xuu,xuv]   =   gradient(xu);
[xvu,xvv]   =   gradient(xv);

[yu,yv]     =   gradient(y);
[yuu,yuv]   =   gradient(yu);
[yvu,yvv]   =   gradient(yv);

[zu,zv]     =   gradient(z);
[zuu,zuv]   =   gradient(zu);
[zvu,zvv]   =   gradient(zv);

Xu(:,:,1) = xu;
Xu(:,:,2) = yu;
Xu(:,:,3) = zu;

Xv(:,:,1) = xv;
Xv(:,:,2) = yv;
Xv(:,:,3) = zv;

Xuu(:,:,1) = xuu;
Xuu(:,:,2) = yuu;
Xuu(:,:,3) = zuu;

Xuv(:,:,1) = xuv;
Xuv(:,:,2) = yuv;
Xuv(:,:,3) = zuv;

Xvv(:,:,1) = xvv;
Xvv(:,:,2) = yvv;
Xvv(:,:,3) = zvv;

E = dot(Xu,Xu,3);
F           =   dot(Xu,Xv,3);
G           =   dot(Xv,Xv,3);
m           =   cross(Xu,Xv,3);
temp(:,:,1) = sqrt(sum(m.*m,3));
temp(:,:,2) = temp(:,:,1);
temp(:,:,3) = temp(:,:,1);
n           =   m./temp;
L           =   dot(Xuu,n,3);
M           =   dot(Xuv,n,3);
N           =   dot(Xvv,n,3);
gm          =   ((E.*N)+(G.*L)-(2.*F.*M))./(2.*(E.*G - F.^2));

dim = size(z);
samc = 1/ (dim(1) * dim(2)) * sum (gm(:).^2);


function y=expSlope2(x)
%%EXPSLOPE2  Evaluate the function 2*(exp(x)-1-x)/x^2 avoiding problems at
%            the point x=0, where the limit equals 1. This function arises
%            in range enclosure algorithms for interval arithmetic.
%
%INPUTS: x A vector of matrix of real values at which the function should
%          be evaluated.
%
%OUTPUTS: y The value(s) of the function 2*(exp(x)-1-x)/x^2 at the point(s)
%           in x.
%
%For values of x having magnitude over 1e-2 or for complex values, the
%function is evaluated as written. For smaller values, a Taylor series
%expansion is used to avoid the singularity near the origin. The Taylor
%series expansion is simple, because the value of the nth derivative at 0
%is just 1/(n+1).
%
%This is one of the slope function in Table 10.6 of Section 10.6.2 of [1].
%This file implements the function for non-intervals. See the Interval
%class for an implementation for Interval arithmetic.
%
%REFERENCES:
%[1] IEEE Standard for Interval Arithmetic," in IEEE Std 1788-2015,
%    pp.1-97, June 30 2015.
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Allocate space
y=zeros(size(x));

%For large enough values, use the standard function.
sel=abs(x)>1e-2|~isreal(x);
x1=x(sel);
y(sel)=2*(expm1(x1)-x1)./x1.^2;

%For smaller magnitude values, use a sixth-order Taylor series expansion.
%The relative error at 10^-2 is on the order of 1e-20, which is less than
%the precision of a double floating point number at that value. The series
%is given in Horner form.
x1=x(~sel);
y(~sel)=1+x1.*(1/3+x1.*(1/12+x1.*(1/60+x1.*(1/360+(1/2520+x1./20160).*x1))));

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.


%% Test Newton Method 2
% Test Newton_n_sytem subroutine

% Clear memory
clear all; close all; clc;

% display format
format long

%% Examples
example = 3;
switch example
    case{1} % 2-by-2 Polynomials,
        % Define vector of functions 'f' and matrix of partial derivates 'df',
        f = inline('[x(1)^3+x(2)-1 ; x(2)^3-x(1)+1]');
        df = inline('[3*x(1)^2, 1  ; -1,  3*x(2)^2]');

        % Plot figures,
        g1 = 'x^3+y-1'; g2 = 'y^3-x+1'; xy_range = [-4,4,-4,4];
        figure(1); grid on;
        hold on;
        ez1 = ezplot(g1,xy_range);
        ez2 = ezplot(g2,xy_range);
        hold off;
        legend('g1(x,y)=x^3+y-1','g2(x,y)=y^3-x+1');
        set(ez1,'color',[0 0 1]);
        set(ez2,'color',[1 0 0]);
        title('Solving x^3+y-1 & y^3-x+1 for {x,y}')

        % Initial Guess,
        x0 = [.5;.5] ;

    case{2} % 2-by-2 Nonlinear system,
        % Define vector of functions 'f' and matrix of partial derivates 'df',
        f = inline('[10*x(1)^2+sin(x(2))-20 ; x(1)^4+5*x(2)-6]');
        df = inline('[20*x(1), cos(x(2))  ; 4*x(1)^3, 5]');

        % Plot figures,
        g1 = '10*x^2+sin(y)-20'; g2 = 'x^4+5*y-6'; xy_range = [-8,8,-8,8];
        figure(1); grid on;
        hold on;
        ez1 = ezplot(g1,xy_range);
        ez2 = ezplot(g2,xy_range);
        hold off;
        legend('g1(x,y)=10x^2+sin(y)-20','g2(x,y)=x^4+5y-6',1);
        set(ez1,'color',[0 0 1]);
        set(ez2,'color',[1 0 0]);
        title('Solving 10x^2+sin(y)=20 & x^4+5y=6 for {x,y}')

        % Initial Guess,
        x0 = [1;1];

        case{3} % 3-by-3 Polynomial System,
        % Define vector of functions 'f' and matrix of partial derivates 'df',
        f = inline('[x(1)^3-2*x(2)-2 ; x(1)^3-5*x(3)^2+7 ; x(2)*x(3)^2-1]');
        df = inline('[3*x(1)^2 -2 0;3*x(1)^2 0 -10*x(3);0 x(3)^2 2*x(2)*x(3)]');

        % Initial Guess,
        x0 = [1;1;1];
end

%% Convergence criteria
    % Define max number of iterations,
    n_max = 8;

    % Define tolerance,
    tol = 1e-6;
    tol = tol*ones(size(2,1));

%% Use Newton_n_sytem.m func,
tic;
x = x0; x_next = Newton_n_system(f,df,x); n = 1;
while and((n < n_max),(abs(x_next - x) > tol))
    x = x_next;
    x_next = Newton_n_system(f,df,x);
    n = n + 1;
end
fprintf('My solver: %1.12f \n',x) % show me the result
t1 = toc; % time for Costumb solver

%% Using Matlab solver,
tic;
x = x0; x = fsolve(f,x);
fprintf('Matlab solver: %1.12f \n',x) % show me the result
t2 = toc; % time for Matlab solver

% how fast is our Newton Solver,
fprintf('Costum Solver is: %1.1f times faster than Matlab solver \n',t2/t1)


function [ x, w ] = ncc_compute ( n )

%*****************************************************************************80
%
%% NCC_COMPUTE computes a Newton-Cotes Closed quadrature rule.
%
%  Discussion:
%
%    For the interval [-1,+1], the Newton-Cotes Closed quadrature rule
%    estimates
%
%      Integral ( -1 <= X <= +1 ) F(X) dX
%
%    using N abscissas X and weights W:
%
%      sum ( 1 <= I <= N ) W(I) * F ( X(I) ).
%
%    For the CLOSED rule, the abscissas are equally spaced, and include
%    the end points.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order.
%
%    Output, real X(N), the abscissas.
%
%    Output, real W(N), the weights.
%
  x = ncc_compute_points ( n );

  w = ncc_compute_weights ( n );

  return
end


% KRON   Kronecker tensor product.
%    KRON(X,Y) is the Kronecker tensor product of X and Y.
%    The result is a large matrix formed by taking all possible
%    products between the elements of X and those of Y. For
%    example, if X is 2 by 3, then KRON(X,Y) is
%
%       [ X(1,1)*Y  X(1,2)*Y  X(1,3)*Y
%         X(2,1)*Y  X(2,2)*Y  X(2,3)*Y ]
%
%    If either X or Y is sparse, only nonzero elements are multiplied
%    in the computation, and the result is sparse.
%
%    Class support for inputs X,Y:
%       float: double, single
%       integers: uint8, int8, uint16, int16, uint32, int32, uint64, int64
%
%    Reference page in Doc Center
%       doc kron
%
%    Other functions named kron
%
%       splanar/kron    sym/kron
%


function y = norm_cdf(x,mu,sigma)
%NORM_CDF Normal cumulative probability density function (cdf)
%
%   Y = NORMCDF(X,MU,SIGMA) Returns the normal cdf with
%   mean, MU, and standard deviation, SIGMA, 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.
%
%   Default values for MU and SIGMA are 0 and 1 respectively.
%
% Copyright (c) 1998-2004,2011 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,
  sigma = 1;
end

if nargin < 2;
  mu = 0;
end

if nargin < 1,
  error('Requires at least one input argument.');
end

y = 0.5 * erfc(-((x-mu) ./ sigma) ./ sqrt(2));


function J = computeCostMulti(X, y, theta)
%COMPUTECOSTMULTI Compute cost for linear regression with multiple variables
%   J = COMPUTECOSTMULTI(X, y, theta) computes the cost of using theta as the
%   parameter for linear regression to fit the data points in X and y

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

% You need to return the following variables correctly
J = 0;

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta
%               You should set J to the cost.

J = 1 / (2 * m) * sum( (X * theta - y) .^ 2);

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

end


function value = circle_area_2d ( r )

%*****************************************************************************80
%
%% CIRCLE_AREA_2D returns the area of a circle in 2D.
%
%  Integration region:
%
%    Points (X,Y) such that
%
%      ( X - XC )**2 + ( Y - YC )**2 <= R**2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the radius of the circle.
%
%    Output, real CIRCLE_AREA_2D, the area of the circle.
%
  value = pi * r * r;

  return
end


function [ x, y, a, b, c, ierror ] = r8poly2_ex2 ( x1, y1, x2, y2, x3, y3 )

%*****************************************************************************80
%
%% R8POLY2_EX2 finds the extremal point of a parabola determined by three points.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 September 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X1, Y1, X2, Y2, X3, Y3, the coordinates of
%    three points on the parabola.  X1, X2 and X3 must be distinct.
%
%    Output, real X, Y, the X coordinate of the extremal
%    point of the parabola, and the value of the parabola at that point.
%
%    Output, real A, B, C, the coefficients that define the
%    parabola: P(X) = A * X**2 + B * X + C.
%
%    Output, integer IERROR, error flag.
%    0, no error.
%    1, two of the X values are equal.
%    2, the data lies on a straight line; there is no finite extremal
%    point.
%
  ierror = 0;
  x = x1;
  y = y1;
  a = 0.0;
  b = 0.0;
  c = 0.0;

  if ( x1 == x2 || x2 == x3 || x3 == x1 )
    ierror = 1;
    return
  end

  if ( y1 == y2 && y2 == y3 && y3 == y1 )
    x = x1
    y = y1
    return
  end
%
%  Set up the Vandermonde matrix.
%
  v(1,1) = 1.0;
  v(1,2) = x1;
  v(1,3) = x1 * x1;

  v(2,1) = 1.0;
  v(2,2) = x2;
  v(2,3) = x2 * x2;

  v(3,1) = 1.0;
  v(3,2) = x3;
  v(3,3) = x3 * x3;
%
%  Get the inverse.
%
  [ w, det ] = r8mat_inverse_3d ( v );
%
%  Compute the parabolic coefficients.
%
  c = w(1,1) * y1 + w(1,2) * y2 + w(1,3) * y3;
  b = w(2,1) * y1 + w(2,2) * y2 + w(2,3) * y3;
  a = w(3,1) * y1 + w(3,2) * y2 + w(3,3) * y3;
%
%  Determine the extremal point.
%
  if ( a == 0.0 )
    ierror = 2;
    return
  end

  x = -b / ( 2.0 * a );
  y = a * x * x + b * x + c;

  return
end


function J=normVecJacob(x)
%%NORVECJACOB Consider a unit vector created as u=x/norm(x). This function
%         returns the partial derivatives of u with respect to the elements
%         of x. This partial derivative
%
%INPUTS: x A real NX1 vector.
%
%OUTPUTS: J The NXN partial derivative matrix The columns are the element
%           of x with respect to which the partial derivative is taken and
%           the rows are the elements of u.
%
%EXAMPLE:
%Here, we verify that the output of this function agrees with the numerical
%differentiation result.
% x=[4;-18;12];
% u=@(x)x/norm(x);
% JNumDiff=numDiff(x,u,3);
% J=normVecJacob(x);
% RelErr=max(abs((J(:)-JNumDiff(:))./J(:)))
%The relative error will be about 3.8488e-10, indicating a good level of
%agreement between the numerical differentiation result and the analytic
%result.
%
%November 2020 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

xDim=length(x);
normX=norm(x);

J=-x*x'/normX^3+eye(xDim,xDim)/normX;

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 val=geometricMean(x,dim)
%%GEOMETRICMEAN Compute the geometric mean of a set of samples.
%
%INPUTS: x The set of samples over which the geometric mean is to be found.
%          How the function handles vectors and matrices is determined by
%          the parameter dim.
%      dim An optional parameter specifying over which dimension of x the
%          geometric mean is to be taken. If dim is omitted or an empty
%          matrix is passsed, then if x is a vector, the geometric mean is
%          found over all elements of the vector. If x is a matrix, then
%          the mean is found over the columns of the matrix (resulting in a
%          row vector), and if x is an n-dimensional (n>2) matrix, then the
%          geometric mean is found over the first non-singleton dimension
%          of the matrix.
%
%OUTPUT: val The geometric mean of x taken over the appropriate dimension.
%
%The geometric mean of n items is the nth-root of the product of those
%items. The computation is performed using logarithms to avoid overflows.
%This can mean that one does not obtain the desired complex nth root when
%negative values are complex numbers are the argument as there are multiple
%solutions to the nth root.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(isempty(x))
    val=[];
    return
end

xDims=size(x);
if(nargin<2||isempty(dim))
    if(length(xDims)<3)%If x is a vector or matrix.
        if(xDims(1)==1||xDims(2)==1)%If x is a vector
            x=x(:);
            dim=1;
            n=length(x);
        else%x is a matrix, go over the columns.
            dim=2;
            n=xDims(2);
        end
    else%If x is an n-dimensional matrix.
        dim=find(xDims>1,1);
        if(isempty(dim))
            dim=1;
            n=1;
        else
            n=xDims(dim);
        end
    end
else
    n=xDims(dim);
end

%We could do prod(x,dim).^(1/n);, but that is likely to overflow if there
%are many values. Thus, we take the exponent of the sum of the logarithm.
val=exp((1/n)*sum(log(x),dim));

end

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


function value = mono_total_enum ( m, n )

%*****************************************************************************80
%
%% MONO_TOTAL_ENUM enumerates monomials in M dimensions of degree equal to N.
%
%  Discussion:
%
%    For M = 3, we have the following values:
%
%    N  VALUE
%
%    0    1
%    1    3
%    2    6
%    3   10
%    4   15
%    5   21
%
%    In particular, VALUE(3,3) = 10 because we have the 10 monomials:
%
%      x^3, x^2y, x^2z, xy^2, xyz, xz^3, y^3, y^2z, yz^2, z^3.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 September 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the maximum degree.
%
%    Output, integer VALUE, the number of monomials in D variables,
%    of total degree N.
%
  value = nchoosek ( n + m - 1, n );

  return
end


function value = r8vec_scalar_triple_product ( v1, v2, v3 )

%*****************************************************************************80
%
%% R8VEC_SCALAR_TRIPLE_PRODUCT finds the scalar triple product in 3D.
%
%  Discussion:
%
%    [A,B,C] = A dot ( B cross C )
%            = B dot ( C cross A )
%            = C dot ( A cross B )
%
%    The volume of a parallelepiped, whose sides are given by
%    vectors A, B, and C, is abs ( A dot ( B cross C ) ).
%
%    Three vectors are coplanar if and only if their scalar triple
%    product vanishes.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 August 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Eric Weisstein,
%    "Scalar Triple Product",
%    CRC Concise Encyclopedia of Mathematics, 1999
%
%  Parameters:
%
%    Input, real V1(3), V2(3), V3(3), the vectors.
%
%    Output, real VALUE, the scalar triple product.
%
  v4 = r8vec_cross_product_3d ( v2, v3 );

  value = v1' * v4;

  return
end