function fx = p31_fun ( n, x )

%*****************************************************************************80
%
%% P31_FUN evaluates the integrand for problem 31.
%
%  Discussion:
%
%    A simple Newton-Cotes quadrature rule, in which the order of the
%    rule is increased, but the interval is not subdivided, diverges
%    for this integrand.
%
%    This is Runge's function, a standard example of the perils of
%    using high order polynomial interpolation at equally spaced nodes.
%    Since this is exactly what is really going on in a Newton Cotes
%    rule, it is little wonder that the result is so poor.
%
%  Interval:
%
%    -4 <= x <= 4
%
%  Integrand:
%
%    1 / ( 1 + x^2 )
%
%  Antiderivative:
%
%    arctan ( x )
%
%  Exact Integral:
%
%    2 * arctan ( 4 )
%
%  Approximate Integral (20 digits):
%
%    2.6516353273360649301...
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Kendall Atkinson,
%    An Introduction to Numerical Analysis,
%    Prentice Hall, 1984, page 266.
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N), the evaluation points.
%
%    Output, real FX(N), the integrand values.
%
  fx = 1.0 ./ ( 1.0 + x.^2 );

  return
end


function cfl = fd1d_heat_implicit_cfl ( k, t_num, t_min, t_max, x_num, ...
  x_min, x_max )

%*****************************************************************************80
%
%% FD1D_HEAT_IMPLICIT_CFL: compute the Courant-Friedrichs-Loewy coefficient.
%
%  Discussion:
%
%    The equation to be solved has the form:
%
%      dUdT - k * d2UdX2 = F(X,T)
%
%    over the interval [X_MIN,X_MAX] with boundary conditions
%
%      U(X_MIN,T) = U_X_MIN(T),
%      U(X_MIN,T) = U_X_MAX(T),
%
%    over the time interval [T_MIN,T_MAX] with initial conditions
%
%      U(X,T_MIN) = U_T_MIN(X)
%
%    The code uses the finite difference method to approximate the
%    second derivative in space, and an explicit forward Euler approximation
%    to the first derivative in time.
%
%    The finite difference form can be written as
%
%      U(X,T+dt) - U(X,T)                  ( U(X-dx,T) - 2 U(X,T) + U(X+dx,T) )
%      ------------------  = F(X,T) + k *  ------------------------------------
%               dt                                   dx * dx
%
%    or, assuming we have solved for all values of U at time T, we have
%
%      U(X,T+dt) = U(X,T) + cfl * ( U(X-dx,T) - 2 U(X,T) + U(X+dx,T) ) + dt * F(X,T)
%
%    Here "cfl" is the Courant-Friedrichs-Loewy coefficient:
%
%      cfl = k * dt / dx / dx
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 January 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    George Lindfield, John Penny,
%    Numerical Methods Using MATLAB,
%    Second Edition,
%    Prentice Hall, 1999,
%    ISBN: 0-13-012641-1,
%    LC: QA297.P45.
%
%  Parameters:
%
%    Input, real K, the heat conductivity coefficient.
%
%    Input, integer T_NUM, the number of time values, including the initial
%    value.
%
%    Input, real T_MIN, T_MAX, the minimum and maximum times.
%
%    Input, integer X_NUM, the number of nodes.
%
%    Input, real X_MIN, X_MAX, the minimum and maximum spatial coordinates.
%
%    Output, real CFL, the Courant-Friedrichs-Loewy coefficient.
%
  x_step = ( x_max - x_min ) / ( x_num - 1 );
  t_step = ( t_max - t_min ) / ( t_num - 1 );
%
%  Check the CFL condition, print out its value, and quit if it is too large.
%
  cfl = k * t_step / x_step / x_step;

  if ( 0.5 <= cfl )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FD1D_HEAT_EXPLICIT_CFL - Fatal error!\n' );
    fprintf ( 1, '  CFL condition failed.\n' );
    fprintf ( 1, '  0.5 <= K * dT / dX / dX = %f\n', cfl );
    error ( 'FD1D_HEAT_EXPLICIT_CFL - Fatal error!' );
  end

  return
end


function [valuesSelected,costVal]=knapsack01DP(v,w,W)
%%KNAPSACK01DP Solve the 0-1 knapsack problem using dynamic programming.
%        The 0-1 knapsack problem is to find a subset sel of the items in v
%        that solves the optimization problem
%        max_{sel} sum(v(sel))
%        such that sum(w(sel))<=W
%        This can be thought of as fitting the most things in a knapsack if
%        the v's are all 1's, the w's are the sizes of things and W is the
%        capacity of the knapsack.
%
%INPUTS: v An nX1 or 1Xn vector of positive real values to maximize.
%        w An nX1 or 1Xn vector of positive integer capacities required for
%          each value.
%        W The positive integer maximum allowable capacity that can be
%          filled.
%
%OUTPUTS: valuesSelected The indices of the items in v (and w) that are
%                  selected. If the problem is infeasible, then an empty
%                  matrix is returned.
%          costVal The sum of the selected items in v. 0 is returned if the
%                  problem is infeasible.
%
%The knapsack problem is NP-hard. The complexity of this algorithm
%scaled with W. It is O(n*W) The algorithm is sovled via dynamic
%programming. A development of the recursion in such a dynamic programming
%approach is given in Chapter 5.4 of [1]. However, this is a very common
%method for solving this problem and thus solutions can be found in a
%number of basic textbooks on algorithms.
%
%EXAMPLE:
% W=7;
% v=[2.1;3.125;66;4.3;6.2];
% w=[1;2;3;4;5];
% [valuesSelected,costVal]=knapsack01DP(v,w,W)
%One will get vales 3, 2, and 1 selected.
%
%REFERENCES:
%[1] L. A. Wolsey, Integer Programming. New York: Wiley-Interscience, 1998.
%
%January 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

n=length(v);

V=zeros(n+1,W+1);
V(0+1,:)=0;
keep=zeros(n,W+1);

for i=1:n
    for wIdx=0:W
        if(wIdx-w(i)>=0)
            VTest=V(i-1+1,wIdx-w(i)+1);
        else
            VTest=-Inf;
        end

        if((w(i)<=wIdx)&&(v(i)+VTest)>V(i-1+1,wIdx+1))
            V(i+1,wIdx+1)=v(i)+VTest;
            keep(i,wIdx+1)=1;
        else
            V(i+1,wIdx+1)=V(i-1+1,wIdx+1);
            keep(i,wIdx+1)=0;
        end
    end
end

K=W;

valuesSelected=zeros(n,1);
numSelected=0;

for i=n:-1:1
    if(keep(i,K+1)==1)
        numSelected=numSelected+1;
        valuesSelected(numSelected)=i;
        K=K-w(i);
    end
end

valuesSelected=valuesSelected(1:numSelected);

costVal=V(n+1,W+1);
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 bern = bernstein_poly_ab ( n, a, b, x )

%*****************************************************************************80
%
%% BERNSTEIN_POLY_AB 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:
%
%    11 July 2011
%
%  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 A, B, the endpoints of the interval on which the
%    polynomials are to be based.  A and B should not be equal.
%
%    Input, real X, the point at which the polynomials are to be evaluated.
%
%    Output, real BERN(N+1,1), the values of the N+1 Bernstein polynomials at X.
%
  if ( b == a )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'BERNSTEIN_POLY_AB - Fatal error!\n' );
    fprintf ( 1, '  A = B = %f\n', a );
    error ( 'BERNSTEIN_POLY_AB - Fatal error!' );
  end

  bern = zeros ( n + 1, 1 );

  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


function dy = ode_system(t, y, m, b, k)

%*****************************************************************************80
%
%% ODE_SYSTEM evaluates the right hand side of the ODE.
%
%  Discussion:
%
%    The second order ODE:
%
%      m * x'' + b * x' + k * x = 0
%
%    is transformed into a pair of first order ODE's
%    using the variables:
%
%
%      y(1) = x,
%      y(2) = x'
%
%    so that
%
%      y'(1) = y(2)
%      y'(2) = - ( k / m ) y(1) - ( b / m ) y(2)
%
%  Modified:
%
%    01 March 2010
%
%  Parameters:
%
%    Input, real T, the current time.
%
%    Input, real Y(2), the current solution.
%
%    Input, real M, B, K, the mass, damping and stiffness constants.
%
%    Output, real DY(2,1), the right hand sides of the ODE's,
%    returned as a column vector.
%
  dy(1,1) = y(2);
  dy(2,1) = - ( k / m ) * y(1) - ( b / m ) * y(2);

  return
end


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

% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));

% ====================== YOUR CODE HERE ======================
% Instructions: First, for each feature dimension, compute the mean
%               of the feature and subtract it from the dataset,
%               storing the mean value in mu. Next, compute the
%               standard deviation of each feature and divide
%               each feature by it's standard deviation, storing
%               the standard deviation in sigma.
%
%               Note that X is a matrix where each column is a
%               feature and each row is an example. You need
%               to perform the normalization separately for
%               each feature.
%
% Hint: You might find the 'mean' and 'std' functions useful.
%

N = size(X,2);                  % number of features

for i=1:N,
    feature = X(:,i);           % get feature
    mu(i) = mean(feature);      % mean
    sigma(i) = std(feature);    % standard deviation

    % normalize
    X_norm(:,i) = (feature - mu(i)) / sigma(i);
end

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

end


classdef WeibullD
%%WEIBULLD Functions to handle the Weibull distribution.
%Implemented methods are: mean, var, PDF, CDF, invCDF, rand, entropy
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(lambda,k)
%%MEAN Obtain the mean of the Weibull distribution for given scale and
%      shape parameters.
%
%INPUTS: lambda The scale parameter of the distribution. lambda>0.
%             k The shape parameter of the distribution. k>0.
%
%OUTPUTS:val The mean of the Weibull distribution.
%
%The mean of the Weibull distribution is given on the inside of the front
%cover of [1].
%
%EXAMPLE:
%We verify the computed mean by comparing it to the sample mean.
% lambda=2.2;
% k=3.1;
% meanVal=WeibullD.mean(lambda,k)
% numSamp=1e6;
% sampMeanVal=mean(WeibullD.rand([numSamp,1],lambda,k))
%One will find both values are about 1.967
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

   val=lambda*gamma(1+1/k);
end

function val=var(lambda,k)
%%VAR Obtain the variance of the Weibull distribution for given scale and
%     shape parameters/
%
%INPUTS: lambda The scale parameter of the distribution. lambda>0.
%             k The shape parameter of the distribution. k>0.
%
%OUTPUTS:val The variance of the Weibull distribution.
%
%The variance of the Weibull distribution is given on the inside of the front
%cover of [1].
%
%EXAMPLE:
%We verify the computed variance by comparing it to the sample variance.
% lambda=2.2;
% k=3.1;
% varVal=WeibullD.var(lambda,k)
% numSamp=1e6;
% sampVarVal=var(WeibullD.rand([numSamp,1],lambda,k))
%One will find both values are about 0.4821
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

   val=lambda^2*(gamma(1+2/k)-(gamma(1+1/k))^2);
end

