function value = zabs2 ( z )

%*****************************************************************************80
%
%% ZABS2 returns the L2 norm of a complex number.
%
%  Discussion:
%
%    The L2 norm of a complex number is the square root of the sum
%    of the squares of the real and imaginary components.
%
%    ZABS2 ( Z ) = sqrt ( ( real ( Z ) )**2 + ( imaginary ( Z ) )**2 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 May 2006
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Cleve Moler, Jim Bunch, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979.
%
%    Charles Lawson, Richard Hanson, David Kincaid, Fred Krogh,
%    Basic Linear Algebra Subprograms for FORTRAN usage,
%    ACM Transactions on Mathematical Software,
%    Volume 5, Number 3, pages 308-323, 1979.
%
%  Parameters:
%
%    Input, complex Z, the number whose norm is desired.
%
%    Output, real VALUE, the L2 norm of Z.
%
  value = sqrt ( ( real ( z ) ).^2 + ( imag ( z ) ).^2 );

  return
end


function verifyquadpts
%% VERIFYQUADPTS examples and verfication on quadrature rules.
%
%  error = verifyquadpts(n) computes the error of n-th order quadrature
%  rule in a triangle. This is an example on the usage of quadrature points
%  and verification of qudarture order for approximating integrals in a
%  triangle.
%
% See also quadpts
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

% a reference triangle
node = [0 0; 1 0; 0 1];
elem = [1 2 3];
area = 0.5;
err = zeros(9,2);
for n = 1:9
    % get quadrature points
    [lambda,weight] = quadpts(n);
    nQuad = size(lambda,1);
    t1 = 0;
    t2 = 0;
    for p = 1:nQuad
        % quadrature points in the x-y coordinate
        pxy = lambda(p,1)*node(elem(:,1),:) ...
            + lambda(p,2)*node(elem(:,2),:) ...
            + lambda(p,3)*node(elem(:,3),:);
        t1 = t1 + weight(p)*f1(pxy(1),pxy(2),n);
        t2 = t2 + weight(p)*f2(pxy(1),pxy(2));
    end
    t1 = t1*area;
    t2 = t2*area;
    err(n,1) = abs(t1 - 2/((n+1)*(n+2)));
    err(n,2) = abs(t2 - (sin(1) - cos(1)));
end
display('Table: Error of quadrature for two smooth functions')
colname = {'n','x^n + y^n','sin(x+y)'};
disptable(colname,(1:9)',[],err(:,1),'%0.5e',err(:,2),'%0.5e');
end

function z = f1(x,y,n)
z = x.^n + y.^n;
end

function z = f2(x,y)
z = sin(x+y);
end

%% Results
% Let T be the triangle formed by (0,0), (1,0), and (0,1).
%
% Error1 is for the integral
% $\int _{T} x^n + y^n \, dxdy$.
% It should be numerically exact.
%
% Error2 is for the integral
% $\int _{T} \sin(x+y) \, dxdy$.
% It decays as n increas.
%
% See the doc for qudrature rules in <matlab:ifemdoc('quadpts') quadpts>.


function [ht, rho, theta] = hough(IM, f, t, M, N)
% HOUGH Hough transform for detection lines in images.
% [HT,RHO,THETA] = HOUGH(IM,M,N).
% From an image IM, computes the integration of the values
% of the image over all the lines. The origin of the coordinates is
% in the middle of x axis (-250<=x<250, 0<=y<=1). The formula for the
% transform is rho = x*cos(theta) + y*sin(theta). Only the values of IM exceeding 5 % of the maximum
%	are taken into account (to speed up the algorithm).
%
%	IM    : image to be analyzed (size Xmax x Ymax).
%	M     : desired number of samples along the radial axis
%					(default : Xmax).
%	N     : desired number of samples along the azimutal (angle) axis
%					(default : Ymax).
%	HT    : output matrix (MxN matrix).
%	RHO   : sequence of samples along the radial axis.
%	THETA : sequence of samples along the azimutal axis.

if (nargin < 3 ),
 error('At least three parameters required');
end;
[Xmax,Ymax] = size(IM);

if (nargin == 3),
M = Xmax; N = Ymax;
elseif (nargin == 4),
N=Ymax;
end;

rhomax = sqrt(Xmax^2 + Ymax^2)/2;
deltar=rhomax/(M-1);
deltat=2*pi/N;

ht=zeros(M,N);
Max=max(max(IM));
for x = 0:Xmax-1,
    for y = 0:Ymax-1,
        if abs(IM(x+1,y+1))>Max/20,
            for theta = 0:deltat:(2*pi-deltat),
                 rho = x*cos(theta) + y*sin(theta);
                if ((rho>=0)&&(rho<=rhomax)),
                    ht(round(rho/deltar)+1,round(theta/deltat)+1) =...
                        ht(round(rho/deltar)+1,round(theta/deltat)+1)+...
                        IM(x+1,y+1);
                end
            end
        end
    end
end
rho=0:deltar:rhomax;
theta=0:deltat:(2*pi-deltat);


function r=ellipsoidalRadius(el,elType,a,f)
%%ELLIPSOIDALRADIUS Find the distance from the center of an axis-aligned
%           oblate spheroid, as is used to approximate the shape of the
%           Earth, to a point on the surface of the spheroid as a function
%           of the (spherical) elevation angle above the equatorial plane
%           or as a function of the ellipsoidal latitude.
%
%INPUTS: el A point or a matrix of the elevation points for which one wants
%           to find radii. The points are in radians. The next parameter
%           sets the type of points.
%    elType An optional parameter specifying the type of elevation el is.
%           Possible values are:
%           0 (The default if omitted or an empty matrix is passed)
%             Geocentric elevations (as in spherical cooridinates).
%           1 Geodetic (ellipsoidal) latitudes.
%         a The semi-major axis of the reference ellipsoid. If this
%           argument is omitted, the value in Constants.WGS84SemiMajorAxis
%           is used.
%         f The flattening factor of the reference ellipsoid. If this
%           argument is omitted, the value in Constants.WGS84Flattening is
%           used.
%
%OUTPUTS: r A matrix of the radii corresponding to the values in el.
%
%The formula for the radius as a function of spherical elevation is taken
%from Section 3.2 of [1].
%
%REFERENCES:
%[1] C. Hirt and M. Rexer, "Earth2014: 1 arc-min shape, topography, bedrock
%    and ice-sheet models - available as gridded data and degree - 10,800
%    spherical harmonics," International Journal of Applied Earth
%    Observation and Geoinformation, vol. 39, pp. 103-112, Jul. 2015.
%
%June 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

if(nargin<3||isempty(a))
   a=Constants.WGS84SemiMajorAxis;
end

if(nargin<4||isempty(f))
   f=Constants.WGS84Flattening;
end

b=a*(1-f);%Semi-minor axis
e2=(a^2-b^2)/a^2;%eccentricity squared

if(elType==0)
    %We need the square of the sine of the ellipsoidal latitude. However,
    %we only have the spherical elevation. Here, we just substituted the
    %formula from spherLat2EllipsLat into the square of the sine and
    %simplified to get the following formula in terms of the squared
    %tangent.
    spherLat=wrapRange(el,-pi/2,pi/2,true);
    sinEl2=1-1./(1+(1/(1-e2))^2*tan(spherLat).^2);
else
    sinEl2=sin(el).^2;
end

r=a*sqrt((1-e2*(2-e2)*sinEl2)./(1-e2*sinEl2));

end

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


function value = i4_log_10 ( i )

%*****************************************************************************80
%
%% I4_LOG_10 returns the integer part of the logarithm base 10 of ABS(X).
%
%  Example:
%
%        I  VALUE
%    -----  --------
%        0    0
%        1    0
%        2    0
%        9    0
%       10    1
%       11    1
%       99    1
%      100    2
%      101    2
%      999    2
%     1000    3
%     1001    3
%     9999    3
%    10000    4
%
%  Discussion:
%
%    I4_LOG_10 ( I ) + 1 is the number of decimal digits in I.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 January 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, the number whose logarithm base 10 is desired.
%
%    Output, integer VALUE, the integer part of the logarithm base 10 of
%    the absolute value of X.
%
  i = floor ( i );

  if ( i == 0 )

    value = 0;

  else

    value = 0;
    ten_pow = 10;

    i_abs = abs ( i );

    while ( ten_pow <= i_abs )
      value = value + 1;
      ten_pow = ten_pow * 10;
    end

  end

  return
end


%% Fun with remap
% Maps a rectangular image into a circle using cv.remap
%
% To build the mapping we do the following simple geometry calculation:
%
% * shift the origin (0,0) coordinate to the center of the image
% * convert the cartesian x-y coordinates to polar r-theta form
% * determine the length of the line with the same theta that touches the
%   border of the rectangle
% * retain the theta, but scale the r value based on how much the line has to
%   shrink to fit into the circle.
% * convert the modified r-theta values back into x-y coordinates
%
% Sources:
%
% * <http://sidekick.windforwings.com/2012/12/opencv-fun-with-remap.html>
%

%%
% source image
fname = which('coins.png');
if isempty(fname)
    fname = fullfile(mexopencv.root(), 'test', 'apple.jpg');
end
src = imread(fname);

%%
% coordinates space, shifted so that origin is at the center of the image
[h,w,~] = size(src);
c = [w,h] / 2;
[X,Y] = meshgrid(single(1:w)-c(1), single(1:h)-c(2));

%%
% convert cartesian coordinates to polar form (r,theta)
R = hypot(Y,X);
T = atan(Y./X);  % NOTE: atan not atan2

% handle NaN case when atan(0/0) in the center
T(isnan(T)) = 0;

%%
% scale R
radius = min(h,w) / 2;
D = min(abs(c(1)./cos(T)), abs(c(2)./sin(T)));
R = R ./ (radius ./ D);

%%
% remap points
map_X = c(1) + sign(X) .* R .* cos(abs(T));
map_Y = c(2) + sign(Y) .* R .* sin(abs(T));

%%
% destination image
dst = cv.remap(src, map_X, map_Y);

%%
% show result
subplot(121), imshow(src), title('image')
subplot(122), imshow(dst), title('remapped')


function area = triangle_area_heron ( s )

%*****************************************************************************80
%
%% TRIANGLE_AREA_HERON computes the area of a triangle using Heron's formula.
%
%  Discussion:
%
%    The formula is valid for any spatial dimension, depending only
%    on the lengths of the sides, and not the coordinates of the vertices.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real S(3,1), the lengths of the three sides.
%
%    Output, real AREA, the area of the triangle, or -1.0 if the
%    sides cannot constitute a triangle.
%
  area = (   s(1,1) + s(2,1) + s(3,1) ) ...
       * ( - s(1,1) + s(2,1) + s(3,1) ) ...
       * (   s(1,1) - s(2,1) + s(3,1) ) ...
       * (   s(1,1) + s(2,1) - s(3,1) );

  if ( area < 0.0 )
    area = -1.0;
    return
  end

  area = 0.25 * sqrt ( area );

  return
end


function y = norm_pdf(x,mu,sigma)
%NORM_PDF Normal probability density function (pdf).
%
%   Y = NORMPDF(X,MU,SIGMA) Returns the normal pdf with
%   mean, MU, and standard deviation, SIGMA, at the values in X.
%
%   The size of X is the common size of the input arguments. A scalar input
%   functions as a constant matrix of the same size as the other inputs.
%
%   Default values for MU and SIGMA are 0 and 1 respectively.

% Copyright (c) 1998-2004 Aki Vehtari

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

if nargin < 3,
  sigma = 1;
end

if nargin < 2;
  mu = 0;
end

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

y = exp(-0.5 * ((x-mu)./sigma).^2 -log(sigma) -log(2*pi)/2);


% Quadratic discrimination (separating ellipsoid)
% Section 8.6.2, Boyd & Vandenberghe "Convex Optimization"
% Original by Lieven Vandenberghe
% Adapted for CVX by Joelle Skaf - 10/16/05
% (a figure is generated)
%
% The goal is to find an ellipsoid that contains all the points
% x_1,...,x_N but none of the points y_1,...,y_M. The equation of the
% ellipsoidal surface is: z'*P*z + q'*z + r =0
% P, q and r can be obtained by solving the SDP feasibility problem:
%           minimize    0
%               s.t.    x_i'*P*x_i + q'*x_i + r >=  1   for i = 1,...,N
%                       y_i'*P*y_i + q'*y_i + r <= -1   for i = 1,...,M
%                       P <= -I

% data generation
n = 2;
rand('state',0);
randn('state',0);
N=50;
X = randn(2,N);  X = X*diag(0.99*rand(1,N)./sqrt(sum(X.^2)));
Y = randn(2,N);  Y = Y*diag((1.02+rand(1,N))./sqrt(sum(Y.^2)));
T = [1 -1; 2 1];  X = T*X;  Y = T*Y;

% Solution via CVX
fprintf(1,'Find the optimal ellipsoid that seperates the 2 classes...');

cvx_begin sdp
    variable P(n,n) symmetric
    variables q(n) r(1)
    P <= -eye(n); %#ok
    sum((X'*P).*X',2) + X'*q + r >= +1; %#ok
    sum((Y'*P).*Y',2) + Y'*q + r <= -1; %#ok
cvx_end

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

% Displaying results
r = -r; P = -P; q = -q;
Pq = P \ q;
c = 0.25*q'*Pq - r;
xc = -0.5*Pq;
nopts = 1000;
angles = linspace(0,2*pi,nopts);
ell = sqrtm(P/c)\[cos(angles); sin(angles)] + repmat(xc,1,nopts);
graph=plot(X(1,:),X(2,:),'o', Y(1,:), Y(2,:),'o', ell(1,:), ell(2,:),'-');
set(graph(2),'MarkerFaceColor',[0 0.5 0]);
set(gca,'XTick',[]); set(gca,'YTick',[]);
title('Quadratic discrimination');
% print -deps ellips.eps


function c=zak(f,a);
%ZAK  Zak transform
%   Usage:  c=zak(f,a);
%
%   `zak(f,a)` computes the Zak transform of *f* with parameter *a*.  The
%   coefficients are arranged in an $a \times L/a$ matrix, where *L* is the
%   length of *f*.
%
%   If *f* is a matrix then the transformation is applied to each column.
%   This is then indexed by the third dimension of the output.
%
%   Assume that $c=zak(f,a)$, where *f* is a column vector of length *L* and
%   $N=L/a$. Then the following holds for $m=0,\ldots,a-1$ and $n=0,\ldots,N-1$
%
%   ..                     N-1
%     c(m+1,n+1)=1/sqrt(N)*sum f(m-k*a+1)*exp(2*pi*i*n*k/N)
%                          k=0
%
%   .. math:: c(m+1,n+1) = \frac{1}{\sqrt{N}}\sum_{k=0}^{N-1}f(m-ka+1)e^{2\pi ink/M}
%
%   Examples:
%   ---------
%
%   This figure shows the absolute value of the Zak-transform of a Gaussian.
%   Notice that the Zak-transform is 0 in only a single point right in the
%   middle of the plot :::
%
%     a=64;
%     L=a^2;
%     g=pgauss(L);
%     zg=zak(g,a);
%
%     surf(abs(zg));
%
%   This figure shows the absolute value of the Zak-transform of a 4th order
%   Hermite function.  Notice how the Zak transform of the Hermite functions
%   is zero on a circle centered on the corner :::
%
%     a=64;
%     L=a^2;
%     g=pherm(L,4);
%     zg=zak(g,a);
%
%     surf(abs(zg));
%
%   See also:  izak
%
%   References: ja94-4 bohl97-1

%   AUTHOR : Peter L. Søndergaard
%   TESTING: TEST_ZAK
%   REFERENCE: REF_ZAK

complainif_argnonotinrange(nargin,2,2,mfilename);

if (prod(size(a))~=1 || ~isnumeric(a))
  error([callfun,': a must be a scalar']);
end;

if rem(a,1)~=0
  error([callfun,': a must be an integer']);
end;

if size(f,2)>1 && size(f,1)==1
  % f was a row vector.
  f=f(:);
end;

L=size(f,1);
W=size(f,2);
N=L/a;

if rem(N,1)~=0
  error('The parameter for ZAK must divide the length of the signal.');
end;

c=zeros(a,N,W,assert_classname(f));

for ii=1:W
  % Compute it, it can be done in one line!
  % We use a normalized DFT, as this gives the correct normalization
  % of the Zak transform.
  c(:,:,ii)=dft(reshape(f(:,ii),a,N),[],2);
end;


function x = line_grid ( n, a, b, c )

%*****************************************************************************80
%
%% LINE_GRID: grid points over the interior of a line segment in 1D.
%
%  Discussion:
%
%    In 1D, a grid is created using N points.
%
%    Over the interval [A,B], we have 5 choices for grid centering:
%      1: 0,   1/3, 2/3, 1
%      2: 1/5, 2/5, 3/5, 4/5
%      3: 0,   1/4, 2/4, 3/4
%      4: 1/4, 2/4, 3/4, 1
%      5: 1/8, 3/8, 5/8, 7/8
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 August 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points.
%
%    Input, real A, B, the endpoints for each dimension.
%
%    Input, integer C, the grid centering for each dimension.
%    1 <= C <= 5.
%
%    Output, real X(N), the points.
%

%
%  Create the 1D grids in each dimension.
%
  x = zeros ( n, 1 );

  for j = 1 : n

    if ( c == 1 )

      if ( n == 1 )
        x(j) = 0.5 * ( a + b );
      else
        x(j) = (   ( n - j     ) * a   ...
                 + (     j - 1 ) * b ) ...
                 / ( n     - 1 );
      end
    elseif ( c == 2 )
      x(j) = (   ( n - j + 1 ) * a   ...
               + (     j     ) * b ) ...
               / ( n     + 1 );
    elseif ( c == 3 )
      x(j) = (   ( n - j + 1 ) * a   ...
               + (     j - 1 ) * b ) ...
               / ( n         );
    elseif ( c == 4 )
      x(j) = (   ( n - j ) * a   ...
               + (     j ) * b ) ...
               / ( n     );
    elseif ( c == 5 )
      x(j) = (   ( 2 * n - 2 * j + 1 ) * a   ...
               + (         2 * j - 1 ) * b ) ...
               / ( 2 * n             );
    end

  end

  return
end


function geometry_test1746 ( )

%*****************************************************************************80
%
%% TEST1746 tests R8MAT_INVERSE_3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2005
%
%  Author:
%
%    John Burkardt
%
  n = 3;

  a = [ ...
    3.0, 2.0, 0.0; ...
    2.0, 2.0, 1.0; ...
    1.0, 1.0, 1.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST1746\n' );
  fprintf ( 1, '  R8MAT_INVERSE_3D inverts a 3 by 3 matrix.\n' );

  r8mat_print ( n, n, a, '  Matrix A:' );

  [ b, det ] = r8mat_inverse_3d ( a );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Determinant of A is %f\n', det );

  r8mat_print ( n, n, b, '  Inverse matrix B:' );

  return
end


function A = vandermonde_interp_1d_matrix ( n, x )

%*****************************************************************************80
%
%% VANDERMONDE_INTERP_1D_MATRIX computes a Vandermonde 1D interpolation matrix.
%
%  Discussion:
%
%    We assume the interpolant has the form
%
%      p(x) = c1 + c2 * x + c3 * x^2 + ... + cn * x^(n-1).
%
%    We have n data values (x(i),y(i)) which must be interpolated:
%
%      p(x(i)) = c1 + c2 * x(i) + c3 * x(i)^2 + ... + cn * x(i)^(n-1) = y(i)
%
%    This can be cast as an NxN linear system for the polynomial
%    coefficients:
%
%      [ 1 x1 x1^2 ... x1^(n-1) ] [  c1 ] = [  y1 ]
%      [ 1 x2 x2^2 ... x2^(n-1) ] [  c2 ] = [  y2 ]
%      [ ...................... ] [ ... ] = [ ... ]
%      [ 1 xn xn^2 ... xn^(n-1) ] [  cn ] = [  yn ]
%
%    and if the x values are distinct, the matrix A is theoretically
%    invertible (though in fact, generally badly conditioned).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 July 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of data points.
%
%    Input, real X(N,1), the data values.
%
%    Output, real A(N,N), the Vandermonde matrix for X.
%
  A = ( x(1:n,1) * ones(1,n) ) .^ ( ones(n,1) * (0:n-1) );

  return
end


function [ x, ierror ] = congruence ( a, b, c )

%*****************************************************************************80
%
%% CONGRUENCE solves a congruence of the form A * X = C ( mod B ).
%
%  Discussion:
%
%    A, B and C are given integers.  The equation is solvable if and only
%    if the greatest common divisor of A and B also divides C.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Eric Weisstein, editor,
%    CRC Concise Encylopedia of Mathematics,
%    CRC Press, 1998, page 446.
%
%  Parameters:
%
%    Input, integer A, B, C, the coefficients of the Diophantine equation.
%
%    Output, integer X, the solution of the Diophantine equation.
%    X will be between 0 and B-1.
%
%    Output, integer IERROR, error flag.
%    0, no error, X was computed.
%    1, A = B = 0, C is nonzero.
%    2, A = 0, B and C nonzero, but C is not a multiple of B.
%    3, A nonzero, B zero, C nonzero, but C is not a multiple of A.
%    4, A, B, C nonzero, but GCD of A and B does not divide C.
%    5, algorithm ran out of internal space.
%
  nmax = 100;
%
%  Defaults for output parameters.
%
  ierror = 0;
  x = 0;
  y = 0;
%
%  Special cases.
%
  if ( a == 0 & b == 0 & c == 0 )
    x = 0;
    return
  elseif ( a == 0 & b == 0 & c ~= 0 )
    ierror = 1;
    x = 0;
    return
  elseif ( a == 0 & b ~= 0 & c == 0 )
    x = 0;
    return
  elseif ( a == 0 & b ~= 0 & c ~= 0 )
    x = 0;
    if ( mod ( c, b ) ~= 0 )
      ierror = 2;
    end
    return
  elseif ( a ~= 0 & b == 0 & c == 0 )
    x = 0;
    return
  elseif ( a ~= 0 & b == 0 & c ~= 0 )
    x = c / a;
    if ( mod ( c, a ) ~= 0 )
      ierror = 3;
    end
    return
  elseif ( a ~= 0 & b ~= 0 & c == 0 )
%   g = i4_gcd ( a, b );
%   x = b / g;
    x = 0;
    return
  end
%
%  Now handle the "general" case: A, B and C are nonzero.
%
%  Step 1: Compute the GCD of A and B, which must also divide C.
%
  g = i4_gcd ( a, b );

  if ( mod ( c, g ) ~= 0 )
    ierror = 4;
    return
  end

  a_copy = a / g;
  b_copy = b / g;
  c_copy = c / g;
%
%  Step 2: Split A and B into sign and magnitude.
%
  a_mag = abs ( a_copy );
  a_sign = i4_sign ( a_copy );
  b_mag = abs ( b_copy );
  b_sign = i4_sign ( b_copy );
%
%  Another special case, A_MAG = 1 or B_MAG = 1.
%
  if ( a_mag == 1 )
    x = a_sign * c_copy;
    return
  elseif ( b_mag == 1 )
    x = 0;
    return
  end
%
%  Step 3: Produce the Euclidean remainder sequence.
%
  if ( b_mag <= a_mag )

    swap = 0;
    q(1) = a_mag;
    q(2) = b_mag;

  else

    swap = 1;
    q(1) = b_mag;
    q(2) = a_mag;

  end

  n = 3;

  while ( 1 )

    q(n) = mod ( q(n-2), q(n-1) );

    if ( q(n) == 1 )
      break;
    end

    n = n + 1;

    if ( nmax < n )
      ierror = 5;
      fprintf ( 1, '\n' );
      fprintf ( 1, 'CONGRUENCE - Fatal error!\n' );
      fprintf ( 1, '  Exceeded number of iterations.\n' );
      error ( 'CONGRUENCE - Fatal error!' );
    end

  end
%
%  Step 4: Now go backwards to solve X * A_MAG + Y * B_MAG = 1.
%
  y = 0;
  for k = n : -1 : 2
    x = y;
    y = ( 1 - x * q(k-1) ) / q(k);
  end
%
%  Step 5: Undo the swapping.
%
  if ( swap )
    z = x;
    x = y;
    y = z;
  end
%
%  Step 6: Now apply signs to X and Y so that X * A + Y * B = 1.
%
  x = x * a_sign;
%
%  Step 7: Multiply by C, so that X * A + Y * B = C.
%
  x = x * c_copy;
%
%  Step 8: Now force 0 <= X < B.
%
  x = mod ( x, b );
%
%  Step 9: Force positivity.
%
  if ( x < 0 )
    x = x + b;
  end

  return
end


function F = bst_window( Method, L, R )
% BST_WINDOW: Generate a window of length L, ot the given type: hann, hamming, blackman, parzen, tukey
%
% USAGE:  F = bst_window( Method, L, R )
%
% References:
%    Formulas documented on Wikipedia: http://en.wikipedia.org/wiki/Window_function

% @=============================================================================
% This function is part of the Brainstorm software:
% https://neuroimage.usc.edu/brainstorm
%
% Copyright (c) University of Southern California & McGill University
% This software is distributed under the terms of the GNU General Public License
% as published by the Free Software Foundation. Further details on the GPLv3
% license can be found at http://www.gnu.org/copyleft/gpl.html.
%
% FOR RESEARCH PURPOSES ONLY. THE SOFTWARE IS PROVIDED "AS IS," AND THE
% UNIVERSITY OF SOUTHERN CALIFORNIA AND ITS COLLABORATORS DO NOT MAKE ANY
% WARRANTY, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, NOR DO THEY ASSUME ANY
% LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE.
%
% For more information type "brainstorm license" at command prompt.
% =============================================================================@
%
% Authors: Francois Tadel, 2013-2014

% Parse inputs
if (nargin < 3) || isempty(R)
    R = [];
end
if (nargin < 2) || isempty(L)
    L = 64;
end
if (nargin < 1) || isempty(Method)
    Method = 'hann';
end
% Calculate normalized time vector
t = (0:L-1)' ./ (L-1);
% Switch according to windowing method
switch (lower(Method))
    case 'hann'
        F = 0.5 - 0.5 * cos(2*pi*t);
    case 'hamming'
        F = 0.54 - 0.46 * cos(2*pi*t);
    case 'blackman'
        F = 0.42 - 0.5 * cos(2*pi*t) + 0.08 * cos(4*pi*t);
    case 'tukey'
        % Tukey window = tapered cosine window, cosine lobe of width aL/2
        if isempty(R)
            R = 0.5;
        end
        a = R;
        % If a=0: square function
        if (a <= 0)
            F = ones(L,1);
        % If a=1: Hann window
        elseif (a >= 1)
            F = bst_window('hann', L);
        % Else: Function in three blocks
        else
            % Define three blocks
            len = floor(a*(L-1)/2) + 1;
            t1 = t(1:len);
            t3 = t(L-len+1:end);
            % Window is defined in three sections: taper, constant, taper
            F = [ 0.5 * (1 + cos(pi * (2*t1/a - 1)));  ...
                  ones(L-2*len,1); ...
                  0.5 * (1 + cos(pi * (2*t3/a - 2/a + 1)))];
        end
    case 'parzen'
        % Reference:
        % Harris FJ, On the Use of Windows for Harmonic Analysis with the Discrete Fourier Transform,
        % Proceedings of IEEE, Vol. 66, No. 1, January 1978   [Equation 37]

        % Time indices
        t = -(L-1)/2 : (L-1)/2;
        i1 = find(abs(t) <= (L-1)/4);  %   0 <= |n| <= N/4
        i2 = find(abs(t) >  (L-1)/4);  % N/4 <  |n| <  N/2

        % Definition of the Parzen window: 2 parts
        F = zeros(length(t), 1);
        F(i1) = 1 - 6 .* (t(i1)/L*2).^2 .* (1 - abs(t(i1))/L*2);
        F(i2) = 2 .* (1 - abs(t(i2))/L*2) .^3;

    otherwise
        error(['Unsupported windowing method: "' Method '".']);
end


function value = agud ( g )

%*****************************************************************************80
%
%% AGUD evaluates the inverse Gudermannian function.
%
%  Discussion:
%
%    The Gudermannian function relates the hyperbolic and trigonomentric
%    functions.  For any argument X, there is a corresponding value
%    G so that
%
%      SINH(X) = TAN(G).
%
%    This value G(X) is called the Gudermannian of X.  The inverse
%    Gudermannian function is given as input a value G and computes
%    the corresponding value X.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real G, the value of the Gudermannian.
%
%    Output, real VALUE, the argument of the Gudermannian.
%
  value = log ( tan ( 0.25 * pi + 0.5 * g ) );

  return
end


function [ mX ] = ProjectPosSemiDefinite( mY, numIterations, stopTol )
% ----------------------------------------------------------------------------------------------- %
% [ mX ] = ProjectPosSemiDefinite( mY, numIterations, stopTol )
%   Solves \arg \min_{X} 0.5 || X - Y ||, s.t. X \in \mathcal{S}_{+}^{n} by
%   Iterative Projection onto the set of Symmetric Matrices and PSD
%   Matrices.
% Input:
%   - mY            -   Input Matrix.
%                       Input model matrix.
%                       Structure: Matrix (m x n).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
%   - numIterations -   Number of Iterations.
%                       Sets the number of iterations for the algorithm to
%                       run.
%                       Structure: Scalar.
%                       Type: 'Single' / 'Double'.
%                       Range {1, 2, ...}.
%   - stopTol       -   Stopping Condition Tolerance.
%                       Sets the stopping threshold for the L Inf (Maximum
%                       Absolute Value) of the change between 2 iterations
%                       of the algorithm.
%                       Structure: Scalar.
%                       Type: 'Single' / 'Double'.
%                       Range [0, inf).
% Output:
%   - mX            -   Solution Matrix.
%                       A PSD Symmetric matrix which is the closest in
%                       Frobenius Norm sense to 'mY'.
%                       Structure: Matrix (m x n).
%                       Type: 'Single' / 'Double'.
%                       Range: (-inf, inf).
% References
%   1.  A
% Remarks:
%   1.  Since both the Symmetric Matrices Set and the PSD Matrices Set are
%       sub spaces the iterative (POCS) projection onto each is the
%       orthogonal projection onto the intersection. See https://math.stackexchange.com/questions/1492095.
% TODO:
%   1.  C
% Release Notes:
%   -   1.0.000     12/04/2020  Royi Avital
%       *   First release version.
% ----------------------------------------------------------------------------------------------- %

FALSE   = 0;
TRUE    = 1;

OFF     = 0;
ON      = 1;

vectorMode = OFF;

if(size(mY, 2) == 1)
    numRows     = sqrt(size(mY, 1));
    vectorMode  = ON;
    mX          = reshape(mY, numRows, numRows);
else
    numRows = size(mY, 1);
    mX      = mY;
end

mQ      = zeros(numRows, numRows);
mD      = zeros(numRows, numRows);
mXPrev  = mX;

for ii = 1:numIterations
    % Projection onto Symmetric Matrices Set
    mX(:) = (mX.' + mX) / 2;

    % Projection onto PSD Matrices Set
    [mQ(:), mD(:)] = eig(mX);
    mD(:) = max(mD, 0);
    mX(:) = mQ * mD * mQ.';

    if(max(abs(mX(:) - mXPrev(:))) <= stopTol)
        break;
    end

    mXPrev(:) = mX;

end

if(vectorMode == ON)
    mX = mX(:);
end

end


function verifyquadpts
%% VERIFYQUADPTS examples and verfication on quadrature rules.
%
%  error = verifyquadpts(n) computes the error of n-th order quadrature
%  rule in a triangle. This is an example on the usage of quadrature points
%  and verification of qudarture order for approximating integrals in a
%  triangle.
%
% See also quadpts
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

% a reference triangle
node = [0 0; 1 0; 0 1];
elem = [1 2 3];
area = 0.5;
err = zeros(9,2);
for n = 1:9
    % get quadrature points
    [lambda,weight] = quadpts(n);
    nQuad = size(lambda,1);
    t1 = 0;
    t2 = 0;
    for p = 1:nQuad
        % quadrature points in the x-y coordinate
        pxy = lambda(p,1)*node(elem(:,1),:) ...
            + lambda(p,2)*node(elem(:,2),:) ...
            + lambda(p,3)*node(elem(:,3),:);
        t1 = t1 + weight(p)*f1(pxy(1),pxy(2),n);
        t2 = t2 + weight(p)*f2(pxy(1),pxy(2));
    end
    t1 = t1*area;
    t2 = t2*area;
    err(n,1) = abs(t1 - 2/((n+1)*(n+2)));
    err(n,2) = abs(t2 - (sin(1) - cos(1)));
end
ts = zeros(9,3); ts = char(ts);
display('n     x^n + y^n     sin(x+y)');
display([num2str((1:9)') ts num2str(err(:,1),'%0.5e') ts num2str(err(:,2),'%0.5e')]);
end

function z = f1(x,y,n)
z = x.^n + y.^n;
end

function z = f2(x,y)
z = sin(x+y);
end

%% Results
% Let T be the triangle formed by (0,0), (1,0), and (0,1).
%
% Error1 is for the integral
% $\int _{T} x^n + y^n \, dxdy$.
% It should be numerically exact.
%
% Error2 is for the integral
% $\int _{T} \sin(x+y) \, dxdy$.
% It decays as n increas.
%
% See the doc for qudrature rules in <matlab:ifemdoc('quadpts') quadpts>.


function theta = lines_imp_angle_2d ( a1, b1, c1, a2, b2, c2 )

%*****************************************************************************80
%
%% LINES_IMP_ANGLE_2D finds the angle between two implicit lines in 2D.
%
%  Discussion:
%
%    The implicit form of a line in 2D is:
%
%      A * X + B * Y + C = 0
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Adrian Bowyer and John Woodwark,
%    A Programmer's Geometry,
%    Butterworths, 1983.
%
%  Parameters:
%
%    Input, real A1, B1, C1, the implicit parameters of the
%    first line.
%
%    Input, real A2, B2, C2, the implicit parameters of the
%    second line.
%
%    Output, real THETA, the angle between the two lines.
%
  pdotq = a1 * a2 + b1 * b2;
  pnorm = sqrt ( a1 * a1 + b1 * b1 );
  qnorm = sqrt ( a2 * a2 + b2 * b2 );

  theta = r8_acos ( pdotq / ( pnorm * qnorm ) );

  return
end


function [inter, inside]= intersectRayPolygon3d(ray, poly)
%INTERSECTRAYPOLYGON3D Intersection point of a 3D ray and a 3D polygon
%
%   INTER = intersectRayPolygon3d(RAY, POLY)
%   Compute coordinates of intersection point between the 3D ray RAY and
%   the 3D polygon POLY. RAY is a 1-by-6 row vector containing origin and
%   direction vector of the ray, POLY is a Np-by-3 array containing
%   coordinates of 3D polygon vertices.
%   INTER is a 1-by-3 row vector containing coordinates of intersection
%   point, or [NaN NaN NaN] if ray and polygon do not intersect.
%
%   INTERS = intersectRayPolygon3d(RAYS, POLY)
%   If RAYS is a N-by-6 array representing several rays, the result
%   INTERS is a N-by-3 array containing coordinates of intersection of each
%   ray with the polygon.
%
%   [INTER INSIDE] = intersectRayPolygon3d(RAY, POLY)
%   Also return a N-by-1 boolean array containing TRUE if both the polygon
%   and the corresponding ray contain the intersection point.
%
%   Example
%     % Compute intersection between a 3D ray and a 3D triangle
%     pts3d = [3 0 0; 0 6 0;0 0 9];
%     ray1 = [0 0 0 3 6 9];
%     inter = intersectRayPolygon3d(ray1, pts3d)
%     inter =
%           1   2   3
%
%     % keep only valid intersections with several rays
%     pts3d = [3 0 0; 0 6 0;0 0 9];
%     rays = [0 0 0 3 6 9;10 0 0 1 2 3;3 6 9 3 6 9];
%     [inter inside] = intersectRayPolygon3d(rays, pts3d);
%     inter(inside, :)
%     ans =
%           1   2   3
%
%   See Also
%   intersectRayPolygon, intersectLinePolygon3d, intersectLineTriangle3d
%

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2011-05-22,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% supporting plane of polygon vertices
plane   = createPlane(poly(1:3, :));

% intersection of 3D ray with the plane
inter   = intersectLinePlane(ray, plane);

% project all points on reference plane
pts2d   = planePosition(projPointOnPlane(poly, plane), plane);
pInt2d  = planePosition(projPointOnPlane(inter, plane), plane);

% need to check polygon orientation
inPoly  = xor(isPointInPolygon(pInt2d, pts2d), polygonArea(pts2d) < 0);
onRay   = linePosition3d(inter, ray) >= 0;
inside  = inPoly & onRay;

% intersection points outside the polygon are set to NaN
inter(~inside, :) = NaN;


function cx = jacobi_poly ( n, alpha, beta, x )

%*****************************************************************************80
%
%% JACOBI_POLY evaluates the Jacobi polynomials at X.
%
%  Differential equation:
%
%    (1-X*X) Y'' + (BETA-ALPHA-(ALPHA+BETA+2) X) Y' + N (N+ALPHA+BETA+1) Y = 0
%
%  Recursion:
%
%    P(0,ALPHA,BETA,X) = 1,
%
%    P(1,ALPHA,BETA,X) = ( (2+ALPHA+BETA)*X + (ALPHA-BETA) ) / 2
%
%    P(N,ALPHA,BETA,X)  =
%      (
%        (2*N+ALPHA+BETA-1)
%        * ((ALPHA**2-BETA**2)+(2*N+ALPHA+BETA)*(2*N+ALPHA+BETA-2)*X)
%        * P(N-1,ALPHA,BETA,X)
%        -2*(N-1+ALPHA)*(N-1+BETA)*(2*N+ALPHA+BETA) * P(N-2,ALPHA,BETA,X)
%      ) / 2*N*(N+ALPHA+BETA)*(2*N-2+ALPHA+BETA)
%
%  Restrictions:
%
%    -1 < ALPHA
%    -1 < BETA
%
%  Norm:
%
%    Integral ( -1 <= X <= 1 ) ( 1 - X )**ALPHA * ( 1 + X )**BETA
%      * P(N,ALPHA,BETA,X)**2 dX
%    = 2**(ALPHA+BETA+1) * Gamma ( N + ALPHA + 1 ) * Gamma ( N + BETA + 1 ) /
%      ( 2 * N + ALPHA + BETA ) * N! * Gamma ( N + ALPHA + BETA + 1 )
%
%  Special values:
%
%    P(N,ALPHA,BETA)(1) = (N+ALPHA)!/(N!*ALPHA!) for integer ALPHA.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 July 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%  Parameters:
%
%    Input, integer N, the highest order polynomial to compute.  Note
%    that polynomials 0 through N will be computed.
%
%    Input, real ALPHA, one of the parameters defining the Jacobi
%    polynomials, ALPHA must be greater than -1.
%
%    Input, real BETA, the second parameter defining the Jacobi
%    polynomials, BETA must be greater than -1.
%
%    Input, real X, the point at which the polynomials are to be evaluated.
%
%    Output, real CX(1:N+1), the values of the first N+1 Jacobi
%    polynomials at the point X.
%
  if ( alpha <= -1.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'JACOBI_POLY - Fatal error!\n' );
    fprintf ( 1, '  Illegal input value of ALPHA = %f\n', alpha );
    fprintf ( 1, '  But ALPHA must be greater than -1.\n' );
    error ( 'JACOBI_POLY - Fatal error!' );
  end

  if ( beta <= -1.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'JACOBI_POLY - Fatal error!\n' );
    fprintf ( 1, '  Illegal input value of BETA = %f\n', beta );
    fprintf ( 1, '  But BETA must be greater than -1.\n' );
    error ( 'JACOBI_POLY - Fatal error!' );
  end

  if ( n < 0 )
    cx = [];
    return
  end

  cx(1) = 1.0;

  if ( n == 0 )
    return
  end

  cx(2) = ( 1.0 + 0.5 * ( alpha + beta ) ) * x  + 0.5 * ( alpha - beta );

  for i = 2 : n

    c1 = 2 * i * ( i + alpha + beta ) * ( 2 * i - 2 + alpha + beta );

    c2 = ( 2 * i - 1 + alpha + beta ) * ( 2 * i + alpha + beta ) ...
      * ( 2 * i - 2 + alpha + beta );

    c3 = ( 2 * i - 1 + alpha + beta ) * ( alpha + beta ) * ( alpha - beta );

    c4 = - 2 * ( i - 1 + alpha ) * ( i - 1 + beta )  * ( 2 * i + alpha + beta );

    cx(i+1) = ( ( c3 + c2 * x ) * cx(i) + c4 * cx(i-1) ) / c1;

  end

  return
end


function yi = lagrange_basis_function_1d ( mx, xd, i, xi )

%*****************************************************************************80
%
%% LAGRANGE_BASIS_FUNCTION_1D evaluates a 1D Lagrange basis function.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer MX, the degree of the basis function.
%
%    Input, real XD(MX+1), the interpolation nodes.
%
%    Input, integer I, the index of the basis function.
%    1 <= I <= MX+1.
%
%    Input, real XI, the evaluation point.
%
%    Output, real YI, the value of the I-th Lagrange 1D basis function
%    for the nodes XD, evaluated at XI.
%
  if ( xi == xd(i) )
    yi = 1.0;
  else
    j = find ( 1 : mx + 1 ~= i );
    yi = prod ( xi - xd(j) ) / prod ( xd(i) - xd(j) );
  end

  return
end


function [coeffs,sigma2]=multilinRegress(zSamp,y,w,hasIntercept)
%%MULTILINREGRESS Perform multilinear regression. This means, given a set
%         of multidimensional points of the form [x1;x2;x3;...;xn],
%         determine the line/plane/hyperplane best fitting the points
%         such that
%         xn=coeffs(1)*x(2)+coeffs(2)*x(3)+....coeffs(n-1)*x(n-1)+coeffs(n)
%         if there is an intercept or
%         xn=coeffs(1)*x(2)+coeffs(2)*x(3)+....coeffs(n)*x(n).
%         if it is known there is a zero intercept.
%         The "best" fitting line/plane/hyperplane is the one that
%         minimizes
%         sum_{i=1}^N w(i)*(dot(coeffs(1:(n-1)),zSamp(1:(n-1),i))+coeffs(n)-zSamp(n,i))^2
%         if there is an intercept and y is not provided or that minimizes
%         sum_{i=1}^N w(i)*(dot(coeffs(1:(n-1)),zSamp(:,i))+coeffs(n)-y(i))^2
%         if y is provided and there is a y intercept. If there is no y
%         intercept, then the coeffs(n) term goes away in both instances.
%         The w(i) terms are all positive weights. For unweighted fusion,
%         w(i)=1.
%
%INPUTS: There are two parameterizations for zSamp and y. If y is an empty
%        matrix, then zSamp is a numDimsXnumPoints set of numPoints data
%        samples numDims>=2, as given above. On the other hand, if y is
%        provided, then y corresponds to zSamp(n,:) in the previous
%        parameterization (and can be a row or column vector) and zSamp thus
%        lacks the final row that it has in the initial parameterization.
%        Thus, zSamp will be a (numDims-1)XnumPoints matrix when y is
%        given.
%      w If weighted linear least squares optimization is supposed to be
%        performed, this is a length numPoints vector of values >0
%        containing the weight of each sample. If the regression is
%        performed with un unweighted cost function, this parameter can be
%        omitted or an empty matrix can be passed.
% hasIntercept A boolean value indicating whether the fit has a nonzero y
%        intercept. The default if omitted or an empty matrix is passed is
%        true.
%
%OUTPUTS: coeffs The numDimsX1 set of weights for the linear equation
%                described above. If hasIntercept=true, then the last
%                element is the additive constant.
%         sigma2 The residual mean square.  This is SSE/(numPoints-numDims)
%                where SSE is the vector of ordinary residuals e'*diag(w)*e
%                where e=(y(:)-x'*coeffs), where x is
%                [zSamp;ones(1,numPoints)] if an intercept is desired and y
%                is given, or x=zSamp if an intercept is not desired and y
%                is given. Similar expressions for when y is not given
%                hold, whereby y is replaced by the last row of zSamp. This
%                is the quantity being minimized in the optimization.
%
%Formulae for this type of regression are given in Appendix A.7.1 and A.7.3
%of [1] for 2D and 3D measurements without the weights. This function just
%continues the pattern implementing the results for an arbitrary number of
%dimensions, for weights and a modification allowing for there to be a
%known zero y intercept is also added. The derivation is just basic
%differential calculus. Note that this function will fail if the plane
%being estimated does not depend on the independent parameter. In 2D, this
%would correspond to a vertical line (e.g. x=4).
%
%EXAMPLE 1:
%Here is an example with a nonzero y intercept using both input formats.
% coeffs=[4;6;2];
% numPts=20;
% xVals=linspace(-4,4,numPts);
% yVals=linspace(-4,4,numPts);
% [x,y]=ndgrid(xVals,yVals);
% xyPts=[x(:).';y(:).'];
% zPts=sum(bsxfun(@times,coeffs(1:2),xyPts),1)+coeffs(3);
% zPts=zPts+0.1*randn(1,numPts^2); %Add noise.
% zSamp=[xyPts;zPts];
% [coeffsEst,sigma2]=multilinRegress(zSamp)
% [coeffsEstAlt,sigma2Alt]=multilinRegress(xyPts,zPts)
%One finds that coeffsEst is the same as coeffsEstAlt and is close to
%coeffs. A perfect fit (wihtin finite precision limitaitions) is achieved
%if there is zero noise.
%
%EXAMPLE 2:
%Here is an example when it is known that the y intercept is zero.
% coeffs=[4;6];
% numPts=20;
% xVals=linspace(-4,4,numPts);
% yVals=linspace(-4,4,numPts);
% [x,y]=ndgrid(xVals,yVals);
% xyPts=[x(:).';y(:).'];
% zPts=sum(bsxfun(@times,coeffs(1:2),xyPts),1);
% zPts=zPts+0.1*randn(1,numPts^2); %Add noise.
% zSamp=[xyPts;zPts];
% [coeffsEst,sigma2]=multilinRegress(zSamp,[],[],false)
% [coeffsEstAlt,sigma2Alt]=multilinRegress(xyPts,zPts,[],false)
%Again, the results are comparable to those in problem 1 with the two input
%formulations equal and close to coeffs.
%
%REFERENCES:
%[1] P. J. Schneider and D. H. Eberly, Geometric Tools for Computer
%    Graphics. Amsterdam: Morgan Kaufmann Publishers, 2003.
%
%April 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numDims=size(zSamp,1);
numPoints=size(zSamp,2);

if(nargin<4||isempty(hasIntercept))
    hasIntercept=true;
end

if(nargin<3)
   w=[];
end

if(nargin>1&&~isempty(y))
    if(hasIntercept)
        x=[zSamp;ones(1,numPoints)];
        p=numDims+1;
    else
        x=zSamp;
        p=numDims;
    end
else
    if(hasIntercept)
        x=[zSamp(1:(numDims-1),:);ones(1,numPoints)];
        p=numDims;
    else
        x=zSamp(1:(numDims-1),:);
        p=numDims-1;
    end

    y=zSamp(numDims,:);
    y=y(:);
end

if(isempty(w))
    A=x*x';
    b=x*y(:);
else
    %In Matlab, x*eye(size(x,2))*x'-x*x' and
    %bsxfun(@times,x,ones(numPoints,1).')*x'-x*x' are not numerically zero,
    %which means that just using w with weights all equal to 1 will change
    %the last few bits of the result.

    w=w(:);
    A=bsxfun(@times,w.',x)*x';
    b=x*(w.*y(:));
end

coeffs=A\b;

if(nargout>1)
    if(nargin>1&&~isempty(y))
        e=y(:)-x'*coeffs;
    else
        e=vec(zSamp(numDims,:))-x'*coeffs;
    end

    if(isempty(w))
        %The residual sum of squares.
        sigma2=e'*e/(numPoints-p);
    else%The weighted residual sum of squares.
        sigma2=(w.*e)'*e/(numPoints-p);
    end
end
end

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


function alpha = anglePoints3d(varargin)
%ANGLEPOINTS3D Compute angle between three 3D points.
%
%   ALPHA = anglePoints3d(P1, P2)
%   Computes angle (P1, O, P2), in radians, between 0 and PI.
%
%   ALPHA = anglePoints3d(P1, P2, P3)
%   Computes angle (P1, P2, P3), in radians, between 0 and PI.
%
%   ALPHA = anglePoints3d(PTS)
%   PTS is a 3x3 or 2x3 array containing coordinate of points.
%
%   Example
%       rad2deg(anglePoints3d([0 0 1],[1 1 0]))
%
%   See also
%   points3d, angles3d

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

p2 = [0 0 0];
if length(varargin) == 1
    pts = varargin{1};
    if size(pts, 1)==2
        p1 = pts(1,:);
        p0 = [0 0 0];
        p2 = pts(2,:);
    else
        p1 = pts(1,:);
        p0 = pts(2,:);
        p2 = pts(3,:);
    end

elseif length(varargin) == 2
    p1 = varargin{1};
    p0 = [0 0 0];
    p2 = varargin{2};

elseif length(varargin) == 3
    p1 = varargin{1};
    p0 = varargin{2};
    p2 = varargin{3};
end

% ensure all data have same size
n1 = size(p1, 1);
n2 = size(p2, 1);
n0 = size(p0, 1);

if n1 ~= n0
    if n1 == 1
        p1 = repmat(p1, [n0 1]);
        n1 = n0;
    elseif n0==1
        p0 = repmat(p0, [n1 1]);
    else
        error('Arguments P1 and P0 must have the same size');
    end
end

if n1 ~= n2
    if n1 == 1
        p1 = repmat(p1, [n2 1]);
    elseif n2 == 1
        p2 = repmat(p2, [n1 1]);
    else
        error('Arguments P1 and P2 must have the same size');
    end
end

% normalized vectors
p1 = normalizeVector3d(p1 - p0);
p2 = normalizeVector3d(p2 - p0);

% compute angle
alpha = acos(dot(p1, p2, 2));


function bw = audfiltbw(fc,varargin)
%AUDFILTBW  Bandwidth of auditory filter
%   Usage: bw = audfiltbw(fc)
%
%   `audfiltbw(fc)` returns the critical bandwidth of the auditory filter
%   at center frequency *fc* defined in equivalent rectangular bandwidth.
%   The function uses the relation:
%
%   .. bw = 24.7 + fc/9.265
%
%   .. math::  bw = 24.7 + \frac{fc}{9.265}
%
%   as estimated in Glasberg and Moore (1990). This function is also used
%   when the original ERB scale ('erb83') is chosen.
%
%   `audfiltbw(fc,'bark')` returns the critical bandwidth at *fc* according
%   to the Bark scale using the relation:
%
%   .. bw = 25 + 75 ( 1+1.4*10^{-6} fc^2 )^0.69
%
%   .. math::  bw = 25 + 75 ( 1+1.4\times10^{-6} fc^2 )^{0.69}
%
%   as estimated by Zwicker and Terhardt (1980).
%
%   For the scales 'mel', 'mel1000', 'log10' and 'semitone', no critical
%   bandwidth function is usually given. Following the example of the
%   equivalent rectangular bandwidth (associated with the ERB scale), we
%   use the derivative of the inverse of the scale function F_{Scale},
%   evaluated at F_{Scale}(fc), i.e.
%
%   .. bw = (F_{scale}^{-1})'(F_{scale}(fc))
%
%   .. math::  bw = (F_{scale}^{-1})'(F_{scale}(fc))
%
%   See also: freqtoerb, erbspace, freqtoaud, audtofreq
%
%   References: glasberg1990daf zwickerterhardt80

%   AUTHOR : Peter L. Søndergaard

% ------ Checking of input parameters ---------

% narginchk(1,1);
if nargin<1
  error('%s: Too few input parameters.',upper(mfilename));
end;

if ~isnumeric(fc) || any(fc(:)<0)
  error('AUDFILTBW: fc must be non-negative.');
end;

definput.flags.audscale={'erb','erb83','bark','mel','mel1000','log10','semitone'};
[flags,kv]=ltfatarghelper({},definput,varargin);

% ------ Computation --------------------------

% FIXME: What is the upper frequency for which the estimation is valid?
if flags.do_erb || flags.do_erb83
    bw = 24.7 + fc/9.265;
end

if flags.do_bark
    bw = 25 + 75*(1 + 1.4E-6*fc.^2).^0.69;
end

if flags.do_mel
    bw = log(17/7)*(700+fc)/1000;
end

if flags.do_mel1000
    bw = log(2)*(1+fc/1000);
end;

if flags.do_log10 || flags.do_semitone
    bw = fc;
end


% This function calculates the fractional derivative of order d for the
% given function r(t). It is assumed that the vector r contains the
% samples of the continuous signal r(t) which we are going to calculate its
% fractional derivative. h is a constant and represents the sampling
% period of r(t) (the time period between two samples). h must be small
% enough in the sense of Nyquist sampling theorem.
% y is the result achieved by applying the fractional differentiation
% operator on the input r. This contains the samples of the real output
% y(t) with the same sampling period used for r.
% It makes use of the Grünwald-Letnikov definition. The first element of
% the vector "r", i.e. r(1), is always zero.
%
% d        :        the order of fractional differentiation
% r        :        samples of the signal to be differentiated
% h        :        sampling poriod

function [y] = fderiv(d,r,h)

temp = 0;
for i=1:length(r)
    for j=0:i-1
        temp = temp+(-1)^j*(gamma(d+1)/(gamma(j+1)*gamma(d-j+1)))*r(i-j);
    end
    y(i) = temp;
    temp = 0;
end
y = y/(h^d);


function [ a, b, c, d, e, f ] = rs_to_xy_map ( t )

%*****************************************************************************80
%
%% RS_TO_XY_MAP returns the linear map from reference to physical triangle.
%
%  Location:
%
%    http://people.sc.fsu.edu/~jburkardt/m_src/triangle_poly_integral/rs_to_xy_map.m
%
%  Discussion:
%
%    This function returns the coefficients of the linear map that sends
%    the vertices of the reference triangle, (0,0), (1,0) and (0,1), to
%    the vertices of a physical triangle T, of the form:
%
%      X = A + B * R + C * S;
%      Y = D + E * R + F * S.
%
%  Reference Element:
%
%    |
%    1  3
%    |  |\
%    |  | \
%    S  |  \
%    |  |   \
%    |  |    \
%    0  1-----2
%    |
%    +--0--R--1-->
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 April 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real T(2,3), the coordinates of the vertices.  The vertices are
%    assumed to be the images of (0,0), (1,0) and (0,1) respectively.
%
%    Output, real A, B, C, D, E, F, the mapping coefficients.
%
  a = t(1,1);
  b = t(1,2) - t(1,1);
  c = t(1,3) - t(1,1);

  d = t(2,1);
  e = t(2,2) - t(2,1);
  f = t(2,3) - t(2,1);

  return
end


function [rankVal,V,U,S]=matrixRank(A,algorithm)
%%MATRIXRANK Determine the rank of a matrix using a chosen criterion.
%
%INPUTS: A The MXN matrix whose rank is desired.
% algorithm An optional parameter specifying the criterion to use. All
%          methods compare the singular values to a bound. Possible values
%          are:
%          0 (The default if omitted or an empty matrix is passed) Use
%            eps(norm(A,1)) as the bound.
%          1 Use max(size(A))*eps(max(s)), where s is the vector of
%            singular values.
%          2 Use eps()*norm(A,1).
%          3 Use max(size(A))*eps()*max(s).
%
%OUTPUTS: rankVal The rank of matrix A.
%               V The right singular vectors from the SVD used here (The
%                 full SVD is computed, not the 'econ' or 0 options). Given
%                 the rank, one can extract a basis or a nullspace.
%               U The left singular vectors from the SVD.
%               S A diagonal matrix of singular values from the SVD.
%
%The notion of the matrix rank relating to a thresholding of the singular
%values is discussed in Chapter 5.4.1 of [1].
%
%REFERENCES:
%[1] G. H. Golub and C. F. Van Loan, Matrix Computations, 4th ed.
%    Baltimore: Johns Hopkins University Press, 2013.
%
%September 2019 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

if(nargout>1)
    [U,S,V]=svd(A);
else
    [~,S,~]=svd(A);
end
s=diag(S);

switch(algorithm)
    case 0
        rankVal=sum(s>eps(norm(A,1)));
    case 1
        rankVal=sum(s>max(size(A))*eps(max(s)));
    case 2
        rankVal=sum(s>eps()*norm(A,1));
    case 3
        rankVal=sum(s>max(size(A))*eps()*max(s));
    otherwise
        error('Unknown rank algorithm specified.')
end
end

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


% This example shows how to calculate the TM_01 mode of a step-index
% fiber.  The magnetic field for the TM_01 mode is azimuthally
% symmetric, which means that both Hx and Hy are of the same
% magnitude, making this an excellent test case for the
% full-vector modesolver.  It also compares the numerically
% calculated result with the exact solution.  Note that the
% modes look virtually identical, but there is a discrepancy
% betweeen the numerically-computed eigenvalue and the exact
% eigenvalue.  This is thought to be caused by the the
% inaccuracy of representing a curved core-clad interface with
% a staircase function.

% Refractive indices:
nco = 2.5;          % core index
ncl = 1.5;          % cladding index
r = 0.30;           % core radius (um)

side = 0.2;         % space on side (um)

dx = 0.002;         % grid size (horizontal)
dy = 0.002;         % grid size (vertical)

lambda = 1;         % wavelength
nmodes = 1;         % number of modes to compute

% Boundary conditions for antisymmetric mode
boundary = '0A0S';

% Set up finite difference mesh:
[x,y,xc,yc,nx,ny,eps] = fiber([nco,ncl],[r],side,dx,dy);

% Now we stretch out the mesh at the boundaries:
[x,y,xc,yc,dx,dy] = stretchmesh(x,y,[96,0,96,0],[4,1,4,1]);

% Solve for mode (using transverse H modesolver)
[Hx,Hy,neff] = wgmodes (lambda, nco, nmodes, dx, dy, eps, ...
                         boundary);
fprintf(1,'neff (finite difference) = %8.6f\n',neff);

% Now solve for the exact eigenmodes
V = 2*pi*r/lambda*sqrt(nco^2-ncl^2);
U = fzero(@(U) ...
           nco^2*besselj(1,U)/(U*besselj(0,U)) + ...
           ncl^2*besselk(1,sqrt(V^2-U^2))/ ...
           (sqrt(V^2-U^2)*besselk(0,sqrt(V^2-U^2))), 3.2);
W = sqrt(V^2-U^2);
neff0 = sqrt(nco^2 - (U/(2*pi*r/lambda))^2);
fprintf(1,'neff (exact solution)    = %8.6f\n',neff0);

rho = sqrt(x.^2*ones(size(y)) + ones(size(x))*y.^2);
sinphi = ones(size(x))*y./rho;
cosphi = x*ones(size(y))./rho;
Hx0 = zeros(size(rho));
Hy0 = zeros(size(rho));
kv = find(rho < r);
Hx0(kv) = -sinphi(kv).*besselj(1,U*rho(kv)./r)/besselj(1,U);
Hy0(kv) = cosphi(kv).*besselj(1,U*rho(kv)./r)/besselj(1,U);
kv = find(rho >= r);
Hx0(kv) = -sinphi(kv).*besselk(1,W*rho(kv)./r)/besselk(1,W);
Hy0(kv) = cosphi(kv).*besselk(1,W*rho(kv)./r)/besselk(1,W);
[hmax,kv] = max(abs(Hx0(:)));
hmax = Hx0(kv);
Hx0 = Hx0/hmax;
Hy0 = Hy0/hmax;

figure(1);

subplot(221);
contourmode(x,y,Hx);
title('Hx (finite difference)');

subplot(222);
contourmode(x,y,Hy);
title('Hy (finite difference)');

subplot(223);
contourmode(x,y,Hx0);
title('Hx (exact)');

subplot(224);
contourmode(x,y,Hy0);
title('Hy (exact)');


function root = BesselJ_RootsCyl(starts)
% BesselJ_RootsCyl(starts) finds the roots of the equation J'_1(x) = 0
% where J_1 is the first order Bessel function of the first kind.
%
% starts is the number of starting points in the search for
% roots.  The larger it is, the more roots are returned in the root array.
% The default is 20, which returns 6 roots.  starts = 100 returns 32 roots.
% Generally the number of roots is just under 1/3 the number of starting
% points.
%
% author: Daniel C Alexander (d.alexander@ucl.ac.uk)
%

if(nargin==0)
    starts = 20;
end

f = @(x)(0.5*(besselj(0,x) - besselj(2,x)));

% Get a good list of starting points
y = 0:0.1:starts;
dj1 = f(y);
starts = (find(dj1(1:end-1).*dj1(2:end)<0)+1)*0.1;

for s=1:length(starts)
    root(s) = fzero(f,starts(s));
end


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

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

    % cost: J
    J = -1/n * sum(...
        y      .* log(sigmoid(X * theta)) + ...
        (1 - y) .* log(1 - sigmoid(X * theta)) ...
    );

    % gradient: compute as the derivative of the cost function
    grad = 1/n * X' * ((sigmoid(X * theta)) - y);

end


function [R,s]=rotmat2vec(u,v)
%
% [R,s]=rotmat2vec(u,v)
%
% the rotation matrix from vector u to v, satisfying R*u*s=v
%
% author: Bruno Luong
% URL:http://www.mathworks.com/matlabcentral/newsreader/view_original/827969
%
% input:
%   u: a 3D vector in the source coordinate system;
%   v: a 3D vector in the target coordinate system;
%
% output:
%   R: a rotation matrix to transform normalized u to normalized v
%   s: a scaling factor, so that R*u(:)*s=v(:)
%
% -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
%

s=norm(v(:))/norm(u(:));
u1=u(:)/norm(u(:));
v1=v(:)/norm(v(:));

k = cross(u1,v1);
if(~any(k)) % u and v are parallel
    R=eye(3);
    return;
end
% Rodrigues's formula:
costheta = dot(u1,v1);
R =[ 0 -k(3) k(2);
     k(3) 0 -k(1);
    -k(2) k(1) 0];
R = costheta*eye(3) + R + k*k'*(1-costheta)/sum(k.^2);


function xval = r8vec_even_select ( n, xlo, xhi, ival )

%*****************************************************************************80
%
%% R8VEC_EVEN_SELECT returns the I-th of N evenly spaced values in [ XLO, XHI ].
%
%  Discussion:
%
%    XVAL = ( (N-IVAL) * XLO + (IVAL-1) * XHI ) / dble ( N - 1 )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 November 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of values.
%
%    Input, real XLO, XHI, the low and high values.
%
%    Input, integer IVAL, the index of the desired point.
%    IVAL is normally between 1 and N, but may be any
%    integer value.
%
%    Output, real XVAL, the IVAL-th of N evenly spaced values
%    between XLO and XHI.
%
%    Unless N = 1, X(1) = XLO and X(N) = XHI.
%
%    If N = 1, then X(1) = 0.5*(XLO+XHI).
%
  if ( n == 1 )

    xval = 0.5 * ( xlo + xhi );

  else

    xval = ( ( n - ival     ) * xlo   ...
           + (     ival - 1 ) * xhi ) ...
           / ( n        - 1 );

  end

  return
end


function volume = sphere_cap_volume_nd ( dim_num, r, h )

%*****************************************************************************80
%
%% SPHERE_CAP_VOLUME_ND computes the volume of a spherical cap in ND.
%
%  Discussion:
%
%    The spherical cap is a portion of the surface and interior of the sphere:
%
%      sum ( X(1:N)^2 ) <= R * R
%
%    which is no more than H units from some point P on the sphere.
%
%
%    The algorithm proceeds from the observation that the N-dimensional
%    sphere can be parameterized by a quantity RC that runs along the
%    radius from the center to the point P.  The value of RC at the
%    base of the spherical cap is (R-H) and at P it is R.  We intend to
%    use RC as our integration parameeter.
%
%    The volume of the spherical cap is then the integral, as RC goes
%    from (R-H) to R, of the N-1 dimensional volume of the sphere
%    of radius RS, where RC * RC + RS * RS = R * R.
%
%    The volume of the N-1 dimensional sphere of radius RS is simply
%    some constants times RS**(N-1).
%
%    After factoring out the constant terms, and writing RC = R * cos ( T ),
%    and RS = R * sin ( T ), and letting
%      T_MAX = arc_sine ( sqrt ( ( 2.0 * r - h ) * h / r ) ),
%    the "interesting part" of our integral becomes
%
%      constants * R^N * Integral ( T = 0 to T_MAX ) sin^N ( T ) dT
%
%    The integral of sin^N ( T ) dT can be handled by recursion.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the space.
%
%    Input, real R, the radius of the sphere.
%
%    Input, real H, the "thickness" of the spherical cap,
%    which is normally between 0 and 2 * R.
%
%    Output, real VOLUME, the volume of the spherical cap.
%
  if ( h <= 0.0 )
    volume = 0.0;
    return
  end

  if ( 2.0 * r <= h )
    volume = sphere_volume_nd ( dim_num, r );
    return
  end

  if ( dim_num < 1 )

    volume = -1.0;

  elseif ( dim_num == 1 )

    volume = h;

  else

    factor1 = sphere_unit_volume_nd ( dim_num - 1 );

    angle = r8_asin ( sqrt ( ( 2.0 * r - h ) * h / r ) );

    factor2 = sin_power_int ( 0.0, angle, dim_num );

    volume = factor1 * factor2 * r^dim_num;

    if ( r < h )
      volume2 = sphere_volume_nd ( dim_num, r );
      volume = volume2 - volume;
    end

  end

  return
end


function k=FibonacciNumInv(n,choice)
%FIBONACCINUMINV Given a real number >=1, determine the k such that
%                n==FibonacciNum(k). If n given is not a Fibonacci number,
%                then the behaviour is determined by the choice option.
%
%INPUTS: n A scalar or matrix of values for which the argument of
%          FibonacciNum is desired, n>=1.
%   choice An optional parameter that determines what is returned if n
%          is not an exact Fibonacci number. If this parameter is omitted,
%          then the default is one (the next lower value).
%          0 means return the closest value.
%          1 means return the next lower value.
%          2 means return the next higher value.
%
%OUTPUTS: k The argument of FibonacciNum that gives n, or an appropriately
%           close value selected by the choice option. k will always be
%           >=2.
%
%A non-recursive expression for Fibonacci numbers is given in [1] and can
%be inverted. However, due to finite prevision issues, for n in the mid
%70's the value returned can be off. Thus, testing needs to be done for all
%inputs in the choice option to make sure that the proper value is chosen.
%
%REFERENCES:
%[1] Chandra, Pravin and Weisstein, Eric W. "Fibonacci Number." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/FibonacciNumber.html
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

    %The golden ratio.
    phi=(1+sqrt(5))/2;
    k=fix(log(n*sqrt(5))/log(phi)+(1/2));

    %Due to finite precision errors, even if n is a Fibonacci number, k
    %might be the correct value, it might be 1 less or it might be 1 too
    %much. We will adjust k to deal with the situation. Note that from
    %above, k>=2, so there are no issues with k-1 being <1.
    switch(choice)
        case 0%Return the closest value
            valsLower=FibonacciNum(k-1);
            valsCur=FibonacciNum(k);
            valsUpper=FibonacciNum(k+1);

            diffLower=abs(n-valsLower);
            diffCur=abs(n-valsCur);
            diffUpper=abs(n-valsUpper);

            sel=(diffLower<diffCur)&(diffLower<diffUpper);
            k(sel)=k(sel)-1;
            sel=(valsUpper<diffCur)&(diffUpper<diffLower);
            k(sel)=k(sel)+1;
        case 1%Return the next lower value.
            %We have to do a check, because finite precision error
            %above might make k be too large.
            valsCur=FibonacciNum(k);

            sel=valsCur>n;
            k(sel)=k(sel)-1;
        case 2%Return the next higher value.
            valsCur=FibonacciNum(k);
            sel=valsCur<n;
            k(sel)=k(sel)+1;
        otherwise
            error('Unknown choice value specified.')
    end
end

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


function P = Gamma2aCCDF (v, a)
% This function calculates the complementary cumulative probability
% distribution function (CDF) for a unit-variance (two-sided) generalized
% gamma probability density function (PDF) with parameter a,
%
%   p(x,a) = b exp(-b|x|) (b|x|)^(a-1) / (2 G(a)),   a >= 0.
%
% where G(a) is the complete gamma function.
%
% The complementary cumulative distribution function is
%                       inf
%   G(v,a) = b/(2 G(a)) Int exp(-b|x|) (b|x|)^(a-1) dx.
%                        v
% To develop this formula, we start from the one-sided gamma PDF
%
%  G(x,a) = 1/G(a) exp(-x) x^(a-1),  for x >= 0,
%         = 0,                       for x < 0.
% We now make the PDF two-sided
%   Gamma2PDF(x,a) = 1/2 GammaPDF(|x|,a).
% This is a zero-mean (symmetric) distribution. Its variance can be
% calculated integrating the product of t^2 and Gamma2PDF(x,a). But
% multiplying the PDF by t^2 is the same as replacing the exponent a-1
% by a+1. Then the variance is
%   Var(Gamma2PDF(x,a) = G(a+2)/G(a) = a(a+1),
% since G(a+1) = a G(a).
%
% Let the standard deviation be denoted as b = sqrt(a(a+1)). Then scaling
% x by b and scaling the result, gives the unit-variance generalized gamma
% density shown above. The complementary cumulative distribution function
% is then (for v >= 0),
%                      inf
%  G(v,a) = b/(2 G(a)) Int exp(-b|x|) (b|x|)^(a-1) dx
%                       v
%                      inf
%         = 1/(2 G(a)) Int exp(-u) u^(a-1) du
%                      bv
%         = 1/2 Gamma1aCCDF(bv,a).

% Moments
% Let p(x,a1) be the generalized gamma distribution with parameter a1.
%   F0(x,a1) = Int(x,Inf) p(x,a1) dx
% The moment integrals are
%   Fn(x,a1) = Int(x,Inf) x^n p(x,a1) dx
%            = G(a2)/(G(a1) b1^n) F0(b1 x/b2, a2)       n even
%            = G(a2)/(G(a1) b1^n) F0(b1 abs(x)/b2, a2), n odd
% where a2=a1+n, b1=sqrt(b1(b1+1)), and b2=sqrt(a2(a2+1)). Note that the
% generalized gamma PDF uses abs(x). So for odd moments (n odd), we have to
% compensate by changing the sign of the argument.

% Gaussian
% The Gaussian complementary cumulative distribution function can be
% computed from the generalized gamma distribution. Consider the moments
% of the Gaussian distribution
%   Fn(u) = 1/sqrt(2pi) Int u^n e^(-u^2/2) du
% Consider u positive. Substitute x = u^2/(2b) with u = sqrt(2bx). Then
% du = b/sqrt(2) 1/sqrt(bx), giving
%   Fn(x) = 1/sqrt(2pi) Int (2bx)^(n/2) e^(-bx) b/sqrt(2) 1/sqrt(bx) dx
%         = 1/sqrt(2pi) 2^(n/2)/sqrt(2) b Int (bx)^((n-1)/2) e^(-bx) dx
% Let a = (n+1)/2,
%   Fn(x) = 2^(n/2) G(a)/sqrt(pi) b/(2G(a)) Int exp(-bx) (bx)^(a-1) dx
%         = 2^(n/2) G(a)/sqrt(pi) G(x,a)  with x>0 and b=sqrt(a(a+1)).
%
% For the integral of the Gaussian, n=0, a=1/2, b=sqrt(3)/2), and
% G(a)=sqrt(pi))
%   F0(x) = G(x,1/2)
% or
%   F0(u) = G(sgn(x) x^2/(2b),1/2).
% The sgn() function compensates for the loss of sign information in
% squaring x.
%
% The Gaussian first moment is given by n=1, a=1, b=sqrt(2), and
% G(a)=sqrt(2),
%   F1(u) = sqrt(2/pi) G(x^2/(2b), 1)
% The sgn() function is not necessary since the integrand is odd.
%
% The Gaussian second moment is given by n=2, a=3/2, b=sqrt(3)/2, and
% G(a)=sqrt(pi)/2,
%   F2(u) = G(sgn(x) x^2/(2b), 3/2)

b = sqrt(a*(a+1));
if (v >= 0)
  P = (1/2) * Gamma1aCCDF(b*v, a);
else
  P = 1 - (1/2) * Gamma1aCCDF(-b*v, a);
end

return


function fx = p57_fun ( n, x )

%*****************************************************************************80
%
%% P57_FUN evaluates the integrand for problem 57.
%
%  Interval:
%
%    0 <= x <= 1
%
%  Integrand:
%
%    x^(3/2)
%
%  Antiderivative:
%
%    (2/5) * x^(5/2)
%
%  Exact Integral:
%
%    0.4
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    David Kahaner,
%    Comparison of Numerical Quadrature Formulas,
%    in Mathematical Software, edited by John R Rice,
%    Academic Press, 1971.
%
%  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:n) = sqrt ( x(1:n).^3 );

  return
end


function frf=dfracft(f,a,varargin)
%DFRACFT  Discrete Fractional Fourier transform
%   Usage:  V=dfracft(f,a,p);
%           V=dfracft(f,a);
%
%   `dfracft(f,a)` computes the discrete fractional Fourier Transform of the
%   signal *f* to the power *a*. For *a=1* it corresponds to the ordinary
%   discrete Fourier Transform. If *f* is multi-dimensional, the
%   transformation is applied along the first non-singleton dimension.
%
%   `dfracft(f,a,dim)` does the same along dimension *dim*.
%
%   `dfracft(f,a,[],p)` or `dfracft(f,a,dim,p)` allows to choose the order
%   of approximation of the second difference operator (default: *p=2*).
%
%   See also:  ffracft, dft, hermbasis, pherm
%
%   References: ozzaku01,buma04

%   AUTHOR : Christoph Wiesmeyr
%   TESTING: TEST_HERMBASIS
%   REFERENCE: OK

if nargin<2
  error('%s: Too few input parameters.',upper(mfilename));
end;

definput.keyvals.p   = 2;
definput.keyvals.dim = [];
[flags,keyvals,dim,p]=ltfatarghelper({'dim','p'},definput,varargin);

[f,L,Ls,W,dim,permutedsize,order]=assert_sigreshape_pre(f,[],dim,upper(mfilename));

H = hermbasis(L,p);

% set up the eigenvalues
k=0:L-1;
lam = exp(-1i*k*a*pi/2);
lam=lam(:);

% correction for even signal lengths
if ~rem(L,2)
    lam(end)=exp(-1i*L*a*pi/2);
end

% shuffle the eigenvalues in the right order
even=~mod(L,2);
cor=2*floor(L/4)+1;
for k=(cor+1):2:(L-even)
    lam([k,k+1])=lam([k+1,k]);
end

frf =H*(bsxfun(@times,lam,H'*f));

frf=assert_sigreshape_post(frf,dim,permutedsize,order);


function g = sigmoid(z)
%SIGMOID Compute sigmoid functoon
%   J = SIGMOID(z) computes the sigmoid of z.

% You need to return the following variables correctly
g = zeros(size(z));

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

%g = 1 ./ (1 .+ e .^ -z);
g = 1.0 ./ (1.0 + exp(-z));%exp(n)-->e的n次方

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

end


function [val table]= muller(strEqn,strVar,p0,p1,p2,tol,n)
%MULLER uses the Muller's method to solve for a root of f(x)
%
% Find a solution to f(x) = 0 given three approximations p0, p1
% and p2 (Note that Muller's method may return complex roots)
%
%
%  INPUT:
%         strEqn: is the string representation of the equation f(x)
%         strVar: is the varialbe in strEqn
%     p0, p1, p2: initial guesses at the solution
%            tol: is the solution tolerence
%              n: is the maximum number of iterations of the algorithum.
%
%  OUTPUT:   val: is the approximate solution (can be complex)
%          table: is the iteration table
%
%
%  USAGE:   val = muller(strEqn,strVar,x0,x1,x2,tol,n)
%          [val table] = muller(...) to display a table of the iterations
%           val = muller('x^3+2*x^2-5','x',0,1,2,10^-4,100)
%
%     BY: Jonathan Lister (jlister1@utk.edu)

%% Additonal Examples
%
%           strEqn = '16*x^4-40*x^3+5*x^2+20*x+6';
%           strVar = 'x';
%           tol = 10^-5;
%
%           disp('p0 = 0.5, p1 = -0.5, p2 = 0.0')
%           [root1 table1]= muller(strEqn,strVar,0.5,-0.5,0,tol,100)
%
%           disp('p0 = 0.5, p1 = 1.0, p2 = 1.5')
%           [root2 table2]= muller(strEqn,strVar,0.5,1.0,1.5,tol,100)
%
%           disp('p0 = 2.5, p1 = 2.0, p2 = 2.25')
%           [root3 table3]= muller(strEqn,strVar,2.5,2.0,2.25,tol,100)
%

%% Input Error Checking
if nargin < 7
    error('Incorrect number of input arguments type "help muller"')
end

if tol < 0
    error('tolerance must be a positive number')
end

if ~ischar(strEqn)
    error('Input 1 Error, a string of the equation of interest is required')
end

if ~ischar(strVar)
    error('Input 3 Error, a string representation of the variable is required')
end

%parse equation
F = vectorize(inline(strEqn,strVar));

%intitialize output variables
val = [];
table ={};

%% Algorithm 2.8 from text.
%Step 1
h1 = p1 - p0;
h2 = p2 - p1;
del1 = (F(p1)-F(p0))./h1;
del2 = (F(p2)-F(p1))./h2;
d = (del2-del1)./(h2+h1);
I = 3;

%Step 2
while I <= n
    %Step 3
    b = del2+h2.*d;
    D = sqrt(b.^2-4.*F(p2).*d); % could be complex
    %Step 4
    if abs(b - D) < abs(b + D)
        E = b + D;
    else
        E = b - D;
    end
    %Step 5
    h = -2.*F(p2)./E;
    p = p2 + h;

    if I == 3
        table{1} = 'Muller''s Method Iterations';
        table{2}='  I             P                     f(P)           ';
        table{3}='-----------------------------------------------------';
    end
    str = sprintf('%3u:  % 6.6f + %6.6fi % 6.6f + %6.6fi',I,real(p),imag(p),real(F(p)),imag(F(p)));
    table{I + 1} = str; %#ok<*AGROW>

    %Step 6
    if abs(h) < tol
        val = p;
        table = char(table);
        break
    end
    p0 = p1;
    p1 = p2;
    p2 = p;
    h1 = p1 - p0;
    h2 = p2 - p1;
    del1 = (F(p1)-F(p0))./h1;
    del2 = (F(p2)-F(p1))./h2;
    d = (del2-del1)./(h2+h1);
    I = I + 1;
end

if isempty(val)
    disp('The procedure was unsuccessful.')
    table = char(table);
end


function h = gaussianKernel3D( r, sigma)
%Create pre-defined 3-D Gaussian kernel.
%
%   Description :
%
%   h = gaussianKernel3D(r,sigma) returns a rotationally symmetric Gaussian
%   kernel h of size 2*r+1 with standard deviation sigma (positive). The
%   default size of r is 1 and the default sigma is 0.5.
%
%   Author : Mohammad Mustafa
%   By courtesy of University of Nottingham and Mirada Medical Limited,
%   Oxford, UK
%
%   Published under a Creative Commons Attribution-Non-Commercial-Share Alike
%   3.0 Unported Licence http://creativecommons.org/licenses/by-nc-sa/3.0/
%
%   June 2012

    if nargin<1
        r=1; sigma=0.5;
    elseif nargin==1
        sigma=0.5;
    end
    [x,y,z] = ndgrid(-r:r,-r:r,-r:r);
    arg   = -(x.*x + y.*y + z.*z)/(2*sigma*sigma);

    h = exp(arg);

    if sum(h(:)) ~= 0,
      h  = h/sum(h(:));
    end;

end


function varargout = beale(X)
% Beale funcion
%
%   BEALE([x1, x2]) returns the value of the value of the Beale
%   function at the specified points. [x1] and [x2] may be vectors.
%   The search domain is
%
%               -4.5 < x_i < 4.5
%
%   The global minimum is
%
%               f(x1, x2) = f(3, 0.5) = 0.

% Author: Rody P.S. Oldenhuis
% Delft University of Technology
% E-mail: oldenhuis@dds.nl
% Last edited 20/Jul/2009

    % if no input is given, return dimensions, bounds and minimum
    if (nargin == 0)
        varargout{1} = 2;  % # dims
        varargout{2} = [-4.5, -4.5]; % LB
        varargout{3} = [+4.5, +4.5]; % UB
        varargout{4} = [3, 0.5]; % solution
        varargout{5} = 0; % function value at solution

    % otherwise, output function value
    else

        % keep values in the serach interval
        X(X < -4.5) = inf;     X(X > 4.5) = inf;

        % split input vector X into x1, x2
        if size(X, 1) == 2
            x1 = X(1, :);        x2 = X(2, :);
        else
            x1 = X(:, 1);        x2 = X(:, 2);
        end

        % output function value
        varargout{1} = (1.5 - x1 + x1.*x2).^2 + (2.25 - x1 + x1.*x2.^2).^2 + (2.625 - x1 + x1.*x2.^3).^2;

    end

end


function val=superfactorial(n)
%%SUPERFACTORIAL Evaluate the superfactorial of a nonnegative real integer.
%                This is factorial(1)*factorial(2)*...factorial(n).
%
%INPUTS: n A scalar or matrix of real integers >=0.
%
%OUTPUTS: val A matrix having the same dimensions as n holding the
%             superfactorial of the values in n.
%
%The superfactorial is defined in [1]. For values 18 and below, the value
%is taken from a tabel. For higher values, the value is computed from the
%definition starting from the value at 18, maintaining the current
%factorial value at each step. Values 27 and higher overflow with double
%precision arithmetic.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Superfactorial." From MathWorld--A Wolfram Web
%    Resource. http://mathworld.wolfram.com/Superfactorial.html
%
%September 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%A table of values for 0<=n<=18
valTable=[1;
          1;
          2;
          12;
          288;
          34560;
          24883200;
          125411328000;
          5056584744960000;
          1834933472251084800000;
          6658606584104736522240000000;
          265790267296391946810949632000000000;
          127313963299399416749559771247411200000000000;
          792786697595796795607377086400871488552960000000000000;
          69113789582492712943486800506462734562847413501952000000000000000;
          90378331112371142262979521568630736335023247731599748366336000000000000000000;
          1890966832292234727042877370627225068196418587883634153182519380410368000000000000000000000;
          672593129192865130334217631473916658864122332882577979675277211683839238972899328000000000000000000000000;
          4306192564997715382115598640379294845786123319603755168023536027873932927153136831171640950784000000000000000000000000000];

if(any(n(:)<0)||any(n(:)~=fix(n(:)))||any(~isreal(n(:))))
    error('n must be a positive integer.')
end
val=zeros(size(n));

numVals=numel(n);

for curEl=1:numVals
    nCur=n(curEl);

    if(nCur<=18)
        val(curEl)=valTable(nCur+1);
    else
        factVal=6402373705728000;%factorial(18)
        val(curEl)=valTable(18+1);

        for curN=19:nCur
            %Quit if there was an overflow.
            if(~isfinite(val(curEl)))
                break;
            end
            factVal=factVal*curN;
            val(curEl)=val(curEl)*factVal;
        end
    end
end
end

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


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

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

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

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

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

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

end


function [centroid, area] = polygonCentroid(varargin)
%POLYGONCENTROID Compute the centroid (center of mass) of a polygon
%
%   CENTROID = polygonCentroid(POLY)
%   CENTROID = polygonCentroid(PTX, PTY)
%   Computes center of mass of a polygon defined by POLY. POLY is a N-by-2
%   array of double containing coordinates of vertices.
%
%   [CENTROID AREA] = polygonCentroid(POLY)
%   Also returns the (signed) area of the polygon.
%
%   Example
%     % Draws the centroid of a paper hen
%     x = [0 10 20  0 -10 -20 -10 -10  0];
%     y = [0  0 10 10  20  10  10  0 -10];
%     poly = [x' y'];
%     centro = polygonCentroid(poly);
%     drawPolygon(poly);
%     hold on; axis equal;
%     drawPoint(centro, 'bo');
%
%   References
%   algo adapted from P. Bourke web page
%
%   See also:
%   polygons2d, polygonArea, polygonSecondAreaMoments, drawPolygon
%

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

% Algorithme P. Bourke, vectorized version

% HISTORY
% 2012.02.24 vectorize code

% parse input arguments
if nargin == 1
    var = varargin{1};
    px = var(:,1);
    py = var(:,2);
elseif nargin == 2
    px = varargin{1};
    py = varargin{2};
end

% vertex indices
N = length(px);
iNext = [2:N 1];

% compute cross products
common = px .* py(iNext) - px(iNext) .* py;
sx = sum((px + px(iNext)) .* common);
sy = sum((py + py(iNext)) .* common);

% area and centroid
area = sum(common) / 2;
centroid = [sx sy] / 6 / area;


function cx = legendre_associated_normalized ( n, m, x )

%*****************************************************************************80
%
%% LEGENDRE_ASSOCIATED: normalized associated Legendre functions.
%
%  Discussion:
%
%    The unnormalized associated Legendre functions P_N^M(X) have
%    the property that
%
%      Integral ( -1 <= X <= 1 ) ( P_N^M(X) )^2 dX
%      = 2 * ( N + M )! / ( ( 2 * N + 1 ) * ( N - M )! )
%
%    By dividing the function by the square root of this term,
%    the normalized associated Legendre functions have norm 1.
%
%    However, we plan to use these functions to build spherical
%    harmonics, so we use a slightly different normalization factor of
%
%      sqrt ( ( ( 2 * N + 1 ) * ( N - M )! ) / ( 4 * pi * ( N + M )! ) )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 March 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%  Parameters:
%
%    Input, integer N, the maximum first index of the Legendre
%    function, which must be at least 0.
%
%    Input, integer M, the second index of the Legendre function,
%    which must be at least 0, and no greater than N.
%
%    Input, real X, the point at which the function is to be
%    evaluated.  X must satisfy -1 <= X <= 1.
%
%    Output, real CX(1:N+1), the values of the first N+1 function.
%
  if ( m < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!\n' );
    fprintf ( 1, '  Input value of M is %d\n', m );
    fprintf ( 1, '  but M must be nonnegative.\n' );
    error ( 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!' );
  end

  if ( n < m )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!\n' );
    fprintf ( 1, '  Input value of M = %d\n', m );
    fprintf ( 1, '  Input value of N = %d\n', n );
    fprintf ( 1, '  but M must be less than or equal to N.\n' );
    error ( 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!' );
  end

  if ( x < -1.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!\n' );
    fprintf ( 1, '  Input value of X = %f\n', x );
    fprintf ( 1, '  but X must be no less than -1.\n' );
    error ( 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!' );
  end

  if ( 1.0 < x )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!\n' );
    fprintf ( 1, '  Input value of X = %f\n', x );
    fprintf ( 1, '  but X must be no more than 1.\n' );
    error ( 'LEGENDRE_ASSOCIATED_NORMALIZED - Fatal error!' );
  end

  cx(1:m) = 0.0;

  cx(m+1) = 1.0;
  somx2 = sqrt ( 1.0 - x * x );

  fact = 1.0;
  for i = 1 : m
    cx(m+1) = -cx(m+1) * fact * somx2;
    fact = fact + 2.0;
  end

  if ( m < n )
    cx(m+2) = x * ( 2 * m + 1 ) * cx(m+1);
  end

  for i = m+2 : n
    cx(i+1) = ( ( 2 * i     - 1 ) * x * cx(i) ...
              + (   - i - m + 1 ) *     cx(i-1) ) ...
              / (     i - m     );
  end
%
%  Normalization.
%
  for mm = m : n
    factor = sqrt ( ( ( 2 * mm + 1 ) * r8_factorial ( mm - m ) ) ...
      / ( 4.0 * pi * r8_factorial ( mm + m ) ) );
    cx(mm+1) = cx(mm+1) * factor;
  end

  return
end


function result = p00_simpson ( prob, int_num )

%*****************************************************************************80
%
%% P00_SIMPSON applies the composite Simpson rule to integrate a function.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 December 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROB, the problem index.
%
%    Input, integer INT_NUM, the number of subintervals.
%
%    Output, real RESULT, the approximate integral.
%
  [ a, b ] = p00_lim ( prob );

  h = ( b - a ) / ( int_num );
%
%  This section of the code was rewritten to vectorize.
%
  x(1:2*int_num+1) = ( ( 2*int_num - ( 0 : 2*int_num ) ) * a   ...
                   + (               ( 0 : 2*int_num ) ) * b ) ...
                     / ( 2*int_num                         );

  if ( 1 == int_num )
    result = ...
                    p00_fun ( prob, 1,           x(1) ) ...
      + 4.0 *       p00_fun ( prob, int_num,     x(2) ) ...
      +             p00_fun ( prob, 1,           x(3) );
  else
    result = ...
                    p00_fun ( prob, 1,           x(1)               ) ...
      + 2.0 * sum ( p00_fun ( prob, int_num - 1, x(3:2:2*int_num-1) ) ) ...
      + 4.0 * sum ( p00_fun ( prob, int_num,     x(2:2:2*int_num)   ) )...
      +             p00_fun ( prob, 1,           x(2*int_num+1)     );
   end

  result = result * h / 6.0;

  return
end


% Equality constrained norm minimization.
%
% This script constructs a random equality-constrained norm minimization
% problem and solves it using CVX. You can also change p to +2 or +Inf
% to produce different results. Alternatively, you an replace
%     norm( A * x - b, p )
% with
%     norm_largest( A * x - b, 'largest', p )
% for 1 <= p <= 2 * n.

% Generate data
p = 1;
n = 10; m = 2*n; q=0.5*n;
A = randn(m,n);
b = randn(m,1);
C = randn(q,n);
d = randn(q,1);

% Create and solve problem
cvx_begin
   variable x(n)
   dual variable y
   minimize( norm( A * x - b, p ) )
   subject to
        y : C * x == d;
cvx_end

% Display results
disp( sprintf( 'norm(A*x-b,%g):', p ) );
disp( [ '   ans   =   ', sprintf( '%7.4f', norm(A*x-b,p) ) ] );
disp( 'Optimal vector:' );
disp( [ '   x     = [ ', sprintf( '%7.4f ', x ), ']' ] );
disp( 'Residual vector:' );
disp( [ '   A*x-b = [ ', sprintf( '%7.4f ', A*x-b ), ']' ] );
disp( 'Equality constraints:' );
disp( [ '   C*x   = [ ', sprintf( '%7.4f ', C*x ), ']' ] );
disp( [ '   d     = [ ', sprintf( '%7.4f ', d   ), ']' ] );
disp( 'Lagrange multiplier for C*x==d:' );
disp( [ '   y     = [ ', sprintf( '%7.4f ', y ), ']' ] );


% Minimize stopband ripple of a linear phase lowpass FIR filter
% "Filter design" lecture notes (EE364) by S. Boyd
% (figures are generated)
%
% Designs a linear phase FIR lowpass filter such that it:
% - minimizes the maximum passband ripple
% - has a constraint on the maximum stopband attenuation
%
% This is a convex problem.
%
%   minimize   delta
%       s.t.   1/delta <= H(w) <= delta     for w in the passband
%              |H(w)| <= atten_level        for w in the stopband
%
% where H is the frequency response function and variables are
% delta and h (the filter impulse response).
%
% Written for CVX by Almir Mutapcic 02/02/06

%********************************************************************
% user's filter specifications
%********************************************************************
% filter order is 2n+1 (symmetric around the half-point)
n = 10;

wpass = 0.12*pi;        % passband cutoff freq (in radians)
wstop = 0.24*pi;        % stopband start freq (in radians)
atten_level = -30;      % stopband attenuation level in dB

%********************************************************************
% create optimization parameters
%********************************************************************
N = 30*n+1;                            % freq samples (rule-of-thumb)
w = linspace(0,pi,N);
A = [ones(N,1) 2*cos(kron(w',[1:n]))]; % matrix of cosines

% passband 0 <= w <= w_pass
ind = find((0 <= w) & (w <= wpass));   % passband
Ap  = A(ind,:);

% transition band is not constrained (w_pass <= w <= w_stop)

% stopband (w_stop <= w)
ind = find((wstop <= w) & (w <= pi));  % stopband
Us  = 10^(atten_level/20)*ones(length(ind),1);
As  = A(ind,:);

%********************************************************************
% optimization
%********************************************************************
% formulate and solve the linear-phase lowpass filter design
cvx_begin
  variable delta
  variable h(n+1,1);

  minimize( delta )
  subject to
    % passband bounds
    Ap*h <= delta;
    inv_pos(Ap*h) <= delta;

    % stopband bounds
    abs( As*h ) <= Us;
cvx_end

% check if problem was successfully solved
disp(['Problem is ' cvx_status])
if ~strfind(cvx_status,'Solved')
  return
else
  % construct the full impulse response
  h = [flipud(h(2:end)); h];
  fprintf(1,'The optimal minimum passband ripple is %4.3f dB.\n\n',...
            20*log10(delta));
end

%********************************************************************
% plots
%********************************************************************
figure(1)
% FIR impulse response
plot([0:2*n],h','o',[0:2*n],h','b:')
xlabel('t'), ylabel('h(t)')

figure(2)
% frequency response
H = exp(-j*kron(w',[0:2*n]))*h;
% magnitude
subplot(2,1,1)
plot(w,20*log10(abs(H)),[wstop pi],[atten_level atten_level],'r--');
axis([0,pi,-40,10])
xlabel('w'), ylabel('mag H(w) in dB')
% phase
subplot(2,1,2)
plot(w,angle(H))
axis([0,pi,-pi,pi])
xlabel('w'), ylabel('phase H(w)')


function fx = camel ( n, x )

%*****************************************************************************80
%
%% CAMEL evaluates the six-hump camel back function.
%
%  Discussion:
%
%    This function has been modified from its original definition by
%    multiplying by -1 and then adding 1, so that there is a small island
%    of positivity within the box [-2.5,2.5]x[-2.5,2.5].
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 December 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points.
%
%    Input, real X(N,2), the point coordinates.
%
%    Output, real FX(N), the function values.
%
  fx = zeros ( n, 1 );

  fx = - ...
  ( ...
      ( 4 - 2.1 * x(:,1).^2 + 0.33 * x(:,1).^4 ) .* x(:,1).^2 ...
    + x(:,1) .* x(:,2) + 4 * ( x(:,2).^2 - 1 ) .* x(:,2).^2 ...
  ) + ones ( n, 1 );

  return
end


function [ vX ] = LevinsonRecursion( mT, vY )
% ----------------------------------------------------------------------------------------------------- %
%[ vX ] = LevinsonRecursion( mT, vY )
% Solves Linear System mT * vX = vY where the Matrix 'mT' is a Toeplitz
% Matrix using Levinson Recursion improved speed (Complexity of N^2 instead
% of N^3). Input:
%   - mT    -   Input Matrix.
%               Matrix with a Toeplitz Structure.
%               Structure: Matrix (N x N).
%               Type: 'Single' / 'Double'.
%               Range: (-inf, inf).
%   - vY    -   Input Vector.
%               Structure: Column Vector (N x 1).
%               Type: 'Single' / 'Double'.
%               Range: (-inf, inf).
% Output:
%   - vX    -   Output Vector.
%               The solution of the system mT * vX = vY.
%               Structure: Column Vector (N x 1).
%               Type: 'Single' / 'Double'.
%               Range: (-inf, inf).
% References
%   1.  Levinson Recursion (Wikipedia) - https://en.wikipedia.org/wiki/Levinson_recursion
% Remarks:
%   1.  Joint work with Yair Shemer.
%   2.  This implementation supports only rectangular matrices.
% TODO:
%   1.  A
% Release Notes:
%   -   1.0.000     15/02/2017  Royi Avital
%       *   First realease version.
% ----------------------------------------------------------------------------------------------------- %

numRows = size(mT, 1); %<! Square Matrix

vF = zeros([numRows, 1]); %<! Forward Vector
vB = zeros([numRows, 1]); %<! Backward Vector
vX = zeros([numRows, 1]);

% Initialized vF, vB and vX;
vF(1) = 1 / mT(1, 1);
vB(1) = 1 / mT(1, 1);
vX(1) = vY(1) / mT(1, 1);

for iRow = 2 : numRows
    % Calculate the epsilons (error expressions)
    epsF = mT(iRow, 1:(iRow - 1)) * vF(1:(iRow - 1));
    epsB = mT(1, 2:iRow) * vB(1:(iRow - 1));
    epsX = mT(iRow, 1:(iRow - 1)) * vX(1:(iRow - 1));

    % Given vF, vB and vX with size n-1 find those vectors with size n
    vFPrev      = vF;
    scalingFctr = 1 / (1 - (epsF * epsB));

    vF(1:iRow) = scalingFctr * vF(1:iRow) - (epsF * scalingFctr) * [0; vB(1:(iRow - 1))];
    vB(1:iRow) = scalingFctr * [0; vB(1:(iRow - 1))] - (epsB * scalingFctr) * vFPrev(1:iRow);
    vX(1:iRow) = vX(1:iRow) + (vY(iRow) - epsX) * vB(1:iRow);
end

end


function [nb_sources]=source_number_detection_IC(received_signal,criterion,display)

%HELP source_number_detection_IC
%
%Detection of the number of sources with information criteria. The method
%assumes that the noise is spatially white.
%
%Input:     received_signal
%           criterion ('Akaike' or 'MDL')
%           (optional) Display criterion if non empty
%Sorties:   nb_sources
%
%Example:   X=randn(3,500); %3 sources
%           H=randn(10,3)+i*randn(10,3); %10 receivers
%           B=2*(randn(10,500)+i*randn(10,500));
%           Y=H*X+B; %MIMO Mixing Model
%           source_number_detection_IC(Y,'MDL',1)
%
%Reference: [WAX85] Wax, M. and Kailath, T., "Detection of signals by information
%theoretic criteria", IEEE Transactions on Acoustics, Speech and Signal
%Processing, 1985.

[Nb_receivers,Nb_samples]=size(received_signal);
%Computation of the covariance matrix
covariance=received_signal*received_signal'/Nb_samples;
%eigenvalue decomposition
[U,V]=eig(covariance);
%sort the eigenvalue in the decreasing order
eigenvalues=sort(diag(V),'descend');

%Compute criterion
for k=0:Nb_receivers-1
    coef=1/(Nb_receivers-k);
    a=coef*sum(eigenvalues(k+1:Nb_receivers));
    g=prod(eigenvalues(k+1:Nb_receivers)).^(coef);
    akaike_criterion(k+1)=-log(((g/a)^(Nb_samples*(Nb_receivers-k))))+k*(2*Nb_receivers-k);
    MDL_criterion(k+1)=-log(((g/a)^(Nb_samples*(Nb_receivers-k))))+0.5*k*(2*Nb_receivers-k)*log(Nb_samples);
end

switch criterion
    case 'AIC'
        criterion_value=akaike_criterion;
    case 'MDL'
        criterion_value=MDL_criterion;
end
[criterion_value_min,nb_sources]=min(criterion_value);
nb_sources=nb_sources-1; %retrieve 1 because the value k=0 is stocked in the index 1.

if nargin > 2
   plot(0:Nb_receivers-1,criterion_value);
   grid;
   hold on
   plot(nb_sources,criterion_value_min,'ro');
   hold off
   ylabel('Criterion value')
   xlabel('Number of sources')
end

%Created by: Vincent Choqueuse, PhD (vincent.choqueuse@gmail.com)