%% Unstructured Grid
% This examples shows how to use ConstructProjector2D on unstructured
% grids. Two sets of points are generated randomly.
clear;clc;
%% Initializing Part I
disp('- Initializing')
rSource=2*pi;
rDestination=rSource*1.05; % This slightly bigger radius causes some points
                           % on destination grid being outside of the
                           % source grid; hence, on those points it is
                           % actually extrapolation and not interpolation.

ns=300;
nd=50;

nPoly=4; % We gonna fit a fourth order polynomial,
         % i.e. sum_{n,m=0}^{n,m=nPoly} x^n*y^m
nInterp=35; % nPoly=4 requires 25 points. However,
            % we are going to use 35 points. This would be
            % the least-square fit of the surface.
            % Note that: min(nInterp)=(nPoly+1)^2. Otherwise it won't work.
%% Generating the Source grid
disp('- Generating the Source grid')
xs=rand(ns,1)*2*rSource-rSource;
ys=rand(ns,1)*2*rSource-rSource;

%% Generating the Destination Grid
disp('- Generating the Destination Grid')
xd=rand(nd,1)*2*rDestination-rDestination;
yd=rand(nd,1)*2*rDestination-rDestination;

figure
plot(xs,ys,'b.');
hold on
plot(xd,yd,'k.');
axis tight
axis square
legend('Source Grid','Destination Grid')
title('Distribution of the points')

%% Generating the interpolant
disp('- Generating the interpolant')
P=ConstructProjector2D(xs,ys,xd,yd,nPoly,nInterp);

%% Generating sum data
disp('- Generating sum data and interpolating')
F1=@(x,y) (sin(sqrt(x.^2+y.^2)));
F2=@(x,y) (sin(x).*cos(y));
F3=@(x,y) (exp(-sqrt(x.^2+y.^2)));
F4=@(x,y,x0,y0) (exp(-sqrt((x-x0).^2+(y-y0).^2)));

z=zeros(ns,4);
z(:,1)=F1(xs,ys);
z(:,2)=F2(xs,ys);
z(:,3)=F3(xs,ys);
z(:,4)=F4(xs,ys,0,0);

z_Analytic=zeros(nd,4);
z_Analytic(:,1)=F1(xd,yd);
z_Analytic(:,2)=F2(xd,yd);
z_Analytic(:,3)=F3(xd,yd);
z_Analytic(:,4)=F4(xd,yd,0,0);

% Interpolating
z_interp=P*z;

% Note that since the points are randomly generated the RMSE would change
% each time. Depending on how the points are distributed you may get very
% good or very bad RMSE.
RMSE=sqrt(mean( (z_interp-z_Analytic).^2 ));

%% plotting
figure
for i=1:4
  subplot(2,2,i)
  plot(z_interp(:,i),'b.');
  hold on
  plot(z_Analytic(:,i),'r.');
  legend('Interpolated','Analytic');
  title(['RMSE= ' num2str(RMSE(i))]);
end


classdef BernoulliD
%%BERNOULLID Functions to handle the Bernoulli distribution. This is just a
%            binary distribution having a certain probability p of being 1.
%Implemented methods are: mean, var, PMF, CDF, rand, momentGenFun, entropy
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)
function val=mean(p)
%%MEAN Obtain the mean of the Bernoulli distribution.
%
%INPUTS: p The probability of success of a Bernoulli trial.
%
%OUTPUTS: val The mean of the Bernoulli distribution.
%
%As noted on the page opposite the inside front cover of [1], the mean is
%just p.
%
%EXAMPLE:
%We show that the mean matches the sample mean.
% p=0.75;
% meanVal=BernoulliD.mean(p)
% numRuns=1e6;
% meanSamp=mean(BernoulliD.rand([numRuns,1],p))
%One will see that both values are about 0.75.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=p;
end

function val=var(p)
%%VAR Obtain the variance of the Bernoulli distribution.
%
%INPUTS: p The probability of success of a Bernoulli trial.
%
%OUTPUTS: val The variance of the Bernoulli distribution.
%
%As noted on the page opposite the inside front cover of [1], the mean is
%just p*(1-p).
%
%EXAMPLE:
%We show that the mean matches the sample mean.
% p=0.75;
% varVal=BernoulliD.var(p)
% numRuns=1e6;
% varSamp=var(BernoulliD.rand([numRuns,1],p))
%One will see that both values are about 0.1875.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

   val=p*(1-p);
end

function val=PMF(x,p)
%%PMF Evaluate the Bernoulli probability mass function (PMF) at given
%     points.
%
%INPUTS: x The point(s) at which the Bernoulli PMF is to be evaluated. For
%          nonzero PMF values, x=0 or x=1.
%        p The probability of success of a Bernoulli trial.
%
%OUTPUTS: val The value(s) of the Bernoulli PMF.
%
%The Bernoulli distribution is given on the page opposite the inside front
%cover of [1].
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=zeros(size(x));
    val(x==0)=1-p;
    val(x==1)=p;
end

function val=CDF(x,p)
%%CDF Evaluate the cumulative distribution function of the Bernoulli
%     distribution at desired points.
%
%INPUTS: x The point(s) at which the Bernoulli PMF is to be evaluated. For
%          nonzero PMF values, x=0 or x=1.
%        p The probability of success of a Bernoulli trial.
%
%OUTPUTS: val The CDF of the Bernoulli distribution evaluated at the
%             desired point(s).
%
%The Bernoulli distribution is given on the page opposite the inside front
%cover of [1].
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=zeros(size(x));
    sel=(0<=x|x<1);
    val(sel)=1-p;
    sel=(x>=1);
    val(sel)=p;
end

function x=rand(N,p)
%%RAND Generate Bernoulli random variables with a given mean.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row vector, then rand
%          returns an MXN1 matrix of random variables.
%        p The probability of success of a Bernoulli trial.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated Bernoulli random variables.
%
%The Bernoulli random variables are generated simply using the comparison
%mentioned in Chapter 4 of [1]. [1].
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(isscalar(N))
        dims=[N, N];
    else
        dims=N;
    end

    x=rand(dims)<=p;
end

function momentVal=momentGenFun(p,numDerivs,t)
%%MOMENTGENFUN Evaluate the moment generating function (or one of its
%              derivatives) of the Bernoulli distribution. Taking the kth
%              derivative of the moment generating function and evaluating
%              it at t=0 provides the kth noncentral moment of the
%              distribution.
%
%INPUTS: p The probability of success of a Bernoulli trial.
% numDerivs The number of derivatives to take with respect to the
%          argument of the moment generating function. numDerivs>=0.
%        t The matrix of points where the moment generating function
%          should be evaluated. If this parameter is omitted or an
%          empty matrix is passed, the default value of 0 is used.
%
%OUTPUTS: momentVal A numPointsX1 vector of the values of the derivatives
%                   of the moment generating function given at the points
%                   in t or at t=0 if t is omitted.
%
%The moment generating function of a random variable is defined to be
%E(exp(t*x)) where E is the expected value operator, x is the random
%variable and t is a real parameter. The moment generating function for the
%Bernoulli distribution is just (1-p)+p*exp(t). Derivatives are
%straightforward.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(nargin<3||isempty(t))
        t=0;
    end

    momentVal=exp(t)*p;
    sel=numDerivs==0;
    momentVal(sel)=momentVal(sel)+1-p;
end

function entropyVal=entropy(p)
%%ENTROPY Obtain the Shannon entropy of the Bernoulli distribution given in
%         nats. The Shannon entropy of a discrete distribution is
%         entropy=-sum_x Pr(x)*log(Pr(x)) where the sum is over all
%         discrete values of x. Units of nats mean that the natural
%         logarithm is used in the definition.
%
%INPUTS: p The probability of success of a Bernoulli trial.
%
%OUTPUTS: entropyVal The value of the Shannon entropy in nats.
%
%Shannon entropy is defined in Chapter 2 of [1].
%
%REFERENCES:
%[1] T. M. Cover and J. A. Thomas, Elements of Information Theory, 2nd ed.
%    Hoboken, NJ: Wiley-Interscience, 2006.
%
%April 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(p==0||p==1)
        entropyVal=0;
        return;
    end

    q=1-p;

    entropyVal=-q*log(q)-p*log(p);
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.


classdef NegativeBinomialD
%%NEGATIVEBINOMIALD Functions to handle the negative binomial
%           distribution. The Polya distribution and the Pascal
%           distribution are special cases of this distribution. The
%           negative binomial distribution is the number of sucesses in
%           independent trials before a specified number of failures
%           occurs.
%Implemented methods are: mean, var, PMF, CDF, rand
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(r,p)
%%MEAN Obtain the mean of the negative binomial distribution.
%
%INPUTS: r This is the integer number of failed trials until sampling stops
%          (defining the distribution).
%        p This is the probability of success for each trial.
%
%OUTPUTS: val The mean of the distribution.
%
%The negative binomial distribution is discussed in Chapter 4 of [1].
%
%EXAMPLE:
%We verify the computed mean by comparing it to the sample mean.
% p=0.8;
% r=4;
% meanVal=NegativeBinomialD.mean(r,p)
% numSamp=1e5;
% sampMeanVal=mean(NegativeBinomialD.rand([1,numSamp],r,p))
%One will find both values are about 16.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=p*r/(1-p);
end

function val=var(r,p)
%%VAR Obtain the variance of the negative binomial distribution.
%
%INPUTS: r This is the integer number of failed trials until sampling stops
%          (defining the distribution).
%        p This is the probability of success for each trial.
%
%OUTPUTS: val The variance of the distribution.
%
%The negative binomial distribution is discussed in Chapter 4 of [1].
%
%EXAMPLE:
%We verify the computed variance by comparing it to the sample variance.
% p=0.8;
% r=4;
% varVal=NegativeBinomialD.var(r,p)
% numSamp=1e5;
% sampVarVal=var(NegativeBinomialD.rand([1,numSamp],r,p))
%One will find both values are about 80.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=p*r/(1-p)^2;
end

function val=PMF(k,r,p)
%%PMF Evaluate the probability mass function (PMF) of the negative binomial
%     distribution at given points.
%
%INPUTS: x The point(s) at which the negative binomial PMF is to be
%          evaluated. x is an integer. For nonzero PMF values, x>=r.
%        r This is the integer number of failed trials until sampling stops
%          (defining the distribution).
%        p This is the probability of success for each trial.
%
%OUTPUTS: val The value(s) of the negative binomial PMF.
%
%The negative binomial distribution is discussed in Chapter 4 of [1].

%EXAMPLE:
%Here, we validate the PMF by generating random samples and comparing the
%PMF plot with a histogram of the random samples.
% p=0.8;
% r=4;
% numSamples=1e5;
% figure(1)
% clf
% histogram(NegativeBinomialD.rand([numSamples,1],r,p),'BinWidth',1,'Normalization','pdf')
% hold on
% x=0:80;
% vals=NegativeBinomialD.PMF(x,r,p);
% stem(x,vals,'linewidth',2)
% h1=xlabel('x');
% h2=ylabel('PDF(x)');
% set(gca,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h1,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h2,'FontSize',14,'FontWeight','bold','FontName','Times')
%One will see that the histogram matches well with the plot.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=zeros(size(k));
    numEls=numel(val);

    constVal=(1-p)^r;
    for curEl=1:numEls
        if(k(curEl)>=0)
            val(curEl)=binomial(k(curEl)+r-1,k(curEl))*constVal*p^k(curEl);
        end
    end
end

function val=CDF(k,r,p)
%%CDF Evaluate the cumulative distribution function (CDF) of the negative
%     binomial distribution at given points.
%
%INPUTS: x The point(s) at which the negative binomial CDF is to be
%          evaluated. x is an integer. For nonzero CDF values, x>=r.
%        r This is the integer number of failed trials until sampling stops
%          (defining the distribution).
%        p This is the probability of success for each trial.
%
%OUTPUTS: val The value(s) of the negative binomial CDF.
%
%The negative binomial distribution is discussed in Chapter 4 of [1]. The
%CDF can be expressed in terms of a regularized incomplete beta function.
%
%EXAMPLE:
%We validate the CDF value by comparing it to a value computed from random
%samples.
% p=0.8;
% r=5;
% x=16;
% numSamples=1e5;
% prob=NegativeBinomialD.CDF(x,r,p)
% probSamp=mean(NegativeBinomialD.rand([numSamples,1],r,p)<=x)
%One will find the values ot both be about 0.414.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=1-betainc(p,k+1,r);
end