function val=PDF(x,lambda,k)
%%PDF Evaluate the probability density function (PDF) of the Weibull
%     distribution at one or more points.
%
%INPUTS: x The point(s) at which the Weibull PDF is to be evaluated. x>=0
%          for nonzero PDF values.
%   lambda The scale parameter of the distribution. lambda>0.
%        k The shape parameter of the distribution. k>0.
%
%OUTPUTS: val The value(s) of the Weibull PDF.
%
%The PDF of the Weibull distribution is given on the inside of the front
%cover of [1].
%
%EXAMPLE:
%Here, we validate the PDF by generating random samples and comparing the
%PDF plot with a histogram of the random samples.
% lambda=2.2;
% k=3.1;
% numSamples=1e5;
% figure(1)
% clf
% histogram(WeibullD.rand([numSamples,1],lambda,k),'Normalization','pdf')
% hold on
% numPoints=1000;
% x=linspace(0,6,numPoints);
% vals=WeibullD.PDF(x,lambda,k);
% plot(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.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=(k/lambda)*(x/lambda).^(k-1).*exp(-(x/lambda).^k);
    val(x<0)=0;
end

function val=CDF(x,lambda,k)
%%CDF Evaluate the cumulative distribution function (CDF) of the Weibull
%     distribution at one or more desired points.
%
%INPUTS: x The point(s) at which the Weibull CDF is to be evaluated.
%   lambda The scale parameter of the distribution. lambda>0.
%        k The shape parameter of the distribution. k>0.
%
%OUTPUTS: val The value(s) of the Weibull CDF.
%
%The CDF is the integral from 0 to x of the PDF. The Weibull PDF is
%fairely simple and the integral is not hard. The Weibull PDF is given on
%the inside of the front cover of [1].
%
%EXAMPLE:
%We validate the CDF value by comparing it to a value computed from random
%samples.
% lambda=2.2;
% k=3.1;
% x=2;
% numSamples=1e5;
% prob=WeibullD.CDF(x,lambda,k)
% probSamp=mean(WeibullD.rand([numSamples,1],lambda,k)<=x)
%One will see that both values are about 0.5249.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=1-exp(-(x/lambda).^k);
    val(x<0)=0;
end

function val=invCDF(prob,lambda,k)
%%INVCDF Evaluate the inverse of the cumulative distribution function (CDF)
%        of the Weibull distribution.
%
%INPUTS: prob The probability or probabilities (0<=prob<=1) at which the
%             argument of the CDF is desired.
%      lambda The scale parameter of the distribution. lambda>0.
%           k The shape parameter of the distribution. k>0.
%
%OUTPUTS: val The argument(s) of the CDF that would give the probability or
%             probabilities in prob.
%
%The CDF of the Weibull distribution can be easily algebraicly inverted,
%which is what is done here. The Weibull CDF is the integral from 0 to x of
%the Weibull PDF, which is given on the inside of the front cover of [1].
%
%EXAMPLE:
%Here, we validate the inverse CDF by showing it to be the inverse of the
%CDF.
% lambda=2.2;
% k=3.1;
% x=2;
% xBack=WeibullD.invCDF(WeibullD.CDF(x,lambda,k),lambda,k)
%One will see that xBack is the same as x.
%
%REFERENCES:
%[1] A. Papoulis and S. U. Pillai, Probability, Random Variables and
%    Stochastic Processes, 4th ed. Boston: McGraw Hill, 2002.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

val=lambda*(-log(1-prob)).^(1/k);

end

function vals=rand(N,lambda,k,lowerBound)
%%RAND Generate Weibull distributed random variables with the given
%      parameters. This function can also be used to generate random
%      variable from a Weibull distribution that is clipped so that only
%      values above a certain threshold are generated. That can be useful
%      when performing simulations and generating false alarms that are all
%      above a given threshold.
%
%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.
%   lambda The scale parameter of the distribution. lambda>0.
%        k The shape parameter of the distribution. k>0.
% lowerBound An optional parameter specifying a lower bound below which
%          none of the randomly generated values should go. If this is
%          omitted or an empty matrix is passed, then lowerBound=0 and a
%          non-clipped Weibull distribution is used.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated Weibull random variables.
%
%This is an implementation of the inverse transform algorithm of Chapter
%5.1 of [1]. To clip values to only being above lowerBound, the CDF value
%of the lower bound is determined and the uniform random variables as used
%in the inverse transform algorithm are all only generated above the
%threshold.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, Ed. 4, Amsterdam: Elsevier, 2006.
%
%October 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.

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

    if(nargin<4||isempty(lowerBound)||lowerBound<=0)
        %If we are evaluating a standard Weibull-distributed random
        %variable rather than one that has been clipped to a particular
        %region.
        U=rand(dims);
        vals=WeibullD.invCDF(U,lambda,k);
    else
        %Only generate Weibull random variables that are >=lowerBound.
        p=WeibullD.CDF(lowerBound,lambda,k);
        %Generate a uniform random variable between p and 1.
        U=p+(1-p)*rand(dims);
        vals=WeibullD.invCDF(U,lambda,k);
    end
end

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

    gammaVal=-psi(1);
    entropyVal=gammaVal*(1-1/k)+log(lambda/k)+1;
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 [nodes,weights]=gaussquadrule(n,class,alpha,beta)
% gaussquadrule: generate a gauss quadrature rule using associated orthogonal polynomials
% usage: [nodes,weights]=gaussquadrule(n,class,alpha,beta)
%
% arguments:
%        n - number of nodes in the guassian quadrature
%
%    class - (optional) - class of gaussian quadrature rule
%            any one of { 'Legendre' 'Laguerre' 'Hermite',
%            'Jacobi', '1Cheby', '2Cheby' }. '1cheby' refers
%            of course to a first kind Gauss-Chebychev rule.
%
%            Capitalization is ignored and class names
%            may be shortened as long as they are left
%            unambiguous. These are all minimally valid:
%            {'le', 'la', 'h' 'j' '1' '2'}
%
%            DEFAULT == 'Legendre'
%
%            The nominal integration intervals are:
%
%              'Legendre' --> [  -1,  1]
%              'Laguerre' --> [   0,inf]
%              'Hermite'  --> [-inf,inf]
%              'Jacobi'   --> [  -1,  1]
%              '1Cheby'   --> [  -1,  1]
%              '2Cheby'   --> [  -1,  1]
%
%            See Abramowitz & Stegun for in-depth information
%
% alpha, beta - (optional) parameters for the rules
%            DEFAULT == 0 for both
%
%            alpha and beta are ignored for the 'legendre',
%            'hermite', 'cheby1' and 'cheby2' rules. Only
%            alpha is used for the Laguerre quadrature rules.
%
% arguments (output)
%    nodes - x values for integration
%  weights - integration weights

% default parameters
if (nargin<2) || isempty(class)
  class='legendre';
end

class=lower(class);
valc={'legendre' 'laguerre' 'hermite' 'jacobi' 'cheby1' ...
      'cheby2' '1chebychev' '2chebychev'};
ind=strmatch(class,valc);
if isempty(ind)
  error 'Invalid quadrature class'
elseif length(ind)>1
  error 'Ambiguous quadrature class'
else
  class=valc{ind};
end

if (nargin<4) || isempty(beta)
  beta=0;
end
if (nargin<3) || isempty(alpha);
  alpha=0;
end

% generate the appropriate orthogonal sympolys.
% use the sympoly objects for this. orthpoly
% creates them.
pn = orthpoly(n,class,alpha,beta);
pnp1 = orthpoly(n+1,class,alpha,beta);

nodes=roots(pn);
nodes=sort(nodes');

pnprime=diff(pn);
weights=zeros(1,n);
for i=1:n
  weights(i)=-(pnp1.Coefficient(end))/(pn.Coefficient(end))./ ...
    double(subs(pnp1,'x',nodes(i)))./ ...
    double(subs(pnprime,'x',nodes(i)));
end

% norm
switch class
  case 'legendre'
    weights=weights*(2/(2*n+1));
  case 'hermite'
    weights=sqrt(pi)*(2^n)*(gamma(n+1))*weights;
  case 'laguerre'
    weights=weights*gamma(n+alpha+1)/gamma(n+1);
  case 'jacobi'
    weights=weights*(2/sum(weights));
    nodes=(nodes+1)/2;
  case {'cheby1' '1chebychev'}
    weights=weights*(2/sum(weights));
  case {'cheby2' '2chebychev'}
    weights=weights*(2/sum(weights));
end


function [df d_arr] = richardson_based_derivative(eq, x0, n, h)
% July 1, 2013 by Ehsan Behnam.
% [df d_arr] = richardson_based_derivative(...)
% computes the derative of the equation "eq" % at "x0"
% using "n" iterations of Richardson extrapolation.
% "h" specifies the initial differential increment/decrement around x0
% (i.e. f(x+h) or f(x-h)).
% A couple of notes:
% 1) "eq" can be any string in the form of f(x). Note that it should be
% computable in Matlab so for example, use eq = 'exp(x)' instead of 'e^x'.
% 2) No matter of what is "h" at each step h <- h/2. Therefore if you want
% to compare the accuracy of this method to other methods (e.g. Tyler's
% series), you need to adjust the number of required steps properly.

% The first output "df" is the d(eq(x))/dx |@(x = x0). Regarding the
% educational purposes for producing the whole table, the function also
% outputs the whole array iteratively generated as the function progresses.

% Basic usage example:
% eq = 'x^3*exp(-x)';
% df = richardson_based_derivative(eq, 0.1, 10);
% Finding the difference between "df" and the Matlab output ...
% disp(subs(diff(sym(eq)), 0.1) - df);
% It will show "-4.6263e-07" on the workspace.

if (nargin < 2 || nargin > 4)
    help('richardson_based_derivative');
    df = '';
    d_arr = '';
    return;
end

if (nargin == 2)
    h = 1/2;
    n = 5;
end

if (nargin == 3)
    h = 1/2;
end

fx = sym(eq);

%Initialization:
d_arr = zeros(n);
for i = 1:n
    d_arr(i, 1) = subs(fx, 'x', x0 + h) - subs(fx, 'x', x0 - h);
    d_arr(i, 1) = d_arr(i, 1) / (2 * h);
    % Iteratively computing the coefficients:
    for j = 2:i
        d_arr(i, j) = d_arr(i, j - 1) + (d_arr(i, j - 1) - ...
                      d_arr(i - 1, j - 1)) / (4 ^j -1);
    end
    % next iteration "h":
    h = h/2;
end
df = d_arr(end, end);


function kSum=KroneckerSum(A,B)
%KRONECKERSUM Find the Kronecker sum of an nXn matrix A and an mXm matrix
%             B. This is defined as kron(A,eye(m))+kron(eye(n),B)
%
%INPUTS: A An nXn matrix.
%        B An mXm matrix.
%
%OUTPUTS: kSum The (n*m)X(n*m) Kronecker sum of A and B.
%
%The Kronecker sum arises in numerous matrix identities. For example, it is
%used  in [1] for expressions for eigenvectors.
%
%REFERENCES:
%[1] J. W. Brewer, "Kronecker products and matrix calculus in systems
%    theory," IEEE Transactions on Circuits and Systems, vol. CAS-25, no.
%    9, pp. 772-781, Sep. 1978.
%
%December 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

n=size(A,1);
m=size(B,1);

kSum=kron(A,eye(m))+kron(eye(n),B);

end

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


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

% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));

% ====================== YOUR CODE HERE ======================
% Instructions: First, for each feature dimension, compute the mean
%               of the feature and subtract it from the dataset,
%               storing the mean value in mu. Next, compute the
%               standard deviation of each feature and divide
%               each feature by it's standard deviation, storing
%               the standard deviation in sigma.
%
%               Note that X is a matrix where each column is a
%               feature and each row is an example. You need
%               to perform the normalization separately for
%               each feature.
%
% Hint: You might find the 'mean' and 'std' functions useful.
%

mu = mean(X);
sigma = std(X);
X_norm = (X - mu) ./ sigma;
#X_norm = (X - min(X)) ./ (max(X) - min(X))

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

end


function [ x, det ] = r8mat_solve_3d ( a, b, det, x )

%*****************************************************************************80
%
%% R8MAT_SOLVE_3D solves a 3 by 3 linear system using Cramer's rule.
%
%  Discussion:
%
%    If the determinant DET is returned as zero, then the matrix A is
%    singular, and does not have an inverse.  In that case, X is
%    returned as the [] vector.
%
%    If DET is nonzero, then its value is roughly an estimate
%    of how nonsingular the matrix A is.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 December 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A(3,3), the matrix.
%
%    Input, real B(3), the right hand side.
%
%    Output, real DET, the determinant of the matrix A.
%
%    Output, real X(3), the solution of the system,
%    if DET is nonzero.
%

%
%  Compute the determinant.
%
  det =  a(1,1) * ( a(2,2) * a(3,3) - a(2,3) * a(3,2) ) ...
       + a(1,2) * ( a(2,3) * a(3,1) - a(2,1) * a(3,3) ) ...
       + a(1,3) * ( a(2,1) * a(3,2) - a(2,2) * a(3,1) );
%
%  If the determinant is zero, bail out.
%
  if ( det == 0.0 )
    x = [];
    return
  end
%
%  Compute the solution.
%
  x(1) = (   ( a(2,2) * a(3,3) - a(2,3) * a(3,2) ) * b(1) ...
           - ( a(1,2) * a(3,3) - a(1,3) * a(3,2) ) * b(2) ...
           + ( a(1,2) * a(2,3) - a(1,3) * a(2,2) ) * b(3) ) / det;

  x(2) = ( - ( a(2,1) * a(3,3) - a(2,3) * a(3,1) ) * b(1) ...
           + ( a(1,1) * a(3,3) - a(1,3) * a(3,1) ) * b(2) ...
           - ( a(1,1) * a(2,3) - a(1,3) * a(2,1) ) * b(3) ) / det;

  x(3) = (   ( a(2,1) * a(3,2) - a(2,2) * a(3,1) ) * b(1) ...
           - ( a(1,1) * a(3,2) - a(1,2) * a(3,1) ) * b(2) ...
           + ( a(1,1) * a(2,2) - a(1,2) * a(2,1) ) * b(3) ) / det;

  return
end


function area = triangleArea(pt1, pt2, pt3)
%TRIANGLEAREA Signed area of a triangle
%
%   AREA = triangleArea(P1, P2, P3)
%   Computes area of the triangle whose vertices are given by P1, P2 and
%   P3. Each vertex is a 1-by-2 row vector.
%
%   AREA = triangleArea(PTS)
%   Concatenates vertex coordinates in a 3-by-2 array. Each row of the
%   array contains coordinates of one vertex.
%
%
%   Example
%   % Compute area of a Counter-Clockwise (CCW) oriented triangle
%     triangleArea([10 10], [30 10], [10 40])
%     ans =
%         300
%
%   % Compute area of a Clockwise (CW) oriented triangle
%     triangleArea([10 40], [30 10], [10 10])
%     ans =
%         -300
%
%   See also
%   polygonArea, triangleArea3d
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-08-23,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% if data is given as one array, split vertices
if nargin == 1
    pt2 = pt1(2,:);
    pt3 = pt1(3,:);
    pt1 = pt1(1,:);
end

% compute individual vectors
v12 = bsxfun(@minus, pt2, pt1);
v13 = bsxfun(@minus, pt3, pt1);

% compute area from cross product
area = (v13(:,2) .* v12(:,1) - v13(:,1) .* v12(:,2)) / 2;


% Figure 6.19: Polynomial fitting
% Section 6.5.3
% Boyd & Vandenberghe "Convex Optimization"
% Original by Lieven Vandenberghe
% Adapted for CVX by Joelle Skaf - 10/03/05
% (a figure is generated)
%
% Given data u_1,...,u_m and v_1,...,v_m in R, the goal is to fit to the
% data a polynomial of the form
% p(u) = x_1 + x_2*u + ... + x_n*u^{n-1}
% i.e. solve the problem:  minimize ||Ax - v||
% where A is the Vandermonde matrix s.t. Aij = u_i^{j-1}
% Two cases are considered: L2-norm and Linfty-norm

% Input data
n=6;
m=40;
randn('state',0);
% generate 50 ponts ui, vi
u = linspace(-1,1,m);
v = 1./(5+40*u.^2) + 0.1*u.^3 + 0.01*randn(1,m);

% LS fit polynomial x_1 + x_2*u + ... + x_n*u^(n-1) to (ui,vi)
fprintf(1,'Computing optimal polynomial in the case of L2-norm...');