function vals=rand(N,r,p)
%%RAND Generate negative binomial random variables.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row vector, then rand
%          returns an MXN1 matrix of random variables.
%        r This is the integer number of failed trials until sampling
%          stops (defining the distribution); r>0.
%        p This is the probability of success for each trial.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated negative binomial random variables.
%
%The negative binomial distribution arises from a Poisson distribution
%whose mean is a random variable having a central gamma distribution. This
%relationship is briefly mentioned in [1] and can be easily derived. Thus,
%this function generates gamma random variables and then generates poisson
%random variables.
%
%REFERENCES:
%[1] M. H. Quenouille, "A relation between the logarithmic, Poisson, and
%    negative binomial distributions," Biometrics, vol. 5, no. 2, pp.
%    162-164, Jun. 1949.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(isscalar(N))
        dims=[N, N];
    else
        dims=N;
    end

    lambda=GammaD.rand(dims,r,p/(1-p));

    numEls=numel(lambda);

    vals=zeros(size(lambda));
    for curEl=1:numEls
        vals(curEl)=PoissonD.rand(1,lambda(curEl));
    end
end
end
end


function t = tvec_even2 ( nt )

%*****************************************************************************80
%
%% TVEC_EVEN2 computes an evenly spaced set of angles between 0 and 2*PI.
%
%  Discussion:
%
%    The computation realizes that 0 = 2 * PI.  The values are equally
%    spaced in the circle, do not include 0, and are symmetric about 0.
%
%  Example:
%
%    NT = 4
%
%    T = ( PI/4, 3*PI/4, 5*PI/4, 7*PI/4 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NT, the number of values to compute.
%
%    Output, real TVEC(NT), the evenly spaced angles, in radians.
%
  t(1:nt) = ( 1:2:(2*nt-1) ) * pi / nt;

  return
end


function J = computeCost(X, y, theta)
%COMPUTECOST Compute cost for linear regression
%   J = COMPUTECOST(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) * (X * theta - y)' * (X * theta - y);

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

end


% quantile() - computes the quantiles of the data sample from a distribution X
%
% Description:
%      If F is the cumulative distribution function (CDF) of X,
%      the p-th-quantile Qp of distribution X is the value for which holds
%                        F(x) <  p,  for x < Qp, and
%                        F(x) >= p,  for x >= Qp.
%      for example, for p = 0.5, Qp is the median of X. p must be in [0..1].
%
% Usage:
%   >>  q = quantile( data, pc );
%
% Inputs:
%   data   - vector of observations
%   pc     - the quantiles will be estimated at the values in pc [0..1]
%
% Outputs:
%   q      - pc-th-quantiles of the distribution generating the observation
%
% Authors: Scott Makeig & Luca Finelli, CNL/Salk Institute-SCCN, August 21, 2002
%
% Note: this function overload the function from the statistics toolbox. In
%       case the statistic toolbox is present, the function from the
%       statistics toolbox is being called instead.
%
% See also:
%   pop_sample(), eeglab()

% Copyright (C) Scott Makeig & Luca Finelli, CNL/Salk Institute-SCCN, August 21, 2002
%
% 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 q = quantile(data,varargin);

% detect overloaded method in stat toolbox
curPath = fileparts(which('quantile'));
rmpath(curPath);
path2   = fileparts(which('quantile'));
addpath(curPath);
if ~isempty(path2)
    addpath(path2);
    q = quantile(data,varargin{:});
    return;
else
    pc = varargin{1};
end;

if nargin < 2
	help quantile;
	return;
end;

[prows pcols] = size(pc);
if prows ~= 1 & pcols ~= 1
    error('pc must be a scalar or a vector.');
end
if any(pc > 1) | any(pc < 0)
    error('pc must be between 0 and 1');
end
[i,j] = size(data);
sortdata = sort(data);
if i==1 | j==1 % if data is a vector
    i = max(i,j); j = 1;
    if i == 1,
        fprintf('  quantile() note: input data is a single scalar!\n')
        q = data*ones(length(pc),1); % if data is scalar, return it
        return;
    end
    sortdata = sortdata(:);
end
pt = [0 ((1:i)-0.5)./i 1];
sortdata = [min(data); sortdata; max(data)];
q = interp1(pt,sortdata,pc);


function L=lebesque(x)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Computes the Lebesgue coefficient for a set of nodes on an interval
%
% References:
%
% (1) Jean-Paul Berrut & Lloyd N. Trefethen, "Barycentric Lagrange
%     Interpolation"
%     http://web.comlab.ox.ac.uk/oucl/work/nick.trefethen/berrut.ps.gz
% (2) Walter Gaustschi, "Numerical Analysis, An Introduction" (1997) p. 76+
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Get number of nodes
n=length(x);

% use this finer mesh for interpolating between nodes
N=8*n+1;

x=x(:);

X=repmat(x,1,n);

% Compute the weights
w=1./prod(X-X'+eye(n),2);

% Fine mesh for interpolating
xp=linspace(min(x),max(x),N)';

xdiff=repmat(xp.',n,1)-repmat(x,1,N);

% find all the points where the difference is zero
zerodex=(xdiff==0);

% See eq. 3.1 in Ref (1)
lfun=prod(xdiff,1);

% kill zeros
xdiff(zerodex)=eps;

% Compute lebesgue function
lebfun=sum(abs(diag(w)*repmat(lfun,n,1)./xdiff));
plot(xp,lebfun);
L=max(lebfun);


function D = diffmat(N, varargin)
%DIFFMAT   Spectral differentiation matrix.
%   D = DIFFMAT(N) returns the N x N differentiation matrix associated with the
%   Chebyshev spectral collocation method at second-kind Chebyshev points.
%
%   D = DIFFMAT(N, P) returns the N x N differentiation matrix of order P.
%
%   D = DIFFMAT(N, P, DOM) scales the differentiation matrix D to the domain
%   DOM. DOM should be a 1x2 vector.
%
%   D = DIFFMAT(N, P, DOM, GRID) returns the square differentiation matrix on
%   grid specified by GRID. The specifier GRID can be 'chebkind1' (first-kind
%   Chebyshev grid) or 'chebkind2' (second-kind Chebyshev grid) or 'leg'
%   (Legendre grid).
%
%   D = DIFFMAT(N, P, DOM, GRID, LBC, RBC) returns the square differentiation
%   matrix on grid GRID with the corresponding row(s) replaced by boundary
%   conditions specified by string specifiers LBC and RBC for the left and right
%   boundary respectively. The specifier LBC and RBC can be any of 'dirichlet',
%   'neumann', and 'sum' with 'dirichlet' and 'neumann' indicating Dirichlet and
%   Neumann boundary conditions respectively. The string 'sum' indicates a side
%   condition of definite integral i.e., sum(U), where U is the implied solution
%   to the system formed by D. For a differentiation matrix of order higher than
%   1, if there are multiple boundary conditions at one boundary, the
%   corresponding specifiers need to be grouped in a cell using curly brackets.
%   If there is no boundary condition at a boundary, then it needs to be
%   indicated by either an empty array, i.e. [], or an empty cell, i.e. {}. Note
%   that the number of the boundary conditions given by LBC and RBC must total
%   P, i.e. the order of differentiation, otherwise an error is thrown. Also
%   note that RBC can be omitted if there are only left boundary conditions.
%
%   Example 1: D = DIFFMAT(N, 1, DOM, GRID, [], 'dirichlet') replaces the last
%   row of an N x N differentiation matrix by a Dirichlet boundary condition.
%
%   Example 2: D = DIFFMAT(N, 1, DOM, GRID, 'dirichlet') replaces the first
%   row of an N x N differentiation matrix by a Dirichlet boundary condition.
%
%   Example 3: D = DIFFMAT(N, 2, DOM, GRID, 'dirichlet', 'neumann') replaces
%   the first and last rows of an N x N differentiation matrix by a Dirichlet
%   and a Neumann boundary conditions respectively.
%
%   Example 4: D = DIFFMAT(N, 3, DOM, GRID, 'dirichlet', {'dirichlet' 'neumann'})
%   replaces the first row of an N x N differentiation matrix by a Dirichlet
%   boundary condition and the last two rows by Dirichlet and Neumann boundary
%   conditions.
%
%   D = DIFFMAT(N, 'periodic') returns the N x N first-order Fourier
%   differentiation matrix on the default interval [-1 1]. The tag
%   'periodic' can be replaced by 'trig'.
%
%   D = DIFFMAT(N, P, 'periodic') returns the N x N Fourier differentiation
%   matrix of order P  on the default interval [-1 1].
%
%   D = DIFFMAT(N, P, 'periodic', DOM) scales the Pth-order Fourier
%   differetiation matrix to domain DOM.
%
%   The remaining options concern rectangular spectral differentiation matrices,
%   as introduced in [Driscoll & Hale 2014]. Chebfun uses these to solve ODE
%   boundary value problems in the mode GRID1 = 'chebkind2', GRID2 =
%   'chebkind1'. See also [Xu & Hale 2014].
%
%   D = DIFFMAT([M N]) returns the M x N first-order rectangular differentiation
%   matrix which maps from an N-point Chebyshev grid of the second kind to an
%   M-point Chebyshev grid of the same kind.
%
%   D = DIFFMAT([M N], P) returns an M x N rectangular differentiation matrix of
%   order P which maps from an N-point to an M-point Chebyshev grid, both of
%   second kind.
%
%   D = DIFFMAT([M N], P, DOM) returns the same D but scaled to the domain DOM.
%
%   D = DIFFMAT([M N], P, DOM, GRID) returns an M x N first-order rectangular
%   differentiation matrix which maps from an N-point grid of type GRID to an
%   M-point grid of the same type. The specifier GRID can be 'chebkind1',
%   'chebkind2', or 'leg'.
%
%   D = DIFFMAT([M N], P, DOM, GRID1, GRID2) returns an M x N first-order
%   rectangular differentiation matrix which maps from an N-point grid of type
%   GRID1 to an M-point grid of type GRID2. The specifier GRID1 and GRID2 can be
%   any of 'chebkind1', 'chebkind2', and 'leg'.
%
%   D = DIFFMAT(N, P, DOM, GRID1, GRID2, LBC, RBC) returns a square
%   differentiation matrix which is squared up and deflated by appending
%   boundary conditions specified by string specifiers LBC and RBC for the left
%   and the right boundary respectively.
%
%   Example: D = DIFFMAT([M N], P, DOM, GRID1, GRID2, {}, {'neumann' 'sum'})
%   appends two rows to an M x N rectangular differentiation matrix to square it
%   up. The first appended row corresponds to a Neumann boundary condition at
%   the right endpoint while the second appended row corresponds to a side
%   condition sum(U) = I for a scalar I, where U is the solution to the
%   resulting system.
%
% See also DIFF, CHEBCOLLOC2.DIFFMAT, CUMSUMMAT, DIFFROW, INTMAT, INTROW.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% References for rectangular differentiation matrices:
%
%   Driscoll, T. and Hale, N., Rectangular spectral collocation, submitted 2014.
%
%   Xu, K. and Hale, N., Explicit construction of rectangular differentiation
%   matrices, submitted 2014.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% Parse the inputs:
[m, n, p, dom, bc, nlbc, nrbc, mapFrom, mapTo] = parseInputs(N, varargin{:});

%% Different cases:
if ( strcmpi(mapFrom, mapTo) && ( m == n ) ) % Square case:
    if ( strcmpi(mapFrom, 'chebkind1') )
        D = chebcolloc1.diffmat(n, p);
    elseif ( strcmpi(mapFrom, 'chebkind2') )
        D = chebcolloc2.diffmat(n, p);
    elseif ( strcmpi(mapFrom, 'periodic') )
        D = trigcolloc.diffmat(n, p);
    else
        [x, ignored, v] = legpts(n); %#ok<ASGLU>
        [y, ignored, w] = chebpts(n); %#ok<ASGLU>
        z = legpts(n);
        P1 = barymat(y, x, v);
        P2 = barymat(z, y, w);
        D = chebcolloc2.diffmat(n, p);
        D = P2*D*P1;

        % Flipping trick for symmetry:
        d = diag(rot90(D));
        d = sign(d).*(abs(d) + abs(flipud(d)))/2;
        D(logical(flipud(eye(N)))) = d;
        DRot = rot90(D, 2);
        idxTo = rot90(~triu(ones(N)));
        D(idxTo) = (-1)^p*DRot(idxTo);
        if ( mod(N, 2) == 1 )
            D((N+1)/2,(N+1)/2) = 0;
        end
    end

elseif ( strcmpi(mapTo, 'chebkind1') )

    if ( strcmpi(mapFrom, 'chebkind1') )
        if ( p == 1 )
            D = rectdiff1(m, n);
        else
            D = rectdiff_rec(m, n, p, 1);
        end
    elseif ( strcmpi(mapFrom, 'chebkind2') )
        if ( p == 1 )
            D = rectdiff2(m, n);
        else
            D = rectdiff_rec(m, n, p, 2);
        end
    else
        [x, ignored, v] = legpts(n);  %#ok<ASGLU>
        [y, ignored, w] = chebpts(n);  %#ok<ASGLU>
        z = chebpts(m, 1);
        P1 = barymat(y, x, v);
        P2 = barymat(z, y, w);
        D = chebcolloc2.diffmat(n, p);
        D = P2*D*P1;
    end

elseif ( strcmpi(mapTo, 'chebkind2') )
    [z, ignored, ignored, s] = chebpts(m);  %#ok<ASGLU>
    if ( strcmpi(mapFrom, 'chebkind1') )
        D = chebcolloc1.diffmat(n, p);
        [x, ignored, v, r] = chebpts(n, 1);  %#ok<ASGLU>
        P = barymat(z, x, v, s, r, 1);
        D = P*D;
    elseif ( strcmpi(mapFrom, 'chebkind2') )
        D = chebcolloc2.diffmat(n, p);
        [x, ignored, v, r] = chebpts(n);  %#ok<ASGLU>
        P = barymat(z, x, v, s, r, 1);
        D = P*D;
    else
        [x, ignored, v] = legpts(n);  %#ok<ASGLU>
        [y, ignored, w] = chebpts(n);  %#ok<ASGLU>
        P1 = barymat(y, x, v);
        P2 = barymat(z, y, w);
        D = chebcolloc2.diffmat(n, p);
        D = P2*D*P1;
    end

elseif ( strcmpi(mapTo, 'leg') )
    z = legpts(m);
    if ( strcmpi(mapFrom, 'chebkind1') )
        D = chebcolloc1.diffmat(n, p);
        [x, ignored, v] = chebpts(n, 1);  %#ok<ASGLU>
        P = barymat(z, x, v);
        D = P*D;
    elseif ( strcmpi(mapFrom, 'chebkind2') )
        D = chebcolloc2.diffmat(n, p);
        [x, ignored, v] = chebpts(n);  %#ok<ASGLU>
        P = barymat(z, x, v);
        D = P*D;
    else
        [x, ignored, v] = legpts(n);  %#ok<ASGLU>
        [y, ignored, w] = chebpts(n);  %#ok<ASGLU>
        P1 = barymat(y, x, v);
        P2 = barymat(z, y, w);
        D = chebcolloc2.diffmat(n, p);
        D = P2*D*P1;
    end

end

%% Rescaling:
scl = (2/(dom(end) - dom(1)))^p;
D = scl*D;

%% Boundary conditions:
if ( ~isempty(bc) )
    nbc = nlbc + nrbc;
    BC = zeros(nbc, n);
    for j = 1:nbc
        if ( j <= nlbc )
            z = -1;
            r = pi;
            idx = 1;
        else
            z = 1;
            r = 0;
            idx = n;
        end

        switch bc{j}
            case 'dirichlet'
                if ( strcmpi(mapFrom, 'chebkind1') )
                    [x, ignored, v, t] = chebpts(n, 1);  %#ok<ASGLU>
                    BC(j,:) = barymat(z, x, v, r, t);
                elseif ( strcmpi(mapFrom, 'chebkind2') )
                    I = eye(n);
                    BC(j,:) = I(idx,:);
                else
                    [x, ignored, v] = legpts(n);  %#ok<ASGLU>
                    BC(j,:) = barymat(z, x, v);
                end

            case 'neumann'

                if ( strcmpi(mapFrom, 'chebkind1') )
                    DD = diffmat(n, 1, dom, 'chebkind1');
                    [x, ignored, v, t] = chebpts(n, 1);  %#ok<ASGLU>
                    P = barymat(z, x, v, r, t);
                    DD = P*DD;
                    BC(j,:) = DD;
                elseif ( strcmpi(mapFrom, 'chebkind2') )
                    DD = diffmat(n, 1, dom);
                    BC(j,:) = DD(idx,:);
                else
                    DD = diffmat(n, 1, dom);
                    [x, ignored, v] = legpts(n);  %#ok<ASGLU>
                    y = chebpts(n);
                    P = barymat(y, x, v);
                    DD = DD*P;
                    BC(j,:) = DD(idx, :);
                end

            case 'sum'

                if ( strcmpi(mapFrom, 'chebkind1') )
                    [ignored, w] = chebpts(n, dom, 1);  %#ok<ASGLU>
                elseif ( strcmpi(mapFrom, 'chebkind2') )
                    [ignored, w] = chebpts(n, dom);  %#ok<ASGLU>
                else
                    [ignored, w] = legpts(n, dom);  %#ok<ASGLU>
                end

                BC(j,:) = w;

            otherwise
                error('CHEBFUN:diffmat:wrongBC', ...
                    'Unknown type of boundary conditions.');
        end
    end
end

%% Replace or append the boundary conditions:
if ( ~isempty(bc) && ( m == n ) )
    % Replacement for square case:
    D(1:nlbc, :) = BC(1:nlbc, :);
    D(end-nrbc+1:end,:) = BC(nlbc+1:end,:);
elseif ( ~isempty(bc) )
    D = [BC(1:nlbc,:); D; BC(nlbc+1:end,:)];
end

end

function D = rectdiff1(m, n)
%RECTDIFF1  Explicit constrcution of 1st-order rectangular differentiation
%matrix mapping from 1st-kind grid.

% mapping-from grid (angles):
T = chebtech1.angles(n).';

% difference between dimensions:
c = n-m;

% mapping-to grid (angles):
TAU = chebtech1.angles(m);

% Denominator:
denom = bsxfun(@(u,v) 2*sin((v+u)/2).*sin((v-u)/2), T, TAU);

% Sign:
sgn = ones(m, n);
if ( mod(c, 2) )
    sgn(1:2:end,2:2:end) = -1;
    sgn(2:2:end,1:2:end) = -1;
else
    sgn(1:2:end,1:2:end) = -1;
    sgn(2:2:end,2:2:end) = -1;
end

D = sgn.*((cos(c*TAU)./sin(TAU))*sin(T)-sin(c*TAU)/n*sin(T)./denom)./denom;

% indices for applying negative-sum trick:
[~, idx] = min(abs(denom), [], 2);
idx = sub2ind([m n], 1:m, idx.');
D(idx) = 0;
D(idx) = -sum(D, 2);

if ( c == 1 )
    % Flipping trick:
    ii = logical(rot90(tril(ones(m, n)), 2));
    rot90D = rot90(D,2);
    D(ii) = -rot90D(ii);
end

end

function D = rectdiff2(m, n)
%RECTDIFF2  Explicit constrcution of 1st-order rectangular differentiation
%matrix mapping from a 2nd-kind grid.

nm1 = n - 1;                    % For convenience.
cm1 = nm1 - m;                  % Difference between dimensions:
t = chebpts(n).';               % Second-kind grid.
tau = chebpts(m, 1);            % First-kind grid.
T = chebtech2.angles(n).';          % Second-kind grid (angles).
TAU = chebtech1.angles(m);   % First-kind grid (angles).

% Explicit expression:
denom = 2*bsxfun( @(u,v) sin((v+u)/2) .* sin((v-u)/2), T, TAU );
numer = bsxfun( @times, 1 - tau*t, cos(cm1*TAU)./sin(TAU) );

sgn = (-1)^cm1;

if ( cm1 == 0 )
    D = numer ./ denom.^2 / nm1;
else
    D = repmat(sin(cm1*TAU), 1, n)./denom + numer./denom.^2 / nm1;
    D = sgn*D;
end
D(:,[1,n]) = .5*D(:,[1,n]);     % Scaling for first and last columns.

if ( cm1 == 0 )
    % Flipping trick:
    ii = logical(rot90(tril(ones(m, n)), 2));
    rot90D = rot90(D,2);
    D(ii) = sgn*rot90D(ii);
end

% Sign:
D(1:2:end,1:2:end) = -D(1:2:end,1:2:end);
D(2:2:end,2:2:end) = -D(2:2:end,2:2:end);

% Negative sum trick:
[~, idx] = min(abs(denom), [], 2);
idx = sub2ind([m n], 1:m, idx.');
D(idx) = 0; D(idx) = -sum(D, 2);

if ( cm1 == 0 )
    % Fix corner values:
    D(1) = -.25/(nm1*sin(pi/(2*m))*sin(pi/(4*m))^2); D(end) = -D(1);
    % Negative sum trick for corner entries:
    D(1,2) = -sum(D(1,[1 3:end])); D(end,end-1) = -D(1,2);
end

end

function D = rectdiff_rec(m, n, p, kind)
%Recursive construction for high-order rectangular differentiation matrices

% Sign and scaling:
sgn = ones(1, n);
sgn(1:2:end) = -1;

if ( kind == 1 )
    % mapped-from angles (1st-kind):
    T = chebtech1.angles(n).';

    % Compute the first order diff matrix:
    D = rectdiff1(m, n);

    % Preparation for higher order (p>1):
    a = [zeros(n,1); 1];

    % Signs:
    sgn = (-1)^(n-1)*sgn.*sin(T)/n;

else
    % mapped-from grid (2nd-kind):
    T = chebtech2.angles(n).';

    % Compute the first order diff matrix:
    D = rectdiff2(m, n);

    % Preparation for higher order (p>1):
    a = [zeros(n-2,1); -1; 0; 1];

    % Signs:
    sgn = (-1)^(n-1)*sgn/(2*(n-1));
    sgn([1 n]) = sgn([1 n])/2;

end

% mapped-to grid (1st-kind):
tau = chebpts(m, 1);
TAU = chebtech1.angles(m);

a = computeDerCoeffs(a);

% Denominator:
denom = bsxfun(@(u,v) 2*sin((v+u)/2).*sin((v-u)/2), T, TAU);

% indices for applying negative-sum trick:
[~, idx] = min(abs(denom), [], 2);
idx = sub2ind([m n], 1:m, idx.');

% Recursion for higher-order matrices:
for l = 2:p

    % Compute coefficients of the derivative of T_n:
    a = computeDerCoeffs(a);

    % Evaluating at tau by Clenshaw method:
    Tt = chebtech.clenshaw(tau, a);
    D = (Tt*sgn + l*D)./denom;

end

% negative-sum trick:
D(idx) = 0;
D(idx) = -sum(D, 2);

end

function cout = computeDerCoeffs(c)
%COMPUTEDERCOEFFS   Recurrence relation for coefficients of derivative.
%   C is the matrix of Chebyshev coefficients of a (possibly array-valued)
%   CHEBTECH object.  COUT is the matrix of coefficients for a CHEBTECH object
%   whose columns are the derivatives of those of the original.

    [n, m] = size(c);
    cout = zeros(n-1, m);                       % Initialize vector {c_r}
    w = repmat(2*(1:n-1)', 1, m);
    v = w.*c(2:end,:);                          % Temporal vector
    cout(n-1:-2:1,:) = cumsum(v(n-1:-2:1,:));   % Compute c_{n-2}, c_{n-4},...
    cout(n-2:-2:1,:) = cumsum(v(n-2:-2:1,:));   % Compute c_{n-3}, c_{n-5},...
    cout(1,:) = .5*cout(1,:);                   % Adjust the value for c_0
end

function [m, n, p, dom, bc, nlbc, nrbc, mapFrom, mapTo] = parseInputs(N, varargin)
% Parse the inputs to DIFFMAT.

p = 1;
dom = [-1 1];
mapFrom = [];
mapTo = [];
lbc = {};
nlbc = 0;
rbc = {};
nrbc = 0;
isLbcGiven = 0;
isRbcGiven = 0;

if ( isscalar(N) )
    n = N;
    m = n;
elseif ( N(2) < 0 )
    n = N(1);
    m = n + N(2);
else
    m = N(1);
    n = N(2);
end

for j = 1:numel(varargin)
    v = varargin{j};
    if ( isnumeric(v) )
        if ( isempty(v) )
            if ( ~isLbcGiven )
                lbc = {};
                isLbcGiven = 1;
            elseif ( ~isRbcGiven )
                rbc = {};
                isRbcGiven = 1;
            end
        elseif ( isscalar(v) )
            p = v;
        else
            dom = v;
        end
    elseif ( ischar(v) )
        switch v
            case 'rect'

                if ( strcmpi(mapFrom, 'periodic') )
                    error('CHEBFUN:diffmat:wrongInput', ...
                        ['Rectangular Fourier differentiation matrices are '...
                        'not supported.']);
                end

                if ( isscalar(N) )
                    m = n - p;
                end

            case {'periodic', 'trig'}
                mapFrom = 'periodic';
                mapTo = 'periodic';
                if ( m ~= n )
                    error('CHEBFUN:diffmat:wrongInput', ...
                        ['Rectangular Fourier differentiation matrices are '...
                        'not supported.']);
                end

            case {'chebkind1', 'chebkind2', 'leg'}
                if ( isempty(mapFrom) )
                    mapFrom = v;
                elseif ( isempty(mapTo) )
                    mapTo = v;
                else
                    error('CHEBFUN:diffmat:unknown', ...
                        'Too many inputs for grid type.');
                end

            case {'dirichlet', 'neumann', 'sum', []}
                if ( ~isLbcGiven )
                    lbc = {v};
                    isLbcGiven = 1;
                elseif ( ~isRbcGiven )
                    rbc = {v};
                    isRbcGiven = 1;
                else
                    error('CHEBFUN:diffmat:unknown', ...
                        ['Too many inputs for boundary condition. ' ...
                        'Use curly brackets to group left and right ' ...
                        'boundary conditions, if multiple boundary ' ...
                        'conditions are considered at one boundary.']);
                end
            otherwise
                error('CHEBFUN:diffmat:unknown', ['Unknown input ', v]);
        end

    elseif ( iscell(v) )
        if ( ~isLbcGiven )
            lbc = v;
            isLbcGiven = 1;
        elseif ( ~isRbcGiven )
            rbc = v;
            isRbcGiven = 1;
        else
            error('CHEBFUN:diffmat:unknown', ...
                'Unrecognized boundary condition.');
        end
    else
        error('CHEBFUN:diffmat:unknown', ...
            'Unknown input of type %s.', class(v));
    end
end

% If only one grid is given, then let
if ( ~isempty(mapFrom) && isempty(mapTo) )
    mapTo = mapFrom;
end

if ( isempty(mapFrom) )
    mapFrom = 'chebkind2';
    mapTo = 'chebkind2';
end

if ( p < 0 )
    error('CHEBFUN:diffmat:wrongInput', ...
            'The order of differentiation matrix must be non-negative.');
end

% No breakpoints allowed:
if ( numel(dom) > 2 )
    dom = dom([1 end]);
    warning('CHEBFUN:diffmat:noBreaks', ...
        'DIFFMAT does not support domains with breakpoints.');
end

% Boundary conditions:
bc = [lbc rbc];
if ( ~isempty(bc) )
    if ( isa(mapTo, 'periodic')  )
        error('CHEBFUN:diffmat:wrongBC', ...
            ['For periodic functions, there is no need to specify boundary ' ...
             'conditions.']);
    end
    nlbc = numel(lbc);
    nrbc = numel(rbc);
    nbc = nlbc + nrbc;
    if ( nbc ~= p )
        error('CHEBFUN:diffmat:wrongBC', ...
            ['The number of boundary conditions must match differentiation ' ...
             'order p.']);
    end
end

end


function value = ball_volume_3d ( r )

%*****************************************************************************80
%
%% BALL_VOLUME_3D computes the volume of a ball in 3D.
%
%  Integration region:
%
%    Points (X,Y,Z) such that
%
%      X**2 + Y**2 + Z**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 ball.
%
%    Output, real BALL_VOLUME_3D, the volume of the ball.
%
  value = ( 4.0E+00 / 3.0E+00 ) * pi * r * r * r;

  return
end


function [q,qd,q2d] = fourier_series_traj(t,q0,A,B,w,N)
% -----------------------------------------------------------------------
% The function evaluates trancated Fourier series polynomial
% Inputs:
%   t - time instantes at which the polynomail should be evaluated
%   q0 - initial offset, should be vector (nx1)
%   A - sine coefficients
%   B - cosine coefficients
%   w - fundamental frequency
%   N - number of harmonics
% Outputs:
%   q - positions i.e. value of polynomial
%   qd - velocities i.e. derivative of polynomail
%   q2d - accelerations i.e. second derivative of polynomial
% -----------------------------------------------------------------------
q = q0;
qd = zeros(size(q0));
q2d = zeros(size(q0));
for k = 1:N
   q = q + A(:,k)/(w*k).*sin(w*k*t) - B(:,k)/(w*k).*cos(w*k*t);
   qd = qd + A(:,k).*cos(w*k*t) + B(:,k)*sin(w*k*t);
   q2d = q2d - A(:,k)*w*k.*sin(w*k*t) + B(:,k)*w*k*cos(w*k*t);
end


% interp1 举例
clear; clc;

xi=0:pi/5:2*pi; % 将插值区间分成若干等距小区间
yi=sin(xi); % 插值节点处的函数值

xh=0:pi/50:2*pi; % 需要插值的点

% 分段线性插值
subplot(2,2,1)
yh=interp1(xi,yi,xh); % 根据插值函数求出的近似值
plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5);
title('分段线性插值','FontSize',18)

% 分段零次插值
subplot(2,2,2)
yh=interp1(xi,yi,xh,'nearst'); % 用邻近的值近似
plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5);
title('分段零次插值','FontSize',18)

% 分段三次 Hermite
subplot(2,2,3)
yh=interp1(xi,yi,xh,'pchip');
plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5);
title('分段三次Hermite插值','FontSize',18)

% 分段三次样条插值
subplot(2,2,4)
yh=interp1(xi,yi,xh,'spline');
plot(xi,yi,'+r', xh,yh,'o-','LineWidth',1.5);
title('分段三次样条插值','FontSize',18)


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

%   Copyright 1993-2002 The MathWorks, Inc.  Used with permission.
%   $Revision: 1.4 $  $Date: 2003/11/21 14:38:20 $

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

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

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

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


function points=regularNSimplexCoords(numDim,method)
%%REGULARNSIMPLEXCOORDS Find the coordinates of a regular n-dimensional
%               simplex. That is, a hypertetrahedron in n-dimensions.
%               All sides in the simplex have equal length, the centroid of
%               the simplex is zero, and the distance of all of the points
%               in the simplex from the origin is 1.
%
%INPUTS: numDim The number of dimensions of the simplex. numDim>=1.
%        method The simplex is not unique (it can be rotated). If the
%               method parameter is specified, it selects which method of
%               finding a simplex is used. Possible values are
%               0 (The default if omitted or an empty matrix is passed. Use
%                  the method of [1], which utilizes cosines, is used.
%               1 The method of [1] utilizing square roots instead of
%                 cosines is used.
%
%OUTPUTS: points numDimXnumPoints set of points that form a
%                numDim-simplex. numPoints is always equal to numDim+1.
%
%The two methods given are from Chapter 9 of [1]. The methods do not
%actually provide points that are a unit distance from the origin, though
%they are all equidistant from the origin. Thus, this scales the points to
%be a unit distance form the origin.
%
%REFERENCES:
%[1] A.H. Stroud, Approximate Calculation of Multiple Integrals. Cliffs,
%    NJ: Prentice-Hall, Inc., 1971.
%
%December 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<2||isempty(method))
    method=0;
end

switch(method)
    case 0%The method in [1] utilizing cosines
        points=zeros(numDim,numDim+1);

        r=1:fix(numDim/2);

        for k=0:numDim
            points(2*r-1,k+1)=cos(2*r*k*pi/(numDim+1));
            points(2*r,k+1)=sin(2*r*k*pi/(numDim+1));
            %For an odd number of dimensions
            if(mod(numDim,2)~=0)
                points(numDim,k+1)=(-1)^k/sqrt(2);
            end
        end
        points=points/sqrt(numDim/2);
    case 1%The method in [1] utilizing square roots.
        points=zeros(numDim,numDim+1);
        for k=1:(numDim+1)
            i=1:k;
            points(i,k)=-sqrt((numDim+1)./((numDim-i+2).*(numDim-i+1)));
            points(k,k)=sqrt((numDim+1)*(numDim-k+1)/(numDim-k+2));
            %Components for i>k are zero.
        end
        points=points/sqrt(numDim);
    otherwise
       error('Invalid method specified')
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.


classdef BinomialD
%%BINOMIALD Functions to handle the binomial distribution. The binomial
%           distribution is the distribution of the number of successes in
%           a sequence of n independent trials, each with a probability of
%           success p.
%Implemented methods are: mean, var, PMF, CDF, rand
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(n,p)
%%MEAN Obtain the mean of the binomial distribution for the given number of
%      trials and probability of success.
%
%INPUTS: n The number of trials performed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%
%OUTPUTS: val The mean number of successes for the binomial distribution.
%
%EXAMPLE:
%We verify the computed mean by comparing it to the sample mean.
% p=0.75;
% n=61;
% meanVal=BinomialD.mean(n,p)
% numSamp=1e5;
% sampMeanVal=mean(BinomialD.rand([1,numSamp],n,p))
%One will find both values are about 45.75.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=n*p;
end

function val=var(n,p)
%%VAR Obtain the variance of the binomial distribution for the given number
%     of trials and probability of success.
%
%INPUTS: n The number of trials performed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%
%OUTPUTS: val The variance of the binomial distribution with the given
%             parameters.
%
%EXAMPLE:
%We verify that the computed variance by comparing it to the sample
%variance.
% p=0.75;
% n=61;
% varVal=BinomialD.var(n,p)
% numSamp=1e5;
% sampVarVal=var(BinomialD.rand([1,numSamp],n,p))
%One will find both values are about 11.4375.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=n*p*(1-p);
end

function val=PMF(k,n,p)
%%PMF Evaluate the binomial probability mass function at a given point with
%     a specified number of trials and success probability per trial.
%
%INPUTS: k The nonnegative integer point(s) at which the binomial PMF is to
%          be evaluated (the number of successes in n trials). Note that
%          0<=k<=n.
%        n The number of trials of which k successes are observed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%
%OUTPUT: val The value(s) of the binomial PMF with success probability p.
%
%The binomial PMF provides the probability of k successes from n trials,
%each with a success probability of p.
%
%EXAMPLE:
%Here, we validate the PMF by generating random samples and comparing the
%PMF plot with a histogram of the random samples.
% p=0.75;
% n=61;
% numSamples=1e5;
% figure(1)
% clf
% histogram(BinomialD.rand([numSamples,1],n,p),'Normalization','pdf')
% hold on
% x=0:61;
% vals=BinomialD.PMF(x,n,p);
% stem(x,vals,'linewidth',2)
% h1=xlabel('x');
% h2=ylabel('PDF(x)');
% set(gca,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h1,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h2,'FontSize',14,'FontWeight','bold','FontName','Times')
%One will see that the histogram matches well with the plot.
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    numPoints=length(k);
    val=zeros(size(k));
    for curK=1:numPoints
        if(k(curK)>=0&&k(curK)<=n)
            val(curK)=binomial(n,k(curK))*p^k(curK)*(1-p)^(n-k(curK));
        end
    end
end

function val=CDF(k,n,p)
%%CDF Evaluate the cumulative distribution function (CDF) of the binomial
%     distribution at a desired point.
%
%INPUTS: k The nonnegative integer point(s) at which the binomial CDF is to
%          be evaluated. Note that 0<=k<=n.
%        n The number of trials of which k or fewer successes are observed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%
%OUTPUTS: val The CDF of the binomial distribution evaluated at the desired
%             point(s).
%
%Rather than summing over the values of the PMF, the equivalency between
%the binomial distribution and the regularized incomplete beta function,
%described at [1] is used. Thus, the built-in function betainc can be used
%for efficient evaluation of the CDF with large values.
%
%EXAMPLE:
%We validate the CDF value by comparing it to a value computed from random
%samples.
% p=0.75;
% n=61;
% x=45;
% numSamples=1e5;
% prob=BinomialD.CDF(x,n,p)
% probSamp=mean(BinomialD.rand([numSamples,1],n,p)<=x)
%One will find the values ot both be about 0.460.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Binomial Distribution." From MathWorld--A Wolfram
%    Web Resource. http://mathworld.wolfram.com/BinomialDistribution.html
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=zeros(size(k));
    sel=k>=0&k<=n;

    val(sel)=betainc(1-p,n-k(sel),k(sel)+1);
end

function k=invCDF(probVals,n,p,choice)
%%INVCDF Evaluate the inverse sumulative distribution function (CDF) of the
%        binomial distirbution for given probabilities.
%
%INPUTS: probVals The CDF probability value(s) at which the argument of the
%          binomial CDF is to be determined. Note that 0<=prob<=1.
%        n The number of trials of which k or fewer successes are observed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%   choice An optional parameter indicating what to do when probVals does
%          not exactly equal a CDF value (which will presumably be the case
%          most of the time). Possible values are:
%          0 Return the k that is the closest value.
%          1 (The default if omitted or an empty matrix is passed) return
%            the next lower k if it exists, otherwise return 0.
%          2 Return the next higher k if there is one, otherwise return n.
%
%OUTPUTS: k The set of non-negative integer points that are the inverse CDF
%           values (number of trials) corresponding to the values in
%           probVals.  This has the same dimensions as probVals.
%
%Though one can sum the PMF values until the resulting CDF values exceed
%prob, this can be slow as n gets large and the recursive computation of
%costs can be subject to finite precision limitations. These issues can be
%avoided by expressing the CDF in terms of the regularized incomplete beta
%function, which is given in [1]. The CDF can be evaluated using betainc
%without summing all of the terms. The inverse is found using the binSearch
%function.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Binomial Distribution." From MathWorld--A Wolfram
%    Web Resource. http://mathworld.wolfram.com/BinomialDistribution.html
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

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

   f=@(idx)BinomialD.CDF(idx,n,p);
   k=zeros(size(probVals));
   numPts=numel(probVals);

    for i=1:numPts
        [~,k(i)]=binSearch(f,probVals(i),choice,[0;n]);
    end
end

function vals=rand(N,n,p)
%%RAND Generate binomial random variables with a given number of trials and
%      probability of success.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row  vector, then rand
%          returns an MXN1 matrix of random variables.
%        n The number of trials performed.
%        p The probability of success for the underlying Bernoulli trials.
%          0<=p<=1.
%
%The algorithm used depends on the value of n*min(p,1-p). If
%n*min(p,1-p)>=10, then the binomial, triangle, parallelogram, exponential
%algorithm of [1] is used. If n*min(p,1-p)<10, then a basic inverse
%transformation method, as described in [1] is used. This assures that the
%random number generation is fast for a wide variety of values of n and p.
%
%REFERENCES:
%[1] V. Kachitvichyanukul and B. W. Schmeiser, "Binomial random variate
%    generation," Communications of the ACM, vol. 31, no. 2, pp. 216-222,
%    Feb. 1988.
%
%August 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(isscalar(N))
        dims=[N N];
    else
        dims=N;
    end

    vals=zeros(dims);
    numVals=numel(vals);

    %Do not use the BTPE algorithm if n*min(p,1-p) is small. Rather, the
    %inverse transformation algorithm from Section 2 is used. However, it
    %has been modified replacing p with pMin=min(p,1-p) as described in the
    %text to reduce the execution time.
    if(n*min(p,1-p)<10)
        pMin=min(p,1-p);
        q=1-pMin;
        s=pMin/q;
        a=(n+1)*s;

        for curVal=1:numVals
            u=rand(1);
            r=q^n;
            x=0;
            gotoNextVal=false;

            %With n*pMin<10, the mean of the PMF is below 10 and the
            %standard deviation is below sqrt(10). To assure a limited
            %runtime, we thus cap the maximum value of the iterated x at
            %1000, or about 316 standard deviations from the mean.
            while(x<1000)
                if(u<=r)
                    %This part deals with using pMin instead of p.
                    if(p>1/2)
                        x=n-x;
                    end
                    vals(curVal)=x;
                    gotoNextVal=true;
                    break;
                end
                u=u-r;
                x=x+1;
                r=((a/x)-s)*r;
            end

            if(gotoNextVal)
                continue;
            end

            if(p>1/2)
                x=n-x;
            end
            vals(curVal)=x;
        end
        return;
    end

%If we are here, then the BTPE algorithm should be used. Everything below
%is the BTPE algorithm from Section 3 of [1].

%Step 0: Set up constants as functions of n and p.
    r=min(p,1-p);
    q=1-r;
    fM=n*r+r;
    M=floor(fM);
    p1=floor(2.195*sqrt(n*r*q)-4.6*q)+0.5;
    xM=M+0.5;
    xL=xM-p1;
    xR=xM+p1;
    c=0.134+20.5/(15.3+M);
    a=(fM-xL)/(fM-xL*r);
    lambdaL=a*(1+a/2);
    a=(xR-fM)/(xR*q);
    lambdaR=a*(1+a/2);
    p2=p1*(1+2*c);
    p3=p2+c/lambdaL;
    p4=p3+c/lambdaR;

    for curVal=1:numVals
        gotoNextVal=false;
        while(1)
            if(gotoNextVal)
                break;
            end

    %Step 1: Generate a random variable for selecting the region. If region
    %   1 is selected, generate a triangularly distributed random variable.
            u=rand(1)*p4;
            v=rand(1);
            if(u<p1)%Generate a triangular variate.
                y=floor(xM-p1*v+u);
                if(p>1/2)%Step 6
                    y=n-y;
                end
                vals(curVal)=y;
                gotoNextVal=true;
                continue;
            elseif(u<=p2)%Step 2: Parallelograms.
                x=xL+(u-p1)/c;
                v=v*c+1-abs(M-x+0.5)/p1;
                if(v<=0||v>1)
                    continue;
                end

                y=floor(x);
            elseif(u<=p3)%Step 3: Left exponential tail.
                y=floor(xL+log(v)/lambdaL);
                if (y<0)
                    continue;
                end
                v=v*(u-p2)*lambdaL;
            else%Step 4: Right exponential tail.
                y=floor(xR-log(v)/lambdaR);
                if(y>n)
                    continue;
                end
                v=v*(u-p3)*lambdaR;
            end

    %Step 5: Acceptace/ Rejection Comparison.

            k=abs(y-M);
        %5.0 Test for appropriate method of evaluating f(y)
            if(k<=20||k>=n*r*q/2-1)
                %5.1 Evaluate f(y) via recursive relationship
                s=r/q;
                a=s*(n+1);
                F=1;
                if(M<y)
                    i=M;
                    while(1)
                        i=i+1;
                        F=F*(a/i-s);
                        if(i==y)
                            break;
                        end
                    end
                elseif(M>y)
                    i=y;
                    while(1)
                       i=i+1;
                       F=F/(a/i-s);
                       if(i==M)
                           break;
                       end
                    end
                end

                if(v<=F)
                    if(p>1/2)%Step 6
                        y=n-y;
                    end
                    vals(curVal)=y;
                    gotoNextVal=true;
                    continue;
                else
                    continue;
                end
            else
                %5.2 Test for squeezing. Check the value of ln(v) against
                %upper and lower bounds of ln(f(y))
                rho=(k/(n*r*q))*((k*(k/3+0.625)+(1/6))/(n*r*q)+0.5);
                t=-k^2/(2.0*n*r*q);
                A=log(v);
                if(A<t-rho)
                    if(p>1/2)%Step 6
                        y=n-y;
                    end
                    vals(curVal)=y;
                    gotoNextVal=true;
                    continue;
                elseif(A>t+rho)
                    continue;
                end
            %5.3 Final Acceptance/ Rejection Test
                x1=y+1;
                f1=M+1;
                z=n+1-M;
                w=n-y+1;
                x2=x1^2;
                f2=f1^2;
                z2=z^2;
                w2=w^2;

                temp=xM*log(f1/x1)+(n-M+0.5)*log(z/w) ...
                +(y-M)*log(w*r/(x1*q)) ...
                +(13860-(462-(132-(99 ...
                -140/f2)/f2)/f2)/f2)/f1/166320 ...
                +(13860-(462-(132-(99 ...
                -140/z2)/z2)/z2)/z2)/z/166320 ...
                +(13860-(462-(132-(99 ...
                -140/x2)/x2)/x2)/x2)/x1/166320 ...
                +(13860-(462-(132-(99 ...
                -140/w2)/w2)/w2)/w2)/w/166320;
                if(A<=temp)
                    if(p>1/2)%Step 6
                        y=n-y;
                    end
                    vals(curVal)=y;
                    gotoNextVal=true;
                    continue;
                else
                    continue;
                end
            end
        end
    end
end

end
end

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


function y = construct_harmonic_signal( freq,amp,phase,dc,t )
% y = construct_harmonic_signal( freq,amp,phase,dc,t )
% reconstructs a periodical signal from given harmonics
% Written by Dr. Yoash Levron, April 2013.
%
% The input is the individual harmonics of the signal.
% the function reconstructs the signal y(t).
%
% for example, given the input :
% freq        = [50   100  150   200 ...]
% amp       = [3     0      0        0     ...]
% phase    = [0     0      0        0     ...]
% dc  = 2
% The function will output the signal:
% y = 2 + 3*cos(2*pi*50*t)
%
% Generally, the output signal y is:
% y = dc + amp(1)*cos(2*pi*freq(1)*t + phase(1))
%             +amp(2)*cos(2*pi*freq(2)*t + phase(2)) + ...
%
% This function is designed compatible to
% function 'fourier_series_real'. The two functions are inversible:
% The following code will generate a signal y(t) identical to x(t) :
% [ freq,amp,phase,dc ] = fourier_series_real( t,x );
% y = construct_harmonic_signal( freq,amp,phase,dc,t);
%
% inputs:
% freq - [Hz] frequencies of the fourier series, not including zero.
% amp - amplitudes vector, not including the DC component.
% phase - [rad/sec] . phases, not including the DC component.
% dc - the DC value (average of the signal).
% t - [sec] time vector.
%
% outputs:
% y - output signal. same length as t.

y = dc * t.^0;
for ii = 1:length(freq)
    y = y + amp(ii)*cos(2*pi*freq(ii)*t + phase(ii));
end

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(:);

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


function [V,F]=platonic_solid(n,r)

% function [V,F]=platonic_solid(n,r)
% ------------------------------------------------------------------------
% PLATONIC_SOLID Creates the PATCH data, the vertices (V) and faces (F) for
% a given platonic solid (according to "n" see below) with radius (r)
%
% n=1 -> Tetrahedron
% n=2 -> Cube
% n=3 -> Octahedron
% n=4 -> Icosahedron
% n=5 -> Dodecahedron
%
% %%%Example
% clear all; close all; clc;
%
% r=1;
% figure;fig=gcf; clf(fig); colordef (fig, 'white'); units=get(fig,'units'); set(fig,'units','normalized','outerposition',[0 0 1 1]); set(fig,'units',units); set(fig,'Color',[1 1 1]);
% hold on;
%
% [V,F]=platonic_solid(1,r);
% subplot(2,3,1);
% patch('Faces',F,'Vertices',V,'FaceColor','b','FaceAlpha',0.6,'EdgeColor','k','LineWidth',2); axis equal; grid on; hold on; view(3); axis off;
%
% [V,F]=platonic_solid(2,r);
% subplot(2,3,2);
% patch('Faces',F,'Vertices',V,'FaceColor','b','FaceAlpha',0.6,'EdgeColor','k','LineWidth',2); axis equal; grid on; hold on; view(3); axis off;
%
% [V,F]=platonic_solid(3,r);
% subplot(2,3,3);
% patch('Faces',F,'Vertices',V,'FaceColor','b','FaceAlpha',0.6,'EdgeColor','k','LineWidth',2); axis equal; grid on; hold on; view(3); axis off;
%
% [V,F]=platonic_solid(4,r);
% subplot(2,3,4);
% patch('Faces',F,'Vertices',V,'FaceColor','b','FaceAlpha',0.6,'EdgeColor','k','LineWidth',2); axis equal; grid on; hold on; view(3); axis off;
%
% [V,F]=platonic_solid(5,r);
% subplot(2,3,5);
% patch('Faces',F,'Vertices',V,'FaceColor','b','FaceAlpha',0.6,'EdgeColor','k','LineWidth',2); axis equal; grid on; hold on; view(3); axis off;
%
%
% Kevin Mattheus Moerman
% kevinmoerman@hotmail.com
% 13/11/2009
% ------------------------------------------------------------------------

phi=(1+sqrt(5))/2;

switch n
    case 1 % Tetrahedron
        V1=[-0.5;0.5;0;0;];
        V2=[-sqrt(3)/6;  -sqrt(3)/6; sqrt(3)/3; 0];
        V3=[-0.25.*sqrt(2/3); -0.25.*sqrt(2/3); -0.25.*sqrt(2/3);  0.75.*sqrt(2/3)];
        F= [1 2 3; 1 2 4; 2 3 4; 1 3 4;];

    case 2 % Cube
        V1=[-1;  1; 1; -1; -1;  1; 1; -1;];
        V2=[-1; -1; 1;  1; -1; -1; 1;  1;];
        V3=[-1; -1;-1; -1;  1;  1; 1;  1;];
        F= [1 2 3 4; 1 2 6 5; 2 3 7 6; 3 4 8 7; 4 1 5 8; 5 6 7 8;];

    case 3 % Octahedron
        V1=[-1;  1; 1; -1;  0;   0;];
        V2=[-1; -1; 1;  1;  0;   0;];
        V3=[ 0;   0; 0;  0; -1;  1;];
        F= [1 2 5; 2 3 5; 3 4 5; 4 1 5; 1 2 6; 2 3 6; 3 4 6; 4 1 6;];

    case 4 % Icosahedron
        V1=[0;0;0;0;-1;-1;1;1;-phi;phi;phi;-phi;];
        V2=[-1;-1;1;1;-phi;phi;phi;-phi;0;0;0;0;];
        V3=[-phi;phi;phi;-phi;0;0;0;0;-1;-1;1;1;];
        F= [1 4 9;1 5 9;1 8 5;1 8 10;1 10 4; 12 2 5; 12 2 3; 12 3 6; 12 6 9; 12 9 5; 11 7 10; 11 10 8; 11 8 2; 11 2 3; 11 3 7; 2 5 8; 10 4 7; 3 6 7; 6 7 4; 6 4 9; ];

    case 5 % Dodecahedron
        V1=[1;(1/phi);-phi;phi;-1;0;-phi;1;-1;-1;1;(1/phi);-1;0;0;-(1/phi);phi;-(1/phi);1;0;];
        V2=[1;0;-(1/phi);(1/phi);1;-phi;(1/phi);-1;1;-1;-1;0;-1;-phi;phi;0;-(1/phi);0;1;phi;];
        V3=[[1;phi;0;0;-1;-(1/phi);0;1;1;1;-1;-phi;-1;(1/phi);-(1/phi);phi;0;-phi;-1;(1/phi);]];
        F=[1,2,16,9,20;2,16,10,14,8;16,9,7,3,10;7 9 20 15 5;5,7,3,13,18;3,13,6,14,10;6,13,18,12,11;6,11,17,8,14;11,12,19,4,17;1,2,8,17,4;1,4,19,15,20;12,18,5,15,19];

    otherwise
        warning('False input for n')
end

[THETA,PHI,R]=cart2sph(V1,V2,V3);
R=r.*ones(size(V1(:,1)));
[V1,V2,V3]=sph2cart(THETA,PHI,R);
V=[V1 V2 V3];


function value = circle_annulus_area_2d ( radius1, radius2 )

%*****************************************************************************80
%
%% CIRCLE_ANNULUS_AREA_2D returns the area of a circular annulus in 2D.
%
%  Integration region:
%
%    Points (X,Y) such that
%
%      RADIUS1**2 <= ( X - XC )**2 + ( Y - YC )**2 <= RADIUS2**2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real RADIUS1, RADIUS2, the radii of the circles.
%
%    Output, real CIRCLE_ANNULUS_AREA_2D, the area of the annulus.
%
  value = pi * ( radius1 + radius2 ) * ( radius2 - radius1 );

  return
end


function varargout = cart2sph2(varargin)
%CART2SPH2 Convert cartesian coordinates to spherical coordinates.
%
%   [THETA PHI RHO] = cart2sph2([X Y Z])
%   [THETA PHI RHO] = cart2sph2(X, Y, Z)
%
%   The following convention is used:
%   THETA is the colatitude, in radians, 0 for north pole, +pi for south
%   pole, pi/2 for points with z=0.
%   PHI is the azimuth, in radians, defined as matlab cart2sph: angle from
%   Ox axis, counted counter-clockwise.
%   RHO is the distance of the point to the origin.
%   Discussion on choice for convention can be found at:
%   http://www.physics.oregonstate.edu/bridge/papers/spherical.pdf
%
%   Example:
%   cart2sph2([1 0 0])  returns [pi/2 0 1];
%   cart2sph2([1 1 0])  returns [pi/2 pi/4 sqrt(2)];
%   cart2sph2([0 0 1])  returns [0 0 1];
%
%   See also
%     angles3d, sph2cart2, cart2sph, cart2sph2d
%

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2005-02-18
% Copyright 2005-2022 INRA - TPV URPOI - BIA IMASTE

% parse input angles based on input argument number
if length(varargin) == 1
    xyz = varargin{1};
elseif length(varargin) == 3
    xyz = [varargin{1} varargin{2} varargin{3}];
end

% ensure z coordinate is specified
if size(xyz, 2) == 2
    xyz(:,3) = 1;
end

% convert to spherical coordinates
[p, t, r] = cart2sph(xyz(:,1), xyz(:,2), xyz(:,3));

% format output arguments
if nargout == 1 || nargout == 0
    varargout{1} = [pi/2-t p r];
elseif nargout==2
    varargout{1} = pi/2-t;
    varargout{2} = p;
else
    varargout{1} = pi/2-t;
    varargout{2} = p;
    varargout{3} = r;
end


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

%*****************************************************************************80
%
%% TRIANGLE_PDF evaluates the Triangle PDF.
%
%  Discussion:
%
%    Given points A <= B <= C, the probability is 0 to the left of A,
%    rises linearly to a maximum of 2/(C-A) at B, drops linearly to zero
%    at C, and is zero for all values greater than C.
%
%  Formula:
%
%    PDF(A,B,C;X)
%      = 2 * ( X - A ) / ( B - A ) / ( C - A ) for A <= X <= B
%      = 2 * ( C - X ) / ( C - B ) / ( C - A ) for B <= X <= C.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the PDF.
%
%    Input, real A, B, C, the parameters of the PDF.
%    A <= B <= C and A < C.
%
%    Output, real PDF, the value of the PDF.
%
  if ( x <= a )

    pdf = 0.0;

  elseif ( x <= b )

    if ( a == b )
      pdf = 0.0;
    else
      pdf = 2.0 * ( x - a ) / ( b - a ) / ( c - a );
    end

  elseif ( x <= c )

    if ( b == c )
      pdf = 0.0;
    else
      pdf = 2.0 * ( c - x ) / ( c - b ) / ( c - a );
    end

  else
    pdf = 0.0;
  end

  return
end


function [ x, seed ] = sphere_unit_sample_2d ( seed )

%*****************************************************************************80
%
%% SPHERE_UNIT_SAMPLE_2D picks a random point on the unit sphere (circle) in 2D.
%
%  Discussion:
%
%    The unit sphere in 2D satisfies:
%
%      X * X + Y * Y = 1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real X(2), a random point on the unit circle.
%
%    Output, integer SEED, a seed for the random number generator.
%
  dim_num = 2;

  [ u, seed ] = r8_uniform_01 ( seed );

  x(1) = cos ( 2.0 * pi * u );
  x(2) = sin ( 2.0 * pi * u );

  return
end


%PHASECORRELATE  Detect translational shifts that occur between two images
%
%     pshift = cv.phaseCorrelate(src1, src2)
%     [pshift,response] = cv.phaseCorrelate(src1, src2)
%     [...] = cv.phaseCorrelate(..., 'OptionName',optionValue, ...)
%
% ## Input
% * __src1__ First source floating-point array (single-channel `single` or
%   `double`).
% * __src2__ Second source floating-point array (single-channel `single` or
%   `double`), of same size and type as `src1`.
%
% ## Output
% * __pshift__ detected phase shift (sub-pixel) between the two arrays `[x,y]`
% * __response__ Signal power within the 5x5 centroid around the peak, between
%   0 and 1 (optional).
%
% ## Options
% * __Window__ Floating-point array with windowing coefficients to reduce edge
%   effects (optional). Not set by default.
%
% The function is used to detect translational shifts that occur between two
% images.
%
% The operation takes advantage of the Fourier shift theorem for detecting the
% translational shift in the frequency domain. It can be used for fast image
% registration as well as motion estimation. For more information please see
% [Phase correlation](https://en.wikipedia.org/wiki/Phase_correlation).
%
% Calculates the cross-power spectrum of two supplied source arrays. The
% arrays are padded if needed with cv.getOptimalDFTSize.
%
% The function performs the following equations:
%
% * First it applies a
%   [Hanning window](https://en.wikipedia.org/wiki/Hann_function) to each image
%   to remove possible edge effects. This window is cached until the array
%   size changes to speed up processing time.
%
% * Next it computes the forward DFTs of each source array:
%
%       G_a = F{src1}, G_b = F{src2}
%
%   where `F` is the forward DFT.
%
% * It then computes the cross-power spectrum of each frequency domain array:
%
%       R = G_a * G_b^(*) / |G_a * G_b^(*)|
%
% * Next the cross-correlation is converted back into the time domain via the
%   inverse DFT:
%
%       r = F^(-1){R}
%
% * Finally, it computes the peak location and computes a 5x5 weighted
%   centroid around the peak to achieve sub-pixel accuracy.
%
%       (\Delta{x}, \Delta{y}) = weightedCentroid{argmax_(x,y){r}}
%
% * If non-zero, the response parameter is computed as the sum of the elements
%   of `r` within the 5x5 centroid around the peak location. It is normalized
%   to a maximum of 1 (meaning there is a single peak) and will be smaller
%   when there are multiple peaks.
%
% See also: cv.dft, cv.getOptimalDFTSize, cv.idft, cv.mulSpectrums,
%  cv.createHanningWindow, imregcorr
%


function [ s, t ] = segment_point_coords_2d ( p1, p2, p )

%*****************************************************************************80
%
%% SEGMENT_POINT_COORDS_2D: coordinates of a point on a line segment in 2D.
%
%  Discussion:
%
%    A line segment is the finite portion of a line that lies between
%    two points P1 and P2.
%
%    By the coordinates of a point P with respect to a line segment [P1,P2]
%    we mean numbers S and T such that S gives us the distance from the
%    point P to the nearest point PN on the line (not the line segment!),
%    and T gives us the position of PN relative to P1 and P2.
%
%    If S is zero, then P lies on the line.
%
%    If 0 <= T <= 1, then PN lies on the line segment.
%
%    If both conditions hold, then P lies on the line segment.
%
%    If E is the length of the line segment, then the distance of the
%    point to the line segment is:
%
%      sqrt ( S**2 +  T**2    * E**2 )     if      T <= 0;
%             S                            if 0 <= T <= 1
%      sqrt ( S**2 + (T-1)**2 * E**2 )     if 1 <= T
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(2,1), P2(2,1), the endpoints of the line segment.
%
%    Input, real P(2,1), the point to be considered.
%
%    Output, real S, the distance of P to the nearest point PN
%    on the line through P1 and P2.  (S will always be nonnegative.)
%
%    Output, real T, the relative position of the point PN
%    to the points P1 and P2.
%

%
%  If the line segment is actually a point, then the answer is easy.
%
  if ( p1(1:2,1) == p2(1:2,1) )

    t = 0.0;

  else

    bot = sum ( ( p2(1:2,1) - p1(1:2,1) ).^2 );

    t = ( p(1:2,1)  - p1(1:2,1) )' * ( p2(1:2,1) - p1(1:2,1) ) / bot;

  end

  pn(1:2,1) = p1(1:2,1) + t * ( p2(1:2,1) - p1(1:2,1) );

  s = sqrt ( sum ( ( p(1:2,1) - pn(1:2,1) ).^2 ) );

  return
end


function [ n_data, n, c ] = phi_values ( n_data )

%*****************************************************************************80
%
%% PHI_VALUES returns some values of the PHI function.
%
%  Discussion:
%
%    PHI(N) is the number of integers between 1 and N which are
%    relatively prime to N.  I and J are relatively prime if they
%    have no common factors.  The function PHI(N) is known as
%    "Euler's totient function".
%
%    By convention, 1 and N are relatively prime.
%
%    In Mathematica, the function can be evaluated by:
%
%      EulerPhi[n]
%
%  First values:
%
%     N  PHI(N)
%
%     1    1
%     2    1
%     3    2
%     4    2
%     5    4
%     6    2
%     7    6
%     8    4
%     9    6
%    10    4
%    11   10
%    12    4
%    13   12
%    14    6
%    15    8
%    16    8
%    17   16
%    18    6
%    19   18
%    20    8
%
%  Formula:
%
%    PHI(U*V) = PHI(U) * PHI(V) if U and V are relatively prime.
%
%    PHI(P**K) = P**(K-1) * ( P - 1 ) if P is prime.
%
%    PHI(N) = N * Product ( P divides N ) ( 1 - 1 / P )
%
%    N = Sum ( D divides N ) PHI(D).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input/output, integer N_DATA.  The user sets N_DATA to 0 before the
%    first call.  On each call, the routine increments N_DATA by 1, and
%    returns the corresponding data; when there is no more data, the
%    output value of N_DATA will be 0 again.
%
%    Output, integer N, the argument of the PHI function.
%
%    Output, integer C, the value of the PHI function.
%
  n_max = 20;

  c_vec = [ ...
      1,   1,   2,   2,   4,   2,   6,   4,   6,   4, ...
      8,   8,  16,  20,  16,  40, 148, 200, 200, 648 ];

  n_vec = [ ...
      1,   2,   3,   4,   5,   6,   7,   8,   9,  10, ...
     20,  30,  40,  50,  60, 100, 149, 500, 750, 999 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    n = 0;
    c = 0;
  else
    n = n_vec(n_data);
    c = c_vec(n_data);
  end

  return
end


function a_heap = r8vec_heap_a ( n, a )

%*****************************************************************************80
%
%% R8VEC_HEAP_A reorders an R8VEC into an ascending heap.
%
%  Discussion:
%
%    An ascending heap is an array A with the property that, for every index J,
%    A(J) <= A(2*J) and A(J) <= A(2*J+1), (as long as the indices
%    2*J and 2*J+1 are legal).
%
%  Diagram:
%
%                  A(1)
%                /      \
%            A(2)         A(3)
%          /     \        /  \
%      A(4)       A(5)  A(6) A(7)
%      /  \       /   \
%    A(8) A(9) A(10) A(11)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 April 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Albert Nijenhuis, Herbert Wilf,
%    Combinatorial Algorithms,
%    Academic Press, 1978, second edition,
%    ISBN: 0-12-519260-6.
%
%  Parameters:
%
%    Input, integer N, the size of the input array.
%
%    Input, real A(N), an unsorted array.
%
%    Output, real A_HEAP(N), the values of the array have been
%    reordered into a heap.
%
  a_heap(1:n) = a(1:n);
%
%  Only nodes N/2 down to 1 can be "parent" nodes.
%
  for i = floor ( n/2 ) : -1 : 1
%
%  Copy the value out of the parent node.
%  Position IFREE is now "open".
%
    key = a_heap(i);
    ifree = i;

    while ( 1 )
%
%  Positions 2*IFREE and 2*IFREE + 1 are the descendants of position
%  IFREE.  (One or both may not exist because they exceed N.)
%
      m = 2 * ifree;
%
%  Does the first position exist?
%
      if ( n < m )
        break;
      end
%
%  Does the second position exist?
%
      if ( m + 1 <= n )
%
%  If both positions exist, take the smaller of the two values,
%  and update M if necessary.
%
        if ( a_heap(m+1) < a_heap(m) )
          m = m + 1;
        end

      end
%
%  If the small descendant is smaller than KEY, move it up,
%  and update IFREE, the location of the free position, and
%  consider the descendants of THIS position.
%
      if ( key <= a_heap(m) )
        break;
      end

      a_heap(ifree) = a_heap(m);
      ifree = m;

    end
%
%  Once there is no more shifting to do, KEY moves into the free spot.
%
    a_heap(ifree) = key;

  end

  return
end


function bern = bpab ( n, x, a, b )

%*****************************************************************************80
%
%% BPAB evaluates at X the Bernstein polynomials based in [A,B].
%
%  Formula:
%
%    BERN(N,I)(X) = [N!/(I!*(N-I)!)] * (B-X)^(N-I) * (X-A)^I / (B-A)^N
%
%  First values:
%
%    B(0,0)(X) =   1
%
%    B(1,0)(X) = (      B-X              ) / (B-A)
%    B(1,1)(X) = (                X-A    ) / (B-A)
%
%    B(2,0)(X) = (     (B-X)^2           ) / (B-A)^2
%    B(2,1)(X) = ( 2 * (B-X)   * (X-A)   ) / (B-A)^2
%    B(2,2)(X) = (               (X-A)^2 ) / (B-A)^2
%
%    B(3,0)(X) = (     (B-X)^3           ) / (B-A)^3
%    B(3,1)(X) = ( 3 * (B-X)^2 * (X-A)   ) / (B-A)^3
%    B(3,2)(X) = ( 3 * (B-X)   * (X-A)^2 ) / (B-A)^3
%    B(3,3)(X) = (               (X-A)^3 ) / (B-A)^3
%
%    B(4,0)(X) = (     (B-X)^4           ) / (B-A)^4
%    B(4,1)(X) = ( 4 * (B-X)^3 * (X-A)   ) / (B-A)^4
%    B(4,2)(X) = ( 6 * (B-X)^2 * (X-A)^2 ) / (B-A)^4
%    B(4,3)(X) = ( 4 * (B-X)   * (X-A)^3 ) / (B-A)^4
%    B(4,4)(X) = (               (X-A)^4 ) / (B-A)^4
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the degree of the Bernstein polynomials to be used.
%    For any N, there is a set of N+1 Bernstein polynomials, each of
%    degree N, which form a basis for polynomials on [A,B].
%
%    Input, real X, the point at which the polynomials are to be evaluated.
%
%    Input, real A, B, the endpoints of the interval on which the
%    polynomials are to be based.  A and B should not be equal.
%
%    Output, real BERN(1:N+1), the values of the N+1 Bernstein polynomials at X.
%
  if ( b == a )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BPAB - Fatal error!\n' );
    fprintf ( 1, '  A = B = %f\n', a );
    error ( 'BPAB - Fatal error!' );
  end

  if ( n == 0 )

    bern(1) = 1.0;

  elseif ( 0 < n )

    bern(1) = ( b - x ) / ( b - a );
    bern(2) = ( x - a ) / ( b - a );

    for i = 2 : n
      bern(i+1) = ( x - a ) * bern(i) / ( b - a );
      for j = i-1 : -1 : 1
        bern(j+1) = ( ( b - x ) * bern(j+1) + ( x - a ) * bern(j) ) / ( b - a );
      end
      bern(1) = ( b - x ) * bern(1) / ( b - a );
    end

  end

  return
end


% In this example we consider a 127 dimensional space.
% We choose vectors in this space by removing a row from a 128 x 128 Hadamard matrix.
% We then construct 2 d-dimensional subspaces by choosing vectors from this set
% randomly.
% We then measure the principal angle between such a pair of subspaces.
% We repeat it for t trials of random d-dimensional subspaces.
% We vary d from 1 to 64.
% Finally we plot the variation of principal angle with number of dimensions.
% We note that as the subspace dimension increases, the principal angle between
% two randomly chosen subspaces [with basis vectors from the Hadamard matrix]
% keeps decreasing.

clc; clear all;close all;
% Construct a Hadamard matrix
n = 128;
h = hadamard(n);
% drop one row
h2 = h(1:end-1, :);
% normalize the vectors
h2 = spx.norm.normalize_l2(h2);
% compute it's Gram matrix
g = h2' * h2;
% verify that absolute value of all the non-zero elements is 1/(n -1).

trials = 2;

least_angles = [];
ds = [];

% The size of subspace
for d = 1:n/2
    fprintf('Choosing subspace dimension: %d\n', d);
    for t=1:trials
        % select two independent subspaces
        indices = randperm(n, 2*d);
        A = h2(:, indices(1:d));
        B = h2(:, indices(d+1:end));
        angles = spx.la.spaces.principal_angles_cos(A, B);
        least_angle = angles(1);
        least_angle_deg = rad2deg(acos(least_angle));

        fprintf('Trial: %d, smallest principal angle: %.4f, %.2f degrees\n', t, ...
            least_angle, least_angle_deg);
    end
    ds = [ds d];
    least_angles = [least_angles least_angle_deg];
end
plot(ds, least_angles);
xlabel('D');
ylabel('Angle (degrees)');
grid on;


 function tk = ir_chebyshev_poly(n)
%function tk = ir_chebyshev_poly(n)
%|
%| based on ChebyshevPoly.m by David Terr, Raytheon, 5-10-04
%|
%| Given nonnegative integer n, compute the
%| Chebyshev polynomial T_n. Return the result as a column vector whose mth
%| element is the coefficient of x^(n+1-m).
%| polyval(ir_chebyshev_poly(n), x) evaluates T_n(x).

if nargin < 1, ir_usage, end
if streq(n, 'test'), ir_chebyshev_poly_test, return, end

if n==0
	tk = 1;
elseif n==1
	tk = [1 0]';
else
	tkm2 = zeros(n+1,1);
	tkm2(n+1) = 1;
	tkm1 = zeros(n+1,1);
	tkm1(n) = 1;

	for k=2:n
		tk = zeros(n+1,1);

		for e=n-k+1:2:n
			tk(e) = 2*tkm1(e+1) - tkm2(e);
		end

		if mod(k,2)==0
			tk(n+1) = (-1)^(k/2);
		end

		if k<n
			tkm2 = tkm1;
			tkm1 = tk;
		end
	end
end

% ir_chebyshev_poly_test()
function ir_chebyshev_poly_test
nlist = [0:4];
x = 1 * linspace(-1,1,101)';
y = zeros(numel(x), numel(nlist));
for in=1:numel(nlist);
	n = nlist(in);
	p = ir_chebyshev_poly(n);
	y(:,in) = polyval(p,x);
end
if im
	clf
	plot(x, y)
	axis([-1 1 -1.1 1.1])
	xtick([-1 0 1]), ytick([-1 0 1])
	titlef('Chebychev Polynomials')
end


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

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

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

% ====================== YOUR CODE HERE ======================
% Instructions: You should first compute the covariance matrix. Then, you
%               should use the "svd" function to compute the eigenvectors
%               and eigenvalues of the covariance matrix.
%
% Note: When computing the covariance matrix, remember to divide by m (the
%       number of examples).
%

Sigma = 1.0/m .* X' * X;

[U, S, V] = svd(Sigma);

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

end

github-repos/MATLAB/Borye-machine-learning-coursera-1/machine-learning-coursera-1-033fdc2e6da393eeb1179a09aafe92362021effb/Week 8 Assignments/K-Means Clustering and PCA/mlclass-ex7/pca.m


function cdf = binomial_cdf ( x, a, b )

%*****************************************************************************80
%
%% BINOMIAL_CDF evaluates the Binomial CDF.
%
%  Discussion:
%
%    CDF(X)(A,B) is the probability of at most X successes in A trials,
%    given that the probability of success on a single trial is B.
%
%    A sequence of trials with fixed probability of success on
%    any trial is known as a sequence of Bernoulli trials.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer X, the desired number of successes.
%    0 <= X <= A.
%
%    Input, integer A, the number of trials.
%    1 <= A.
%
%    Input, real B, the probability of success on one trial.
%    0.0D+00 <= B <= 1.0.
%
%    Output, real CDF, the value of the CDF.
%
  if ( x < 0 )

    cdf = 0.0;

  elseif ( a <= x )

    cdf = 1.0;

  elseif ( b == 0.0 )

    cdf = 1.0;

  elseif ( b == 1.0 )

    cdf = 0.0;

  else

    cdf = 0.0;

    for j = 0 : x

      cnk = binomial_coef ( a, j );

      pr = cnk * b^j * ( 1.0 - b )^( a - j );

      cdf = cdf + pr;

    end

  end

  return
end


%  Testing the function  y=Kalman1D(x,q)
%  Note : many test were done for  better performance by choosing
%  the values R and Q in the function Kalman1D(X) to be respectively
%  : Q=1e-2, and R=0.05.
%  For other functions, tery choosing optimal Q and R values .
%  july 2012
%  KHMOU Youssef

fprintf('>>Simulating 1D Kalman Filter: \n\n');
%Global parameters
t=0:pi/100:200;
F=200.00;
n=length(t);

% First test
fprintf('>>1st Signal : f(t)=4*sin(t/10)*exp(-t/200)\n');
x1=(4*sin(t./10)).*exp(-inv(F).*t);
W1=randn(size(x1));
X1=(x1+W1);
Q1=1e-4;
fprintf('>>AWGN1 parameters : m1=%3.f\tv1=%.3f\n',mean(W1),var(W1));
[Y1,K1,P1]=Kalman1D(X1,Q1);
% Statistical parametrs for the first signal
Max_x1= max(x1);
Max_y1= max(Y1);
MSE1 = 0.00 ;
for i=1:n
    MSE1=MSE1+((x1(i)-Y1(i))^2);
end
MSE1=MSE1/n;
PSNR1=20*log10(max(Max_x1,Max_y1)/(MSE1^2));
fprintf('>>Mean Square Error1 mse1=%3.f\n',MSE1);
fprintf('>>Peak Signal to Noise Ratio1 psnr1=%.3f\tdB\n\n',PSNR1);
f1=figure(1);set(f1,'Name','Testing 1: f(t)=4*sin(t/10)*exp(-t/200)+W, W~N(m,v)');
subplot(2,3,1), plot(t,x1,'MarkerSize',1.2), title(' original signal '), grid on ,
subplot(2,3,2), plot(t,X1,'g'), title(' noisy signal  (awgn)'), grid on,
subplot(2,3,3), plot(t,Y1,'r'), title(' Filtered signal,R=1e-2,Q=1e-5'), grid on,
subplot(2,3,4), plot(t,x1,'b--','MarkerSize',2), hold on, plot(t,X1,'g+','MarkerSize',1.2), plot(t,Y1,'r--'),...
    title(' Superposition'), legend(' original','noisy','filtered'), grid on,
subplot(2,3,5), plot(K1(1:100)), title(strcat(' Kalman Gain',' convergence=',num2str(K1(100)))), grid on,xlabel(' iterations')
subplot(2,3,6), plot(P1(1:100)), title(strcat(' variance error',' convergence=',num2str(min(P1)))), grid on,xlabel('iterations')

% Second test
fprintf('>>2nd  Signal : g(t)=0.5*square(pi*t/20);\n');
x2=0.5*square(pi*t/20);
W2=randn(size(x2))/10;
X2=(x2+W2);
Q2=1e-4;
fprintf('>>AWGN2 parameters : m2=%.3f\tv2=%.3f\n',mean(W2),var(W2));
[Y2,K2,P2]=Kalman1D(X2,Q2);
% Statistical parameters for the second signal
Max_x2= max(x2);
Max_y2= max(Y2);
MSE2 = 0.00 ;
for i=1:n
    MSE2=MSE2+((x2(i)-Y2(i))^2);
end
MSE2=MSE2/n;
PSNR2=20*log10(max(Max_x2,Max_y2)/(MSE2^2));
fprintf('>>Mean Square Error2 mse2=%3.f\n',MSE2);
fprintf('>>Peak Signal to Noise Ratio2 psnr2=%.3f\tdB\n',PSNR2);
f2=figure(2);set(f2,'Name','Testing 2: g(t)=1/2 *square(pi*t/20)+W, W~N(m,v)');
subplot(2,3,1), plot(t,x2,'MarkerSize',1.2), title(' original signal, Square(pulsetr) '), grid on ,axis([0 200 -1 1])
subplot(2,3,2), plot(t,X2,'g'),axis([0 200 -1 1]), title(' noisy signal  (awgn)'), grid on,
subplot(2,3,3), plot(t,Y2,'r'), title(' Filtered signal,R=1e-2,Q=1e-5'), grid on,
subplot(2,3,4), plot(t,x2,'b--','MarkerSize',2), hold on, plot(t,X2,'g+','MarkerSize',1.2), plot(t,Y2,'r--'),...
    title(' Superposition'), legend(' original','noisy','filtered'), grid on,
subplot(2,3,5), plot(K2(1:100)), title(strcat(' Kalman Gain',' convergence=',num2str(K2(100)))), grid on,xlabel(' iterations')
subplot(2,3,6), plot(P2(1:100)), title(strcat(' variance error',' convergence=',num2str(min(P2)))), grid on,xlabel('iterations')


function a = c8vec_unity ( n )

%*****************************************************************************80
%
%% C8VEC_UNITY returns the N roots of unity.
%
%  Discussion:
%
%    X(1:N) = exp ( 2 * PI * (0:N-1) / N )
%
%    X(1:N)**N = ( (1,0), (1,0), ..., (1,0) ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of elements of A.
%
%    Output, complex A(N), the N roots of unity.
%

%
%  Yes, I realize that in MATLAB "i" already means sqrt(-1).
%  But to me, "i" means an array index, and nothing else.
%
  imaginary = sqrt ( -1.0 );

  for i = 1 : n
    theta = 2 * pi * ( i - 1 ) / n;
    a(i) = cos ( theta ) + imaginary * sin ( theta );
  end

  return
end


function theta = vector_separation_nd ( dim_num, v1, v2, theta )

%*****************************************************************************80
%
%% VECTOR_SEPARATION_ND finds the angular separation between vectors in ND.
%
%  Discussion:
%
%    Any two vectors lie in a plane, and are separated by a plane angle.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the vectors.
%
%    Input, real V1(DIM_NUM), V2(DIM_NUM), the two vectors.
%
%    Output, real THETA, the angle between the two vectors.
%
  v1_norm = sqrt ( sum ( v1(1:dim_num).^2 ) );

  v2_norm = sqrt ( sum ( v2(1:dim_num).^2 ) );

  cos_theta = ( v1(1:dim_num) * v2(1:dim_num)' ) / ( v1_norm * v2_norm );

  theta = r8_acos ( cos_theta );

  return
end


function [X,Y,Z] = cov3elli(x,P,ns,NP)

% COV3ELLI  3D ellipsoid from Gaussian mean and covariance.
%   [X,Y,Z] = COV3ELLI(x0,P,ns,NP) gives X, Y and Z coordinates of the
%   points corresponding to the 2 biggest semi-diametres of the ellipsoid
%   defined by the covariances matrix P and centered at x0:
%
%        (x-x0)'*(P^-1)*(x-x0) = ns^2.
%
%   The ellipsoid can be plotted in a 3D graphic by just creating a line
%   with line(X,Y,Z).
%
%   See also COV2ELLI, IDP3ELLI, LINE.

%   Copyright 2008-2009 Joan Sola @ LAAS-CNRS.

persistent spheroid

% Basic shape: 2 circles at 90 degrees, with the pole at the major axis X.
if isempty(spheroid)
    alpha = 2*pi/NP*(0:NP);
    spheroid = [...
        cos(alpha)    cos(alpha)
        sin(alpha)    zeros(1,NP+1)
        zeros(1,NP+1) sin(alpha)];
end

% Rotation R and semi-diameters d, obtained from P by SVD
[R,D] = svd(P);  % rotation matrix R
d     = sqrt(D); % semi-axes

% spheroid -> aligned ellipsoid -> rotated ellipsoid -> ns-ellipsoid
ellip = ns*R*d*spheroid;

% Choleski is not good here: ellipsoid cross not aligned w/ axis
% C = chol(P)';
% ellip = ns*C*spheroid;

% output ready for plotting (X, Y and Z line vectors), offset by x
X = x(1)+ellip(1,:);
Y = x(2)+ellip(2,:);
Z = x(3)+ellip(3,:);

% ========== End of function - Start GPL license ==========

%   # START GPL LICENSE

%---------------------------------------------------------------------
%
%   This file is part of SLAMTB, a SLAM toolbox for Matlab.
%
%   SLAMTB is free software: you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation, either version 3 of the License, or
%   (at your option) any later version.
%
%   SLAMTB 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 SLAMTB.  If not, see <http://www.gnu.org/licenses/>.
%
%---------------------------------------------------------------------

%   SLAMTB is Copyright:
%   Copyright (c) 2008-2010, Joan Sola @ LAAS-CNRS,
%   Copyright (c) 2010-2013, Joan Sola,
%   Copyright (c) 2014-2015, Joan Sola @ IRI-UPC-CSIC,
%   SLAMTB is Copyright 2009
%   by Joan Sola, Teresa Vidal-Calleja, David Marquez and Jean Marie Codol
%   @ LAAS-CNRS.
%   See on top of this file for its particular copyright.

%   # END GPL LICENSE


function J = computeCost(X, y, theta)
%COMPUTECOST Compute cost for linear regression
%   J = COMPUTECOST(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.

## for i = 1:m,
##   J = J + ((X(i, :) * theta) - y(i)) ^ 2;
## end;

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

J = 1 / (2 * m) * J;

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

end


function [ x, w ] = ncoh_rule ( n )

%*****************************************************************************80
%
%% NCOH_RULE: Newton Cotes Open Half quadrature rule.
%
%  Discussion:
%
%    Newton Cotes Open Half rule on [-1,+1];
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 February 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the rule.
%
%    Output, real X(N), W(N), the points and weights.
%
  x = ( 1 : 2 : 2*n-1 )';
  x = x / ( 2 * n );
%
%  Linear transformation from [0,1] to [-1,+1].
%
  x = 2.0 * x - 1.0;
%
%  Compute the weights.
%
  x_min = -1.0;
  x_max = 1.0;

  w = nc_compute ( n, x_min, x_max, x );

  return
end


function [mu sigma2] = estimateGaussian(X)
%ESTIMATEGAUSSIAN This function estimates the parameters of a
%Gaussian distribution using the data in X
%   [mu sigma2] = estimateGaussian(X),
%   The input X is the dataset with each n-dimensional data point in one row
%   The output is an n-dimensional vector mu, the mean of the data set
%   and the variances sigma^2, an n x 1 vector
%

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

% You should return these values correctly
mu = zeros(n, 1);
sigma2 = zeros(n, 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the mean of the data and the variances
%               In particular, mu(i) should contain the mean of
%               the data for the i-th feature and sigma2(i)
%               should contain variance of the i-th feature.
%

mu = (1 / m) * sum(X);
sigma2 = (1 / m) * sum((X - mu) .^ 2);

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

end