A = vander(u');
A = A(:,m-n+[1:n]);     % last n columns of A
x = A\(v');             % coefficients of the polynomial in the following
                        % order: x = [x_n x_(n-1) ... x_2 x_1]'

fprintf(1,'Done! \n');

% L-infty fit
fprintf(1,'Computing optimal polynomial in the case of Linfty-norm...');

cvx_begin quiet
    variable x1(n)
    minimize (norm(A*x1 - v', inf))
cvx_end

fprintf(1,'Done! \n');

% generates 1000 points in  [-1,1]
u2 = linspace(-1.1,1.1,1000);

% evaluate the interpolating polynomial using Horner's method
vpol = x(1)*ones(1,1000);
vpoll1 = x1(1)*ones(1,1000);
for i = 2:n
  vpol = vpol.*u2 + x(i);
  vpoll1 = vpoll1.*u2 + x1(i);
end;

figure
% plot function and interpolating polynomial
plot(u2, vpol,'-', u, v, 'o', u2, vpoll1,'--');
xlabel('u');
ylabel('p(u)');
title('Fitting of data points with two polynomials of degree 5');
legend('L_2 norm','data points','L_{\infty} norm', 'Location','Best');
% print -deps polapprox.eps


function circle = makeCartCircle(radius, num_points, center_pos, arc_angle, plot_circle)
%MAKECARTCIRCLE     Create a 2D Cartesian circle or arc.
%
% DESCRIPTION:
%       MakeCartCircle creates a 2 x num_points array of the Cartesian
%       coordinates of points evenly distributed over a circle or arc (if
%       arc_angle is given).
%
% USAGE:
%       circle = makeCartCircle(radius, num_points)
%       circle = makeCartCircle(radius, num_points, center_pos)
%       circle = makeCartCircle(radius, num_points, center_pos, arc_angle)
%       circle = makeCartCircle(radius, num_points, center_pos, arc_angle, plot_circle)
%
% INPUTS:
%       radius          - circle radius [m]
%       num_points      - number of points in the circle
%
% OPTIONAL INPUTS:
%       center_pos      - [x, y] position of the circle center [m]
%                         (default = [0, 0])
%       arc_angle       - arc angle for incomplete circle [radians]
%                         (default = 2*pi)
%       plot_circle     - Boolean controlling whether the Cartesian points
%                         are plotted (default = false)
%
% OUTPUTS:
%       circle          - 2 x num_points array of Cartesian coordinates
%
% ABOUT:
%       author          - Bradley Treeby
%       date            - 5th June 2009
%       last update     - 20th March 2014
%
% This function is part of the k-Wave Toolbox (http://www.k-wave.org)
% Copyright (C) 2009-2014 Bradley Treeby and Ben Cox
%
% See also cart2grid, makeCartSphere, makeCircle

% This file is part of k-Wave. k-Wave is free software: you can
% redistribute it and/or modify it under the terms of the GNU Lesser
% General Public License as published by the Free Software Foundation,
% either version 3 of the License, or (at your option) any later version.
%
% k-Wave 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 Lesser General Public License for
% more details.
%
% You should have received a copy of the GNU Lesser General Public License
% along with k-Wave. If not, see <http://www.gnu.org/licenses/>.

% check for plot_circle input
if nargin < 5 || isempty(plot_circle)
    plot_circle = false;
end

% check for arc_angle input
if nargin < 4 || isempty(arc_angle)
    arc_angle = 2*pi;
    full_circle = true;
elseif arc_angle == 2*pi;
    full_circle = true;
else
    full_circle = false;
end

% check for center_pos input
if nargin < 3 || isempty(center_pos)
    cx = 0;
    cy = 0;
else
    cx = center_pos(1);
    cy = center_pos(2);
end

% ensure there is only a total of num_points including the endpoints when
% arc_angle is not equal to 2*pi
if ~full_circle
    num_points = num_points - 1;
end

% create angles
angles = (0:(num_points))*arc_angle/(num_points) + pi/2;

% discard repeated final point if arc_angle is equal to 2*pi
if full_circle
    angles = angles(1:end-1);
end

% create cartesian grid
% circle = flipud([radius*cos(angles); radius*sin(-angles)]);   % B.0.3
circle = ([radius*cos(angles); radius*sin(-angles)]);           % B.0.4

% offset if needed
circle(1, :) = circle(1, :) + cx;
circle(2, :) = circle(2, :) + cy;

% plot results
if plot_circle

    % select suitable axis scaling factor
    [x_sc, scale, prefix] = scaleSI(max(abs(circle(:))));

    % create the figure
    figure;
    plot(circle(2,:)*scale, circle(1,:)*scale, 'b.');
    set(gca, 'YDir', 'reverse');
    xlabel(['y-position [' prefix 'm]']);
    ylabel(['x-position [' prefix 'm]']);
    axis equal;

end


function [R_sq]=R_squared(y,yf)

% function [R_squared]=R_squared(y,yf)
% ------------------------------------------------------------------------
% This function calculates the coefficient of determination (R-Squared) for
% the (e.g. measurement) data |y| and the data |yf| (e.g. a model fit).
% NaN entries in either inputs are ignored.
%
%
% Change log:
% 2008/10/05
% 2019/06/26 Updated description
% 2019/06/26 Updated handling of NaN entries in the data
% ------------------------------------------------------------------------

%%

L=~isnan(y) & ~isnan(yf); %Logic for non-NaN entries

y_bar=mean(y(L)); %Mean of y
SS_err=sum((y(L)-yf(L)).^2); %Sum of differences Of y with yf
SS_tot=sum((y(L)-y_bar).^2); %Sum of differences of y with mean
R_sq=1-(SS_err./SS_tot); %R-squared value

%%
% _*GIBBON footer text*_
%
% License: <https://github.com/gibbonCode/GIBBON/blob/master/LICENSE>
%
% GIBBON: The Geometry and Image-based Bioengineering add-On. A toolbox for
% image segmentation, image-based modeling, meshing, and finite element
% analysis.
%
% Copyright (C) 2006-2022 Kevin Mattheus Moerman and the GIBBON contributors
%
% 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 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program.  If not, see <http://www.gnu.org/licenses/>.


function u2 = fd1d_wave_start ( x_num, x_vec, t, t_delta, alpha, u_x1, u_x2, ...
  ut_t1, u1 )

%*****************************************************************************80
%
%% FD1D_WAVE_START takes the first step for the wave equation.
%
%  Discussion:
%
%    This program solves the 1D wave equation of the form:
%
%      Utt = c^2 Uxx
%
%    over the spatial interval [X1,X2] and time interval [T1,T2],
%    with initial conditions:
%
%      U(T1,X)  = U_T1(X),
%      Ut(T1,X) = UT_T1(X),
%
%    and boundary conditions of Dirichlet type:
%
%      U(T,X1) = U_X1(T),
%      U(T,X2) = U_X2(T).
%
%    The value C represents the propagation speed of waves.
%
%    The program uses the finite difference method, and marches
%    forward in time, solving for all the values of U at the next
%    time step by using the values known at the previous two time steps.
%
%    Central differences may be used to approximate both the time
%    and space derivatives in the original differential equation.
%
%    Thus, assuming we have available the approximated values of U
%    at the current and previous times, we may write a discretized
%    version of the wave equation as follows:
%
%      Uxx(T,X) = ( U(T,   X+dX) - 2 U(T,X) + U(T,   X-dX) ) / dX^2
%      Utt(T,X) = ( U(T+dt,X   ) - 2 U(T,X) + U(T-dt,X   ) ) / dT^2
%
%    If we multiply the first term by C^2 and solve for the single
%    unknown value U(T+dt,X), we have:
%
%      U(T+dT,X) =        (     C^2 * dT^2 / dX^2 ) * U(T,   X+dX)
%                  +  2 * ( 1 - C^2 * dT^2 / dX^2 ) * U(T,   X   )
%                  +      (     C^2 * dT^2 / dX^2 ) * U(T,   X-dX)
%                  -                                  U(T-dT,X   )
%
%    (Equation to advance from time T to time T+dT, except for FIRST step!)
%
%    However, on the very first step, we only have the values of U
%    for the initial time, but not for the previous time step.
%    In that case, we use the initial condition information for dUdT
%    which can be approximated by a central difference that involves
%    U(T+dT,X) and U(T-dT,X):
%
%      dU/dT(T,X) = ( U(T+dT,X) - U(T-dT,X) ) / ( 2 * dT )
%
%    and so we can estimate U(T-dT,X) as
%
%      U(T-dT,X) = U(T+dT,X) - 2 * dT * dU/dT(T,X)
%
%    If we replace the "missing" value of U(T-dT,X) by the known values
%    on the right hand side, we now have U(T+dT,X) on both sides of the
%    equation, so we have to rearrange to get the formula we use
%    for just the first time step:
%
%      U(T+dT,X) =   1/2 * (     C^2 * dT^2 / dX^2 ) * U(T,   X+dX)
%                  +       ( 1 - C^2 * dT^2 / dX^2 ) * U(T,   X   )
%                  + 1/2 * (     C^2 * dT^2 / dX^2 ) * U(T,   X-dX)
%                  +  dT *                         dU/dT(T,   X   )
%
%    (Equation to advance from time T to time T+dT for FIRST step.)
%
%    It should be clear now that the quantity ALPHA = C * DT / DX will affect
%    the stability of the calculation.  If it is greater than 1, then
%    the middle coefficient 1-C^2 DT^2 / DX^2 is negative, and the
%    sum of the magnitudes of the three coefficients becomes unbounded.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 January 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    George Lindfield, John Penny,
%    Numerical Methods Using MATLAB,
%    Second Edition,
%    Prentice Hall, 1999,
%    ISBN: 0-13-012641-1,
%    LC: QA297.P45.
%
%  Parameters:
%
%    Input, integer X_NUM, the number of nodes in the X direction.
%
%    Input, real X_VEC(X_NUM), the spatial coordinates of the nodes.
%
%    Input, real T, the time after the first step has been taken.
%    In other words, T = T1 + T_DELTA.
%
%    Input, real T_DELTA, the time step.
%
%    Input, real ALPHA, the stability coefficient, computed by FD1D_WAVE_ALPHA.
%
%    Input, real U_X1(T), U_X2(T), functions for the left and right boundary
%    conditions.
%
%    Input, real UT_T1(X), the function that evaluates dUdT at the initial time.
%
%    Input, real U1(X_NUM), the initial condition.
%
%    Output, real U2(X_NUM), the solution at the first time step.
%
  ut = ut_t1 ( x_num, x_vec );

  u2 = zeros ( 1, x_num );

  u2(1) = u_x1 ( t );
  u2(2:x_num-1) =         alpha^2   * u1(3:x_num) / 2 ...
                  + ( 1 - alpha^2 ) * u1(2:x_num-1) ...
                  +       alpha^2   * u1(1:x_num-2) / 2 ...
                  +        t_delta  * ut(2:x_num-1);
  u2(x_num) = u_x2 ( t );

  return
end


function Area=unitVectors2SpherTriangArea(u,r)
%%UNITVECTORS2SPHERTRIANGAREA Given unit vectors pointing from the center
%     of a 3D sphere to three points on the sphere, as well as the radius
%     of the sphere, determine the surface area of a spherical triangle.
%
%INPUTS: u A 3X3 matrix such that u(:,i) is the ith unit vector pointing
%          from the center of the sphere to the surface of the sphere.
%        r The scalar radius of the sphere. If this is omitted or an empty
%          matrix is passed, the default of 1 is used.
%
%OUTPUTS: Area The area of the specified triangle on the surface of a
%              sphere of radius r.
%
%Equation 1 in [1] is implemented. The absolute value of the atan function
%is taken so that the result is always positive.
%
%EXAMPLE:
%We find the surface area of a quadrant of a unit sphere. Since the surface
%area of an entire sphere is 4*pi*r^2, the area of a quadrant will be pi/2.
%The relative error is zero.
% u=[[1;0;0],[0;1;0],[0;0;1]];
% r=1;
% Area=unitVectors2SpherTriangArea(u,r);
% trueArea=pi/2;
% RelErr=(Area-trueArea)./trueArea
%
%REFERENCES:
% [1] F. Eriksson, "On the measure of solid angles," Mathematics Magazine,
%     vol. 63, no. 3, pp. 184-187, 1990.
%
%October 2022 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

a=u(:,1);
b=u(:,2);
c=u(:,3);

Area=2*r^2*abs(atan(dot(a,cross(b,c))/(1+dot(b,c)+dot(c,a)+dot(a,b))));

end

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


function val=intCosPow(u,n)
%%INTCOSPOWER Evaluate the integral of cos(u)^n du.  A definite integral
%             can be evaluated, or an indefinite integral (with a
%             particular additive constant).
%
%INPUTS: u A 2XN (for definite integral) or a 1XN (for indefinite
%          integrals) set of N points. For definite integrals, u(1,:) are
%          the real lower bounds and u(2,:) are the real upper bounds. For
%          indefinite integrals, the integral is evaluated at the points in
%          u. The values in u should be real.
%        n The positive integer exponent of the cosine term.
%
%OUTPUTS: val The 1XN set of values of the integral of cos(u)^n.
%
%This function simply implements the recursion that arises from integration
%by parts from basic calculus, as are given in the tables in the back of
%[1].
%
%REFERENCES:
%[1] J. Stewart, Calculus, 7th ed. Belmont, CA: Brooks/Cole, 2012.
%
%October 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numDim=size(u,1);

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

if(numDim==1)%An indefinite integral
    val=indefIntCosPow(u,n);
else%A definite integral
    val=indefIntCosPow(u(2,:),n)-indefIntCosPow(u(1,:),n);
end

end

function val=indefIntCosPow(u,n)

%Special cases for n=0 and n=1.
if(n==0)
    val=u;
    return;
elseif(n==1)
    val=sin(u);
    return;
end

%If here, n>=1
sinVal=sin(u);
cosVal=cos(u);

val=0;
if(mod(n,2)==0)%If n is even
    endVal=2;
else
    endVal=3;
end

coeffProd=1;
for k=n:-2:endVal
    val=val+coeffProd*(1/k)*cosVal.^(k-1).*sinVal;
    coeffProd=coeffProd*(k-1)/k;
end

if(endVal==2)
    %The final integral is over cos^0
    val=val+coeffProd*u;
else
    %The final integral is over cos^1
    val=val+coeffProd*sinVal;
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 val=intSinPow(u,n)
%%INTSINPOWER Evaluate the integral of sin(u)^n du.  A definite integral
%             can be evaluated, or an indefinite integral (with a
%             particular additive constant).
%
%INPUTS: u A 2XN (for definite integral) or a 1XN (for indefinite
%          integrals) set of N points. For definite integrals, u(1,:) are
%          the real lower bounds and u(2,:) are the real upper bounds. For
%          indefinite integrals, the integral is evaluated at the points in
%          u. The values in u should be real.
%        n The positive integer exponent of the sine term.
%
%OUTPUTS: val The 1XN set of values of the integral of sin(u)^n.
%
%This function simply implements the recursion that arises from integration
%by parts from basic calculus, as are given in the tables in the back of
%[1].
%
%REFERENCES:
%[1] J. Stewart, Calculus, 7th ed. Belmont, CA: Brooks/Cole, 2012.
%
%October 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numDim=size(u,1);

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

if(numDim==1)%An indefinite integral
    val=indefIntSinPow(u,n);
else%A definite integral
    val=indefIntSinPow(u(2,:),n)-indefIntSinPow(u(1,:),n);
end
end

function val=indefIntSinPow(u,n)

%Special cases for n=0 and n=1.
if(n==0)
    val=u;
    return;
elseif(n==1)
    val=-cos(u);
    return;
end

%If here, n>=1
sinVal=sin(u);
cosVal=cos(u);

val=0;
if(mod(n,2)==0)%If n is even
    endVal=2;
else
    endVal=3;
end

coeffProd=1;
for k=n:-2:endVal
    val=val-coeffProd*(1/k)*sinVal.^(k-1).*cosVal;
    coeffProd=coeffProd*(k-1)/k;
end

if(endVal==2)
    %The final integral is over sin^0
    val=val+coeffProd*u;
else
    %The final integral is over sin^1
    val=val-coeffProd*cosVal;
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 varargout = randomAngle3d(varargin)
%RANDOMANGLE3D Return a 3D angle uniformly distributed on unit sphere.
%
%   usage
%   [THETA PHI] = randomAngle3d
%   Generate an angle unformly distributed on the surface of the unit
%   sphere.
%
%   "Mathematical" convention is used: theta is the colatitude (angle with
%   vertical axis, 0 for north pole, +pi for south pole, pi/2 for points at
%   equator) with z=0.
%   phi is the same as matlab cart2sph: angle from Ox axis, counted
%   positively counter-clockwise.
%
%   [THETA PHI] = randomAngle3d(N)
%   generates N random angles (N is a scalar). The result is a N-by-2
%   array.
%
%   Example:
%     % Draw some points on the surface of a sphere
%     figure;
%     drawSphere; hold on;
%     drawPoint3d(pts, '.');
%     axis equal;
%
%   See also
%   angles3d, sph2cart2, cart2sph2

% ------
% Author: David Legland
% E-mail: david.legland@grignon.inra.fr
% Created: 2005-02-18
% Copyright 2005-2022 INRA - Cepia Software platform

N = 1;
if ~isempty(varargin)
    N = varargin{1};
end

phi = 2*pi*rand(N, 1);
theta = asin(2*rand(N, 1)-1) + pi/2;

if nargout<2
    var = [theta phi];
    varargout{1} = var;
else
    varargout{1} = theta;
    varargout{2} = phi;
end


function value = ball_volume_nd ( n, r )

%*****************************************************************************80
%
%% BALL_VOLUME_ND computes the volume of a ball in ND.
%
%  Integration region:
%
%    Points X(1:N) such that
%
%      Sum ( X(1:N)**2 ) <= R**2
%
%  Discussion:
%
%    N  Volume
%
%    2             PI    * R**2
%    3  (4/3)    * PI    * R**3
%    4  (1/2)    * PI**2 * R**4
%    5  (8/15)   * PI**2 * R**5
%    6  (1/6)    * PI**3 * R**6
%    7  (16/105) * PI**3 * R**7
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the dimension of the space.
%
%    Input, real R, the radius of the ball.
%
%    Output, real BALL_VOLUME_ND, the volume of the ball.
%
  value = ball_unit_volume_nd ( n ) * r^n;

  return
end


function mu = triangmf(z,a,b,c)
%TRIANGMF Triangular membership function.
%   MU = TRIANGMF(Z,A,B,C) computes a fuzzy membership function with a
%   triangular shape. Z is the input variable and can be a vector of any
%   length. A, B, and C are scalar parameters, such that B >= A and C >=
%   B, that define the triangular shape.
%
%       MU = 0                          Z < A
%       MU = (Z - A) ./ (B - A)         A <= Z < B
%       MU = 1 - (Z - B) ./ (C - B)     B <= Z < C
%       MU = 0                          C <= Z
%
%   Copyright 2002-2020 Gatesmark
%
%   This function, and other functions in the DIPUM Toolbox, are based
%   on the theoretical and practical foundations established in the
%   book Digital Image Processing Using MATLAB, 3rd ed., Gatesmark
%   Press, 2020.
%
%   Book website: http://www.imageprocessingplace.com
%   License: https://github.com/dipum/dipum-toolbox/blob/master/LICENSE.txt

mu = zeros(size(z));

low_side  = (a <= z) & (z < b);
high_side = (b <= z) & (z < c);

mu(low_side)  = (z(low_side) - a)./(b - a);
mu(high_side) = 1 - (z(high_side) - b)./(c - b);


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

g = zeros(size(z));

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

g = exp(-z) ./ ((1.0 + exp(-z)) .^ 2);

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

end


function [ b, det ] = r8mat_inverse_3d ( a )

%*****************************************************************************80
%
%% R8MAT_INVERSE_3D inverts a 3 by 3 R8MAT using Cramer's rule.
%
%  Discussion:
%
%    If DET is zero, then A is singular, and does not have an
%    inverse.  In that case, B is simply set to zero, and a
%    message is printed.
%
%    If DET is nonzero, then its value is roughly an estimate
%    of how nonsingular the matrix A is.
%
%  Modified:
%
%    31 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A(3,3), the matrix to be inverted.
%
%    Output, real B(3,3), the inverse of the matrix.
%
%    Output, real DET, the determinant of the matrix.
%

%
%  Compute the determinant of A
%
  det =   a(1,1) * ( a(2,2) * a(3,3) - a(2,3) * a(3,2) ) ...
        + a(1,2) * ( a(2,3) * a(3,1) - a(2,1) * a(3,3) ) ...
        + a(1,3) * ( a(2,1) * a(3,2) - a(2,2) * a(3,1) );
%
%  If the determinant is zero, bail out.
%
  if ( det == 0.0 )
    b(1:3,1:3) = 0.0;
    return
  end
%
%  Compute the entries of the inverse matrix using an explicit
%  formula.
%
  b(1,1) = + ( a(2,2) * a(3,3) - a(2,3) * a(3,2) ) / det;
  b(1,2) = - ( a(1,2) * a(3,3) - a(1,3) * a(3,2) ) / det;
  b(1,3) = + ( a(1,2) * a(2,3) - a(1,3) * a(2,2) ) / det;

  b(2,1) = - ( a(2,1) * a(3,3) - a(2,3) * a(3,1) ) / det;
  b(2,2) = + ( a(1,1) * a(3,3) - a(1,3) * a(3,1) ) / det;
  b(2,3) = - ( a(1,1) * a(2,3) - a(1,3) * a(2,1) ) / det;

  b(3,1) = + ( a(2,1) * a(3,2) - a(2,2) * a(3,1) ) / det;
  b(3,2) = - ( a(1,1) * a(3,2) - a(1,2) * a(3,1) ) / det;
  b(3,3) = + ( a(1,1) * a(2,2) - a(1,2) * a(2,1) ) / det;


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

% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));

% ====================== YOUR CODE HERE ======================
% Instructions: First, for each feature dimension, compute the mean
%               of the feature and subtract it from the dataset,
%               storing the mean value in mu. Next, compute the
%               standard deviation of each feature and divide
%               each feature by it's standard deviation, storing
%               the standard deviation in sigma.
%
%               Note that X is a matrix where each column is a
%               feature and each row is an example. You need
%               to perform the normalization separately for
%               each feature.
%
% Hint: You might find the 'mean' and 'std' functions useful.
%

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

for i = 1:size(X,2)
	X_norm(:,i) = (X(:,i) - mu(i)) / sigma(i);
end

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

end


function [p,t] = smoothmesh(p,t,maxit,tol)

%*****************************************************************************80
%
%  SMOOTHMESH: Smooth a triangular mesh using Laplacian smoothing.
%
% Laplacian smoothing is an iterative process that generally leads to an
% improvement in the quality of the elements in a triangular mesh.
%
%  [p,t] = smoothmesh(p,t);
%
%  p     : Nx2 array of nodal XY coordinates, [x1,y1; x2,y2; etc].
%  t     : Mx3 array of triangles as indices, [n11,n12,n13;
%                                              n21,n22,n23; etc].
%  maxit : Maximum allowable iterations.
%  tol   : Convergence tolerance (Percentage change in edge length must be
%          less than TOL).
%
% If MAXIT or TOL are left empty the default values MAXIT = 20 and TOL =
% 0.01 are used.
%
%  EXAMPLE:
%
%  [p,t] = smoothmesh(p,t,10,0.05);
%
%  Author:
%
%    Darren Engwirda
%

if nargin<4
   tol = [];
   if nargin<3
      maxit = [];
      if nargin<2
         error('Incorrect number of inputs.');
      end
   end
elseif nargin>5
   error('Incorrect number of inputs.')
end
if nargout>2
   error('Incorrect number of outputs.');
end
if isempty(tol)
   tol = 0.01;
end
if isempty(maxit)
   maxit = 20;
end

[p,t] = fixmesh(p,t);                                                      % Ensure consistent mesh

n = size(p,1);
S = sparse(t(:,[1,1,2,2,3,3]),t(:,[2,3,1,3,1,2]),1,n,n);                   % Sparse connectiity matrix
W = sum(S,2);
if any(W==0)
   error('Invalid mesh. Hanging nodes found.');
end

edge = [t(:,[1,2]); t(:,[1,3]); t(:,[2,3])];                               % Non-unique edges
edge = sortrows(sort(edge,2));                                             % Put shared edges next to each other
idx = all(diff(edge)==0,2);                                                % Find shared edges
idx = [idx;false]|[false;idx];                                             % True for all shared edges
bnde = edge(~idx,:);                                                       % Boundary edges
edge = edge(idx,:);                                                        % Internal edges
edge = [bnde; edge(1:2:end-1,:)];                                          % Unique edges
bnd = unique(bnde);                                                        % Boundary nodes

L = max(sqrt(sum((p(edge(:,1),:)-p(edge(:,2),:)).^2,2)),eps);              % Edge length

for iter = 1:maxit
   pnew = (S*p)./[W,W];                                                    % Laplacian smoothing
   pnew(bnd,:) = p(bnd,:);                                                 % Dont let BND nodes move
   p = pnew;

   Lnew = max(sqrt(sum((p(edge(:,1),:)-p(edge(:,2),:)).^2,2)),eps);        % Edge length
   move = norm((Lnew-L)./Lnew,inf);                                        % Percentage change
   if move<tol
      break
   end
   L = Lnew;
end
if iter==maxit
   disp('WARNING: Maximum number of iterations reached, solution did not converge!');
end

end      % smoothmesh()


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.

predictions = X * theta;
sqrErrors = (predictions - y).^2;

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

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

end


function fibonacci_spiral_connected ( n )

%*****************************************************************************80
%
%% FIBONACCI_SPIRAL_CONNECTED draws connected points on a Fibonacci spiral.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 April 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points to plot.
%    Default is 101.
%
  if ( nargin < 1 )
    n = 101;
  end
%
%  PHI is the golden ratio, the limit of the ratio of
%  successive Fibonacci numbers:
%
%    PHI = limit ( N->oo ) F(N+1)/F(N)
%
  phi = ( 1.0 + sqrt ( 5.0 ) ) / 2.0;
%
%  Allocate storage for the point data.
%
  x = zeros ( n, 1 );
  y = zeros ( n, 1 );
%
%  Set the angle and radius of the first point.
%
  a = 0.0;
  r = 0.0;
%
%  Set the increments.
%
  da = 2.0 * pi * ( phi - 1.0 ) / phi;
  dr = 1.0;
%
%  Create a spiral in which the radius R and angle A both
%  increase by a constant increment,
%
  for i = 1 : n
    x(i) = r * cos ( a );
    y(i) = r * sin ( a );
    a = mod ( a + da, 2 * pi );
    r = r + dr;
  end
%
%  SCALE controls how many steps we take between the actual points.
%  A value of 5 is enough to see the basic spiral that connects the points.
%  A vale of 10 would make a smoother spiral.
%
  scale = 5.0;
%
%  Allocate storage for the intermediate data.
%
  n2 = scale * ( n - 1 ) + 1;
  x2 = zeros ( n2, 1 );
  y2 = zeros ( n2, 1 );
%
%  Set the angle and radius of the first point.
%
  a = 0.0;
  r = 0.0;
%
%  Set the increments.
%
  da = 2.0 * pi * ( phi - 1.0 ) / phi;
  dr = 1.0;

  da = da / scale;
  dr = dr / scale;
%
%  Create a spiral in which the radius R and angle A both
%  increase by a constant increment,
%
  for i = 1 : n2
    x2(i) = r * cos ( a );
    y2(i) = r * sin ( a );
    a = mod ( a + da, 2 * pi );
    r = r + dr;
  end
%
%  Display the points,
%  and use the intermediate points to draw lines that display the spiral.
%
  figure
  scatter ( x, y, 'b.' );
  hold on
  plot ( x2, y2, 'r-' )
  axis equal
  title ( sprintf ( 'Connected Fibonacci spiral, N = %d', n ) )
  hold off

  return
end


%% RATE OF CONVERGENCE OF LINEAR ELEMENT FOR POISSON EQUATION
%
% This example is to show the rate of convergence of linear finite element
% approximation of the Poisson equation on the unit square with the
% following boundary conditions:
%
% - Non-empty Dirichlet boundary condition.
% - Pure Neumann boundary condition.
% - Robin boundary condition.
%
% The basis, data structure and numerical test is summarized in <a
% href="matlab:ifem Poissonfemrate">Poissonfemrate</a>.
%
% See also PoissonP2femrate, Poissonafemrate
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

clear variables
%% Setting
[node,elem] = squaremesh([0,1,0,1],0.25);
mesh = struct('node',node,'elem',elem);
option.L0 = 3;
option.maxIt = 4;
option.printlevel = 1;

%% Non-empty Dirichlet boundary condition.
option.plotflag = 1;
pde = sincosdata;
mesh.bdFlag = setboundary(node,elem,'Dirichlet','~(x==0)','Neumann','x==0');
femPoisson(mesh,pde,option);

%% Pure Neumann boundary condition.
option.plotflag = 0;
% pde = sincosNeumanndata;
pde = sincosdata;
mesh.bdFlag = setboundary(node,elem,'Neumann');
femPoisson(mesh,pde,option);

%% Pure Robin boundary condition.
option.plotflag = 0;
pde = sincosRobindata;
mesh.bdFlag = setboundary(node,elem,'Robin');
femPoisson(mesh,pde,option);

%% Conclusion
%
% The optimal rate of convergence of the H1-norm (1st order) and L2-norm
% (2nd order) is observed. The 2nd order convergent rate between two
% discrete functions ||DuI-Duh|| is known as superconvergence.
%
% MGCG converges uniformly in all cases.


function [ freq,amp,phase,dc ] = fourier_series_real( t,x )
% function [ freq,amp,phase,dc ] = fourier_series_real( t,x )
% Fourier series of real signals.
% Written by Yoash Levron, January 2013.
%
% This function computes the fourier series of a signal x(t).
% the amplitudes of the fourier series have the same dimension
% of the original signal, so this function is useful for immediate
% computation of the actual frequency components, without
% further processing.
%
% for example, x(t) = 2 + 3*cos(2*pi*50*t) will result in
% dc value = 2
% frequencies = [50   100  150   200 ...]
% amplitudes   = [3     0      0        0     ...]
% phases         = [0     0      0        0     ...]
%
% x(t) is one cycle of an infinite cyclic signal. The function
% computes the fourier transform of that infinite signal.
% the period of the signal (T) is determined by the length
% of the input time vector, t.
% x(t) must be real (no imaginary values).
%
% The signal x(t) is represented as:
% x(t) = Adc + A1*cos(w*t + ph1) + A2*cos(2*w*t + ph2) + ...
% the function computes the amplitudes, Adc,A1,A2...
% and the phases ph1,ph2,...
%
% T = period of the signal = t(end) - t(1)
% w = basic frequency = 2*pi/T
%
% The function automatically interpolates the original signal
% to avoid aliasing. Likewise, the function automatically determines
% the number of fourier components, and truncates trailing zeros.
%
% inputs:
% t - [sec] time vector. Sample time may vary within the signal.
% x - signal vector. same length as t.
%
% outputs:
% freq - [Hz] frequencies of the fourier series, not including zero.
% amp - amplitudes vector. amp=[A1 A2 A3 ...], not including the DC component.
% phase - [rad/sec] . phases, not including the DC component.
% dc - the DC value (average of the signal).

%%%%%%%%%%% computation %%%%%%%%
rel_tol = 1e-4;  % relative tolerance, to determine trailing zero truncation

if (~isreal(x))
        clc;
        beep;
        disp('fourier_series_real Error:  x(t) must be real.');
        dc = NaN;  amp = NaN;  freq = NaN;  phase = NaN;
        return;
end

t = t-t(1);  % shifting time to zero.
T = t(end);  % period time.
N = 100;  % number of samples
if (mod(N,2) == 1)
    N = N + 1;
end
N = N/2;

ok = 0;
while (~ok)
    N = N*2;  % increase number of samples

    if (N > 10e6)
        clc;
        beep;
        disp('fourier_series_real Error: signal bandwidth seems too high.');
        disp('Try decreasing the sample time in the input time vector t,');
        disp('or increasing the relative tolerance rel_tol');
        dc = NaN;  amp = NaN;  freq = NaN;  phase = NaN;
        return;
    end
    dt = T/N;
    t1 = 0:dt:(T-dt);
    x1 = interp1(t,x,t1,'cubic',0);
    xk = (1/N)*fft(x1);

    dc = abs(xk(1));
    xkpos = xk(2:(N/2));
    xkneg = xk(end:-1:(N/2+2));

    freq = [1:length(xkpos)]/T;  % Hz
    amp = 2*abs(xkpos);
    phase = angle(xkpos);  % rad/sec

    %%% check if enough samples are used.
    %%% if not, try again, with more samples.
    Am = max(amp);
    ii = find((amp(end-10:end)/Am)>rel_tol);
    ok = isempty(ii);
end

% %%% truncate output vectors to remove trailing zeros
Am = max(amp);
ii = length(amp);
while (amp(ii) < Am*rel_tol)
    ii = ii - 1;
end
amp = amp(1:ii);
freq = freq(1:ii);
phase = phase(1:ii);

end


function [x,xL,t,intersects]=findClosestPointLineEllipsoid(xc,A,x0,a,aType,epsConst)
%%FINDCLOSESTPOINTLINEELLIPSOID Given a 2D or 3D ellipsoid of the form
%           (x-xc)'*A*(x-xc)=1, and a line of the form x=x0+s*t, where t is
%           a scalar parameteric parameter, find the point on the ellipsoid
%           that is closest to the line as well as the point on the line
%           that is closest to the ellipsoid. If the line intersects the
%           ellipsoid, then more than once point can be returned. All
%           solutions and inputs are real.
%
%INPUTS: xc The xDimX1 center of the ellipsoid.
%         A The xDimXxDim symmetric positive definite matrix defining the
%           above equation for an ellipsoid.
%     x0, a These xDimX1 values define a line and the type of line is given
%           by aType. If aType=0, then the line is parameteric as x=x0+a*t
%           where t is a scalar value. If aType=1, then x0 and a are both
%           points on the line.
%     aType As mentioned above, this specifies how the line is
%           parameterized. The default if omitted or an empty matrix is
%           passed is 0.
%  epsConst In the rooting formulation of the solution, is is possible that
%           some candidate solutions are invalid (they do not satisfy the
%           constraint (x-xc)'*A*(x-xc)=1. Thus, the absolute value of a
%           transformed version of abs((x-xc)'*A*(x-xc)-1) must be
%           <=epsConst to be valid. The default if omitted or an empty
%           matrix is passed is 1e-9.
%
%OUTPUTS: x The xDimXnumSol set of closest points on the ellipsoid. If the
%           line and ellipsoid do not intersect, numSol=1.
%        xL The xDimXnumSol set of closest points on the line. These
%           correspond to those in x.
%         t The 1XnumSol set of parametric values such that the kth one is
%           xL(:,k)=x0+s*t(k).
% intersects If the line intersects the ellipsoid, this is true. Otherwise,
%           it is false.
%
%This function utilizes a change of coordiantes to solve the problem.
%We have to solve the optimization problem.
%minimize norm(x0+s*t-x)^2
%such that
%(x-xc)'*A*(x-xc)=1
%We perform an eigenvalue decomposition of A as A=U*D*U', where D is a
%diagonal matrix and U is in a unitary matrix (because A is symmetric and
%positive definite). Next, perform the change of variables
%x=U*y+xc
%s=U*c1        or c1=U'*s
%c=x0-xc=U*c2  or c2=U'*(x0-xc)
%c=U*c2
%Because U'*U=I, the optimization problem becomes:
%norm(c1*t-y+c2)^2
%Subject to
%y'*D*y=1
%Thus, we solve for y and transform back into x. The method of solution is
%Lagrangian relaxation. Chapter 4.1 or [1] goes over Lagrangian
%multipliers. The Lagrangian for the problem is
%L=norm(c1*t-y+c2)^2+lambda*(y'*D*y-1)
%Setting the derivatives of L with respect to t and y equal to 0, one gets
%a solution in terms of lambda (the Lagrangian parameter). One can then
%choose lambda to satisfy the constraint y'*D*y=1. In this instance, that
%can be formulated as involves solving a polynomial in terms of lambda.
%That is what this function does. Due to possible singularities in a ratio
%that is reduced to the polynomial, it is possible that invalid solutiosn
%will be found. Thus, the epsConst parameter is introduced to throw out
%possible solutions that do not sufficiently satisfy the condition. Of the
%multiple solutions found for lambda, only the one minimizing the cost
%function is kept.
%
%EXAMPLE 1:
%This example is done in 2D, so it can be easily plotted. Multiple lines
%are drawn. Two intersect an ellipse and two do not intersect the ellipse.
%The closest points on the ellipse are drawn in red. Those on the lines at
%black circles. Dashed black lines connect them.
% xc=[2;2];
% A=[0.5,-0.1;
%   -0.1, 0.2];
% figure(1)
% clf
% hold on
% drawEllipse(xc,A,1,'linewidth',2)
% axis([-2, 6, -2, 6])
% axis square
% t=linspace(-10,10,500);
% %Consider 4 lines.
% a=[1,0,0, -2;
%    2,0,-2, -1];
% b=[4,1,-2,3;
%    3,1,-1,-1;];
% numLines=size(a,2);
% for k=1:numLines
%     xy=bsxfun(@plus,a(:,k),bsxfun(@times,b(:,k),t));
%     plot(xy(1,:),xy(2,:),'linewidth',2)
%     [x,xL]=findClosestPointLineEllipsoid(xc,A,a(:,k),b(:,k));
%
%     scatter(x(1,:),x(2,:),200,'.r')
%     scatter(xL(1,:),xL(2,:),100,'ok')
%     if(size(xL,2)==1)
%         %If the line either grazes the unit circle or does not intercept
%         %the unit circle, connect the point on the line to the nearest
%         %point on the circle.
%         plot([x(1),xL(1)],[x(2),xL(2)],'--k')
%     end
% end
%
%EXAMPLE 2:
%This example is similar to the first one, but is in 3D.
% xc=[2;2;0];
% A=[0.5,-0.1, 0.15;
%   -0.1, 0.2, 0.15;
%    0.15,0.15,0.3];
% figure(1)
% clf
% hold on
% drawEllipse(xc,A,1,'edgecolor','none')
% light()
% %axis([-2, 6, -2, 6])
% %axis square
% t=linspace(-10,10,500);
% %Consider 4 lines.
% a=[1,0,0, -2;
%    2,0,-2, -1;
%    1,0,1, -1];
% b=[4,1,-2,3;
%    3,1,-1,-1;
%    1,2,0,0];
% numLines=size(a,2);
% for k=1:numLines
%     xyz=bsxfun(@plus,a(:,k),bsxfun(@times,b(:,k),t));
%     plot3(xyz(1,:),xyz(2,:),xyz(3,:),'linewidth',2)
%     [x,xL]=findClosestPointLineEllipsoid(xc,A,a(:,k),b(:,k));
%     scatter3(x(1,:),x(2,:),x(3,:),200,'.r')
%     scatter3(xL(1,:),xL(2,:),xL(3,:),100,'ok')
%     if(size(xL,2)==1)
%         %If the line either grazes the unit circle or does not intercept
%         %the unit circle, connect the point on the line to the nearest
%         %point on the circle.
%         plot3([x(1),xL(1)],[x(2),xL(2)],[x(3),xL(3)],'--k')
%     end
% end
% axis([-6, 6, -6, 6,-6,6])
% axis square
% view(-8,30)
%
%REFERENCES:
%[1] D. P. Bertsekas, Nonlinear Programming, 2nd ed. Belmont, MA:
%    Athena Science, 1999.
%
%October 2021 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<6||isempty(epsConst))
    epsConst=1e-9;
end

if(nargin<5||isempty(aType))
    aType=0;
end

if(aType==1)
    s=a-x0;
else
    s=a;
end

%The special case of s being 0. This means that we just find the closest
%point on the ellipsoid to the point x0.
if(all(s==0))
    x=nearestPointOnEllipsoid(xc,A,x0,1);
    xL=x0;
    t=0;
    intersects=all(x==xL);
    return;
end

%Check the special case of the line intercepting the ellipsoid. In this
%instance,
[x,t]=findEllipsLineIntersect(xc,A,x0,s,0);
if(~isempty(x))
    t=t';
    xL=x;
    intersects=true;
    return;
end

%There is a line and it does not intercept the ellipsoid. Find the closest
%point.
intersects=false;

[~,D,U]=eig(A);
c1=U'*s;
c2=U'*(x0-xc);

[y,t]=solveDiagA(D,c2,c1,epsConst);

%Transform back to x
x=bsxfun(@plus,U*y,xc);
xL=bsxfun(@plus,x0,bsxfun(@times,s,t));

end

function [x,t]=solveDiagA(A,a,b,epsConst)

numDim=size(a,1);
switch(numDim)
    case 2
        a11=A(1,1);
        a22=A(2,2);
        a1=a(1);
        a2=a(2);
        b1=b(1);
        b2=b(2);

        firstTerm=-a11*a22*(b1^2+b2^2)*(a11*b1^2+a22*b2^2);
        sqrtTerm=sqrt(a11^3*a22^3*(a2*b1-a1*b2)^2*(b1^2+b2^2)^2*(a11*b1^2+a22*b2^2));
        denom=a11^2*a22^2*(b1^2+b2^2)^2;

        if(imag(sqrtTerm)~=0)
            %If there is some finite precision error.
            x=[];
            t=[];
            return
        end

        lambda(1)=(firstTerm+sqrtTerm)/denom;
        lambda(2)=(firstTerm-sqrtTerm)/denom;

        x=zeros(2,2);
        t=zeros(1,2);
        cost=zeros(2,1);
        constErr=zeros(2,1);
        for k=1:2
            denom=a22*b2^2+a11*(b1^2+a22*(b1^2+b2^2)*lambda(k));

            x(:,k)=[a22*b2*(a1*b2-a2*b1);a11*b1*(a2*b1-a1*b2)]/denom;
            t(k)=-(a2*a22*b2*(1+a11*lambda(k))+a1*a11*b1*(1+a22*lambda(k)))/denom;

            cost(k)=norm(a+b*t(k)-x);
            constErr(k)=abs(x(:,k)'*A*x(:,k)-1);
        end
        sel=(constErr<=epsConst);
        if(sum(sel)==0)
            %If nothing met the constraint.
            x=[];
            t=[];
            return
        end
        x=x(:,sel);
        t=t(sel);
        cost=cost(sel);

        [~,idx]=min(cost);

        x=x(:,idx);
        t=t(idx);
    case 3
        a11=A(1,1);
        a22=A(2,2);
        a33=A(3,3);

        a1=a(1);
        a2=a(2);
        a3=a(3);
        b1=b(1);
        b2=b(2);
        b3=b(3);

        c0=(a11*b1^2+a22*b2^2+a33*b3^2)*(a22*(-1+a3^2*a33)*b2^2-2*a2*a22*a3*a33*b2*b3+(-1+a2^2*a22)*a33*b3^2+a11*((-1+a2^2*a22+a3^2*a33)*b1^2-2*a1*b1*(a2*a22*b2+a3*a33*b3)+a1^2*(a22*b2^2+a33*b3^2)));
        c1=2*(a11*b1^2+a22*b2^2+a33*b3^2)*(-a11*a33*(b1^2+b3^2)-a22*a33*(b2^2+b3^2)+a11*a22*((-1+(a2^2+a3^2)*a33)*b1^2+(-1+(a1^2+a3^2)*a33)*b2^2-2*a2*a3*a33*b2*b3+(a1^2+a2^2)*a33*b3^2-2*a1*a33*b1*(a2*b2+a3*b3)));
        c2=(-a22^2*a33^2*(b2^2+b3^2)^2+a11^2*(-a33^2*(b1^2+b3^2)^2+a22^2*((-1+a3^2*a33)*(b1^2+b2^2)^2-2*a3*a33*(a1*b1+a2*b2)*(b1^2+b2^2)*b3+a33*(a1*b1+a2*b2)^2*b3^2)+a22*a33*((-4+a2^2*a33)*b1^4-2*a1*a2*a33*b1^3*b2+2*a1*a33*b1*b2*b3*(a3*b2-a2*b3)+b3^2*((-2+a3^2*a33)*b2^2-2*a2*a3*a33*b2*b3+a2^2*a33*b3^2)+b1^2*((-4+a1^2*a33)*b2^2-2*a2*a3*a33*b2*b3+2*(-2+a2^2*a33)*b3^2)))+a11*a22*a33*(-2*a33*(b1^2*b2^2+2*(b1^2+b2^2)*b3^2+2*b3^4)+a22*(-2*a1*a33*b1*(a2*b2+a3*b3)*(b2^2+b3^2)+(b2^2+b3^2)*((-4+a1^2*a33)*b2^2+a1^2*a33*b3^2)+b1^2*((-4+a2^2*a33)*b2^2+2*a2*a3*a33*b2*b3+(-2+a3^2*a33)*b3^2))));
        c3=-2*a11*a22*a33*(b1^2+b2^2+b3^2)*(a11*a22*(b1^2+b2^2)+a11*a33*(b1^2+b3^2)+a22*a33*(b2^2+b3^2));
        c4=-a11^2*(a22^2)*(a33^2)*((b1^2+b2^2+b3^2)^2);

        lambda=roots([c4;c3;c2;c1;c0]);
        lambda=lambda(imag(lambda)==0);
        numSol=length(lambda);

        if(numSol==0)
            %If there is some finite precision error. There should be two
            %solutions.
            x=[];
            t=[];
            return
        end

        x=zeros(3,numSol);
        t=zeros(1,numSol);
        cost=zeros(numSol,1);
        %Due to singularities, some solutions might not be correct. Thus,
        %we also evaluate the relative error for enforcing the constraint
        %and if the error is too high, those solutions are discarded.
        constErr=zeros(numSol,1);
        for k=1:numSol
            lambdaCur=lambda(k);
            denom=a22*b2^2+a33*b3^2+a22*a33*(b2^2+b3^2)*lambdaCur+a11*b1^2*(1+a22*lambdaCur)*(1+a33*lambdaCur)+a11*lambdaCur*(a33*b3^2+a22*(b2^2+a33*(b2^2+b3^2)*lambdaCur));
            x(:,k)=[-a3*a33*b1*b3*(1+a22*lambdaCur)-a2*a22*b1*b2*(1+a33*lambdaCur)+a1*(a22*b2^2+a33*b3^2+a22*a33*(b2^2+b3^2)*lambdaCur);
                     a11*b1*(a2*b1-a1*b2)+a33*b3*(-a3*b2+a2*b3)+a11*a33*(-b2*(a1*b1+a3*b3)+a2*(b1^2+b3^2))*lambdaCur;
                     a11*b1*(a3*b1-a1*b3)+a22*b2*(a3*b2-a2*b3)+a11*a22*(a3*(b1^2+b2^2)-(a1*b1+a2*b2)*b3)*lambdaCur]/denom;
            t(k)=-(a1*a11*b1*(1+a22*lambdaCur)*(1+a33*lambdaCur)+(1+a11*lambdaCur)*(a3*a33*b3*(1+a22*lambdaCur)+a2*a22*b2*(1+a33*lambdaCur)))/denom;
            cost(k)=norm(a+b*t(k)-x);
            constErr(k)=abs(x(:,k)'*A*x(:,k)-1);
        end
        sel=(constErr<=epsConst);
        if(sum(sel)==0)
            %If nothing met the constraint.
            x=[];
            t=[];
            return
        end
        x=x(:,sel);
        t=t(sel);
        cost=cost(sel);

        [~,idx]=min(cost);
        x=x(:,idx);
        t=t(idx);
    otherwise
        error('An unsupported dimensionality is being used.')
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 a = pascal1 ( n )

%*****************************************************************************80
%
%% PASCAL1 returns the PASCAL1 matrix.
%
%  Formula:
%
%    if ( J = 1 )
%      A(I,J) = 1
%    elseif ( I = 0 )
%      A(1,J) = 0
%    else
%      A(I,J) = A(I-1,J) + A(I-1,J-1)
%
%  Example:
%
%    N = 5
%
%    1  0  0  0  0
%    1  1  0  0  0
%    1  2  1  0  0
%    1  3  3  1  0
%    1  4  6  4  1
%
%  Properties:
%
%    A is a "chunk" of the Pascal binomial combinatorial triangle.
%
%    A is generally not symmetric: A' /= A.
%
%    A is nonsingular.
%
%    A is lower triangular.
%
%    A is integral, therefore det ( A ) is integral, and
%    det ( A ) * inverse ( A ) is integral.
%
%    det ( A ) = 1.
%
%    A is unimodular.
%
%    LAMBDA(1:N) = 1.
%
%    (0, 0, ..., 0, 1) is an eigenvector.
%
%    The inverse of A is the same as A, except that entries in "odd"
%    positions have changed sign:
%
%      B(I,J) = (-1)^(I+J) * A(I,J)
%
%    The product A*A' is a Pascal matrix
%    of the sort created by subroutine PASCAL2.
%
%    Let the matrix C have the same entries as A, except that
%    the even columns are negated.  Then Inverse(C) = C, and
%    C' * C = the Pascal matrix created by PASCAL2.
%
%    The family of matrices is nested as a function of N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Robert Gregory, David Karney,
%    Example 3.15,
%    A Collection of Matrices for Testing Computational Algorithms,
%    Wiley, 1969, page 43,
%    LC: QA263.G68.
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

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

      if ( j == 1 )
        a(i,j) = 1.0;
      elseif ( i == 1 )
        a(i,j) = 0.0;
      else
        a(i,j) = a(i-1,j-1) + a(i-1,j);
      end

    end
  end

  return
end


function fx = p46_fun ( n, x )

%*****************************************************************************80
%
%% P46_FUN evaluates the integrand for problem 46.
%
%  Discussion:
%
%    The problem has a parameter ALPHA that can be set by calling
%    P46_PARAM_SET.
%
%    The integrand is the radius of an ellipse as a function of angle.
%
%    The integral represents the arc length of the ellipse.
%
%    The suggested parameter range is 0.0 <= ALPHA < 1.0.  ALPHA is
%    the eccentricity of the ellipse.
%
%  Interval:
%
%    0 <= theta <= 2 pi
%
%  Integrand:
%
%    r(theta) = ( 1 - alpha^2 ) / ( 1 - alpha * cos ( theta ) )
%
%  Exact Integral:
%
%    When alpha = sin ( pi / 12 ), then
%
%      6.0690909595647754101
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 December 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Richard Crandall,
%    Projects in Scientific Computing,
%    Springer, 2000, page 47.
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N), the evaluation points.
%
%    Output, real FX(N), the integrand values.
%
%
  alpha = p46_param_get ( );

  fx(1:n) = ( 1.0 - alpha^2 ) ./ ( 1.0 - alpha * cos ( x(1:n) ) );

  return
end


function z = zernpol(n,m,r,nflag)
%ZERNPOL Radial Zernike polynomials of order N and frequency M.
%   Z = ZERNPOL(N,M,R) returns the radial Zernike polynomials of
%   order N and frequency M, evaluated at R.  N is a vector of
%   positive integers (including 0), and M is a vector with the
%   same number of elements as N.  Each element k of M must be a
%   positive integer, with possible values M(k) = 0,2,4,...,N(k)
%   for N(k) even, and M(k) = 1,3,5,...,N(k) for N(k) odd.  R is
%   a vector of numbers between 0 and 1.  The output Z is a matrix
%   with one column for every (N,M) pair, and one row for every
%   element in R.
%
%   Z = ZERNPOL(N,M,R,'norm') returns the normalized Zernike poly-
%   nomials.  The normalization factor Nnm = sqrt(2*(n+1)) is
%   chosen so that the integral of (r * [Znm(r)]^2) from r=0 to
%   r=1 is unity.  For the non-normalized polynomials, Znm(r=1)=1
%   for all [n,m].
%
%   The radial Zernike polynomials are the radial portion of the
%   Zernike functions, which are an orthogonal basis on the unit
%   circle.  The series representation of the radial Zernike
%   polynomials is
%
%          (n-m)/2
%            __
%    m      \       s                                          n-2s
%   Z(r) =  /__ (-1)  [(n-s)!/(s!((n-m)/2-s)!((n+m)/2-s)!)] * r
%    n      s=0
%
%   The following table shows the first 12 polynomials.
%
%       n    m    Zernike polynomial    Normalization
%       ---------------------------------------------
%       0    0    1                        sqrt(2)
%       1    1    r                           2
%       2    0    2*r^2 - 1                sqrt(6)
%       2    2    r^2                      sqrt(6)
%       3    1    3*r^3 - 2*r              sqrt(8)
%       3    3    r^3                      sqrt(8)
%       4    0    6*r^4 - 6*r^2 + 1        sqrt(10)
%       4    2    4*r^4 - 3*r^2            sqrt(10)
%       4    4    r^4                      sqrt(10)
%       5    1    10*r^5 - 12*r^3 + 3*r    sqrt(12)
%       5    3    5*r^5 - 4*r^3            sqrt(12)
%       5    5    r^5                      sqrt(12)
%       ---------------------------------------------
%
%   Example:
%
%       % Display three example Zernike radial polynomials
%       r = 0:0.01:1;
%       n = [3 2 5];
%       m = [1 2 1];
%       z = zernpol(n,m,r);
%       figure
%       plot(r,z)
%       grid on
%       legend('Z_3^1(r)','Z_2^2(r)','Z_5^1(r)','Location','NorthWest')
%
%   See also ZERNFUN, ZERNFUN2.

% A note on the algorithm.
% ------------------------
% The radial Zernike polynomials are computed using the series
% representation shown in the Help section above. For many special
% functions, direct evaluation using the series representation can
% produce poor numerical results (floating point errors), because
% the summation often involves computing small differences between
% large successive terms in the series. (In such cases, the functions
% are often evaluated using alternative methods such as recurrence
% relations: see the Legendre functions, for example). For the Zernike
% polynomials, however, this problem does not arise, because the
% polynomials are evaluated over the finite domain r = (0,1), and
% because the coefficients for a given polynomial are generally all
% of similar magnitude.
%
% ZERNPOL has been written using a vectorized implementation: multiple
% Zernike polynomials can be computed (i.e., multiple sets of [N,M]
% values can be passed as inputs) for a vector of points R.  To achieve
% this vectorization most efficiently, the algorithm in ZERNPOL
% involves pre-determining all the powers p of R that are required to
% compute the outputs, and then compiling the {R^p} into a single
% matrix.  This avoids any redundant computation of the R^p, and
% minimizes the sizes of certain intermediate variables.
%
%   Paul Fricker 11/13/2006

% Check and prepare the inputs:
% -----------------------------
if ( ~any(size(n)==1) ) || ( ~any(size(m)==1) )
    error('zernpol:NMvectors','N and M must be vectors.')
end

if length(n)~=length(m)
    error('zernpol:NMlength','N and M must be the same length.')
end

n = n(:);
m = m(:);
length_n = length(n);

if any(mod(n-m,2))
    error('zernpol:NMmultiplesof2','All N and M must differ by multiples of 2 (including 0).')
end

if any(m<0)
    error('zernpol:Mpositive','All M must be positive.')
end

if any(m>n)
    error('zernpol:MlessthanN','Each M must be less than or equal to its corresponding N.')
end

if any( r>1 | r<0 )
    error('zernpol:Rlessthan1','All R must be between 0 and 1.')
end

if ~any(size(r)==1)
    error('zernpol:Rvector','R must be a vector.')
end

r = r(:);
length_r = length(r);

if nargin==4
    isnorm = ischar(nflag) & strcmpi(nflag,'norm');
    if ~isnorm
        error('zernpol:normalization','Unrecognized normalization flag.')
    end
else
    isnorm = false;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute the Zernike Polynomials
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Determine the required powers of r:
% -----------------------------------
rpowers = [];
for j = 1:length(n)
    rpowers = [rpowers m(j):2:n(j)];
end
rpowers = unique(rpowers);

% Pre-compute the values of r raised to the required powers,
% and compile them in a matrix:
% -----------------------------
if rpowers(1)==0
    rpowern = arrayfun(@(p)r.^p,rpowers(2:end),'UniformOutput',false);
    rpowern = cat(2,rpowern{:});
    rpowern = [ones(length_r,1) rpowern];
else
    rpowern = arrayfun(@(p)r.^p,rpowers,'UniformOutput',false);
    rpowern = cat(2,rpowern{:});
end

% Compute the values of the polynomials:
% --------------------------------------
z = zeros(length_r,length_n);
for j = 1:length_n
    s = 0:(n(j)-m(j))/2;
    pows = n(j):-2:m(j);
    for k = length(s):-1:1
        p = (1-2*mod(s(k),2))* ...
                   prod(2:(n(j)-s(k)))/          ...
                   prod(2:s(k))/                 ...
                   prod(2:((n(j)-m(j))/2-s(k)))/ ...
                   prod(2:((n(j)+m(j))/2-s(k)));
        idx = (pows(k)==rpowers);
        z(:,j) = z(:,j) + p*rpowern(:,idx);
    end

    if isnorm
        z(:,j) = z(:,j)*sqrt(2*(n(j)+1));
    end
end

% EOF zernpol


function volume = sphere_imp_volume_nd ( dim_num, r )

%*****************************************************************************80
%
%% SPHERE_IMP_VOLUME_ND computes the volume of an implicit sphere in ND.
%
%  Discussion:
%
%    An implicit sphere in ND satisfies the equation:
%
%      sum ( ( X(1:N) - CENTER(1:N) )^2 ) = R^2
%
%    where R is the radius and CENTER is the center.
%
%    Results for the first few values of N are:
%
%    DIM_NUM  Volume
%    -     -----------------------
%    2                PI   * R^2
%    3     (4/3)    * PI   * R^3
%    4     (1/2)    * PI^2 * R^4
%    5     (8/15)   * PI^2 * R^5
%    6     (1/6)    * PI^3 * R^6
%    7     (16/105) * PI^3 * R^7
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the space.
%
%    Input, real R, the radius of the sphere.
%
%    Output, real VOLUME, the volume of the sphere.
%
  volume = r^dim_num * sphere_unit_volume_nd ( dim_num );

  return
end


function [ f, i ] = fibonacci_floor ( n )

%*****************************************************************************80
%
%% FIBONACCI_FLOOR returns the largest Fibonacci number less than or equal to N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the positive integer whose Fibonacci "floor" is desired.
%
%    Output, integer F, the largest Fibonacci number less than or equal to N.
%
%    Output, integer I, the index of the F.
%
  if ( n <= 0 )

    i = 0;
    f = 0;

  else

    i = floor ( log ( 0.5 * ( 2 * n + 1 ) * sqrt ( 5.0 ) ) ...
      / log ( 0.5 * ( 1.0 + sqrt ( 5.0 ) ) ) );

    f = fibonacci_direct ( i );

    if ( n < f )
      i = i - 1;
      f = fibonacci_direct ( i );
    end

  end

  return
end


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

% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));

% ====================== YOUR CODE HERE ======================
% Instructions: First, for each feature dimension, compute the mean
%               of the feature and subtract it from the dataset,
%               storing the mean value in mu. Next, compute the
%               standard deviation of each feature and divide
%               each feature by it's standard deviation, storing
%               the standard deviation in sigma.
%
%               Note that X is a matrix where each column is a
%               feature and each row is an example. You need
%               to perform the normalization separately for
%               each feature.
%
% Hint: You might find the 'mean' and 'std' functions useful.
%

for i = 1:size(X, 2)
	mu(:,i) = mean(X_norm(:,i));
	sigma(:,i) = std(X_norm(:,i));
	X_norm(:,i) = (X_norm(:,i) - mu(:,i)) / sigma(:,i);
end

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

end


function C=cofactorMatrix(A)
%%COFACTORMATRIX Compute the cofactor matrix of a square matrix A. The cofactor
%     matrix of a matrix A is one such that C(i,j)=(-1)^(i+j)det(A_{i,j}), where
%     A_{i,j} is the matrix A with row i and column j removed.
%
%INPUTS: A An nXn square matrix. The elements can be real or complex. The
%          matrix can be singular.
%
%OUTPUTS: C The nXn cofactor matrix of the matrix A.
%
%The adjugate of a matrix is defined in Ch. 4 of [1] as the transpose of the
%cofactor matrix C. This function just calls adj(A) to get the adjugate and then
%takes the transpose of the result.
%
%REFERENCES:
%[1] K. M. Abadir and J. R. Magnus, "Matrix algebra," New York, 2005.
%
%August 2020 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

C=adj(A)';

end