function [phi] = evalPhi( r );
%
% [phi] = evalPhi( r );
%
%  Calculates phi( r ), phi the discrete delta function (without scaling)
%
%  Returns:
%     phi = value of unscaled discrete delta function at each point, r
%
%  Input:
%     r   = the points to evaluate the discrete delta function at
%
%  Note:
%     This code doesn't handle wrapping across periodic boundaries.
%
%
%  License: This code is free to use for any purposes, provided
%           any publications resulting from the use of this code
%           reference the original code/author.
%
%  Author:  Samuel Isaacson (isaacson@math.utah.edu)
%  Date:    11/2007
%
%  Please notify the author of any bugs, and contribute any
%  modifications or bug fixes back to the original author.
%
%  Disclaimer:
%   This code is provided as is. The author takes no responsibility
%   for its results or effects.

phi  = zeros(length(r), 1);
aR   = abs( r );
idx1 = find( aR < 1 );
idx2 = find( aR >= 1 );

rT        = aR(idx1);
phi(idx1) = 3 - 2*rT + sqrt( 1 + 4*rT - 4*rT.*rT );

rT        = aR(idx2);
phi(idx2) = 5 - 2*rT - sqrt( -7 + 12*rT - 4*rT.*rT );

phi = phi / 8;


function centroid = polyhedron_centroid_3d ( coord, maxorder, face_num, node, ...
  node_num, order )

%*****************************************************************************80
%
%% POLYHEDRON_CENTROID_3D computes the centroid of a polyhedron in 3D.
%
%  Discussion:
%
%    The centroid can be computed as the volume-weighted average of
%    the centroids of the tetrahedra defined by choosing a point in
%    the interior of the polyhedron, and using as a base every triangle
%    created by triangulating the faces of the polyhedron.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real COORD(3,NODE_NUM), the vertices.
%    The vertices may be listed in any order.
%
%    Input, integer MAXORDER, the maximum number of vertices that make
%    up a face of the polyhedron.
%
%    Input, integer FACE_NUM, the number of faces of the polyhedron.
%
%    Input, integer NODE(FACE_NUM,MAXORDER).  Face I is defined by
%    the vertices NODE(I,1) through NODE(I,ORDER(I)).  These vertices
%    are listed in neighboring order.
%
%    Input, integer NODE_NUM, the number of points stored in COORD.
%
%    Input, integer ORDER(FACE_NUM), the number of vertices making up
%    each face.
%
%    Output, real CENTROID(3), the centroid of the polyhedron.
%
  dim_num = 3;
%
%  Compute a point in the interior.
%  We take the area-weighted centroid of each face.
%
  point(1:dim_num) = 0.0;
  area = 0.0;

  for face = 1 : face_num

    vert_num = order(face);

    v(1:dim_num,1:vert_num) = coord(1:dim_num,node(face,1:vert_num));

    [ polygon_area, normal ] = polygon_area_3d ( vert_num, v );

    polygon_centroid(1:dim_num) = polygon_centroid_3d ( vert_num, v );

    point(1:dim_num) = point(1:dim_num) + polygon_area * polygon_centroid(1:dim_num);

    area = area + polygon_area;

  end

  point(1:dim_num) = point(1:dim_num) / area;
%
%  Now triangulate each face.
%  For each triangle, consider the tetrahedron created by including POINT.
%
  centroid(1:dim_num) = 0.0;
  volume = 0.0;

  for face = 1 : face_num

    n3 = node(face,order(face));

    for vert = 1 : order(face) - 2

      n1 = node(face,vert);
      n2 = node(face,vert+1);

      tetra(1:dim_num,1:4) = [ ...
        coord(1:dim_num,n1)'; coord(1:dim_num,n2)'; coord(1:dim_num,n3)'; point(1:dim_num) ]';

      tetra_volume = tetrahedron_volume_3d ( tetra );

      tetra_centroid(1:dim_num) = tetrahedron_centroid_3d ( tetra );

      centroid(1:dim_num) = centroid(1:dim_num) + tetra_volume * tetra_centroid(1:dim_num);

      volume = volume + tetra_volume;

    end
  end

  centroid(1:dim_num) = centroid(1:dim_num) / volume;

  return
end


function xyPoints=getEllipseHullPoints(z,A,gammaVal,numPoints,invertA)
%%GETELLIPSHULLPOINTS  Consider an ellipsoid in 3D (x,y,z) coordinates. For
%       every fixed z coordinate, if the x-y plane at the z coordinate
%       intersects the ellipsoid, it cuts an ellipse. For example, the
%       function projEllipse2ZPlane gets the parameters of the ellipse of
%       intersection. This function gets points marking the outer limits of
%       all of those ellipses in the x-y plane (the hull of the ellipses).
%
%INPUTS: z A 3XN vector corresponding to the centers of the N ellipses for
%          which points should be obtained.
%        A A 3X3XN set of N positive definite matrices that specify the
%          size and shape of the ellipsoids, where a point zp is on the ith
%          ellipsoid if
%          (zp-z(:,i))'*A(:,:,i)*(zp-z(:,i))=gammaVal (if invertA is true,
%          then replace A(:,:,i) with inv(A(:,:,i))).
% gammaVal An optional parameter specifying the size of the ellipse/
%          ellipsoid. If omitted or an empty matrix is passed, then
%          gammaVal=18.8049 is used. This is approximately the value for a
%          99.97% confidence region if A are inverse covariance matrices of
%          a Gaussian distribution. gammaVal must be positive gammaVal must
%          be positive.
% numPoints An optional parameter specifying how many points should be
%          generated. The default if omitted or an empty matrix is passed
%          is 500.
%  invertA If this is true, then A is inverted before use. The default if
%          omitted or an empty matrix is passed is false.
%
%OUTPUTS: xyPoints A 2XnumPointsXN set of the points for each of the
%                  ellipsoid projection hulls.
%
%The 3D ellipsoid (with the coordinate system shited to put the origin at
%the center) is defined as x'*R*x=gammaVal. We can rewrite this as
%[r*u,z]*R*[r*u;z]=gammaVal
%where r is a positive scalar and u is a 2X1 unit vector. The matrix R can
%be broken up accordingly as
%R=[Rxy, rz;
%   rz', rzz];
%We want the maximum extent of the ellipsoid in the x-y plane for each
%direction (as specified by u). This will provide the hull of the ellipsoid
%points. Thus, we perform the optimization:
% maximize (over r,z) r^2
% such that r^2*u'*Rxy*u+2*r*z*rz'*u+z^2*rzz=gammaVal
%where the constraint is just from rewriting the expression for the
%definition of an ellipsoid. Writing the Lagrangian, (with lambda as the
%Lagrangian parameter) taking derivatives and setting them equal to 0, we
%get two additional equations. Solving those two equations with the
%original constraint, we get expressions for r, z, and lambda. Choosing the
%solution such that r is positive and nonzero, one gets the expressions
%implemented in this function.
%
%December 2020 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<5||isempty(invertA))
    invertA=false;
end

if(nargin<4||isempty(numPoints))
    numPoints=500;
end

if(nargin<3||isempty(gammaVal))
    gammaVal=18.8049;
end

if(invertA)
    A=applyFunToEachMatrix(@inv,A);
end

numEllipse=size(z,2);

theta=linspace(-pi,pi,numPoints);
u=[cos(theta);
   sin(theta)];
xyPoints=zeros(2,numPoints,numEllipse);
for curEllipse=1:numEllipse
    Rxyrzz=A(1:2,1:2,curEllipse)*A(3,3,curEllipse);
    rz=A(1:2,3,curEllipse);
    rzzGamma=A(3,3,curEllipse)*gammaVal;
    zXYCur=z(1:2,curEllipse);

    for k=1:numPoints
        uCur=u(:,k);

        r=sqrt(rzzGamma/(uCur'*Rxyrzz*uCur-(rz'*uCur)^2));
        xyPoints(:,k,curEllipse)=zXYCur-r*uCur;
    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 [C, sigma] = dataset3Params(X, y, Xval, yval)
%EX6PARAMS returns your choice of C and sigma for Part 3 of the exercise
%where you select the optimal (C, sigma) learning parameters to use for SVM
%with RBF kernel
%   [C, sigma] = EX6PARAMS(X, y, Xval, yval) returns your choice of C and
%   sigma. You should complete this function to return the optimal C and
%   sigma based on a cross-validation set.
%

% You need to return the following variables correctly.
C = 1;
sigma = 0.3;

% ====================== YOUR CODE HERE ======================
% Instructions: Fill in this function to return the optimal C and sigma
%               learning parameters found using the cross validation set.
%               You can use svmPredict to predict the labels on the cross
%               validation set. For example,
%                   predictions = svmPredict(model, Xval);
%               will return the predictions on the cross validation set.
%
%  Note: You can compute the prediction error using
%        mean(double(predictions ~= yval))
%

results = eye(64,3);
errorRow = 0;

for C_test = [0.01 0.03 0.1 0.3 1, 3, 10 30]
    for sigma_test = [0.01 0.03 0.1 0.3 1, 3, 10 30]
        errorRow = errorRow + 1;
        model = svmTrain(X, y, C_test, @(x1, x2) gaussianKernel(x1, x2, sigma_test));
        predictions = svmPredict(model, Xval);
        prediction_error = mean(double(predictions ~= yval));

        results(errorRow,:) = [C_test, sigma_test, prediction_error];
    end
end

sorted_results = sortrows(results, 3); % sort matrix by column #3, the error, ascending

C = sorted_results(1,1);
sigma = sorted_results(1,2);

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

end


function [ wval, dwdx ] = r8poly_lagrange_factor ( npol, xpol, xval )

%*****************************************************************************80
%
%% R8POLY_LAGRANGE_FACTOR evaluates the polynomial Lagrange factor at a point.
%
%  Formula:
%
%    W(X) = Product ( 1 <= I <= NPOL ) ( X - XPOL(I) )
%
%  Discussion:
%
%    Suppose F(X) is at least N times continuously differentiable in the
%    interval [A,B].  Pick NPOL distinct points XPOL(I) in [A,B] and compute
%    the interpolating polynomial P(X) of order NPOL ( and degree NPOL-1)
%    which passes through all the points ( XPOL(I), F(XPOL(I)) ).
%    Then in the interval [A,B], the maximum error
%
%      abs ( F(X) - P(X) )
%
%    is bounded by:
%
%      C * FNMAX * W(X)
%
%    where
%
%      C is a constant,
%      FNMAX is the maximum value of the NPOL-th derivative of F in [A,B],
%      W(X) is the Lagrange factor.
%
%    Thus, the value of W(X) is useful as part of an estimated bound
%    for the interpolation error.
%
%    Note that the Chebyshev abscissas have the property that they minimize
%    the value of W(X) over the interval [A,B].  Hence, if the abscissas may
%    be chosen arbitrarily, the Chebyshev abscissas have this advantage over
%    other choices.
%
%    For a set of points XPOL(I), 1 <= I <= NPOL, the IPOL-th Lagrange basis
%    polynomial L(IPOL)(X), has the property:
%
%      L(IPOL)( XPOL(J) ) = delta ( IPOL, J )
%
%    and may be expressed as:
%
%      L(IPOL)(X) = W(X) / ( ( X - XPOL(IPOL) ) * W'(XPOL(IPOL)) )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NPOL, the number of abscissas.
%    NPOL must be at least 1.
%
%    Input, real XPOL(NPOL), the abscissas, which should
%    be distinct.
%
%    Input, real XVAL, the point at which the Lagrange
%    factor is to be evaluated.
%
%    Output, real WVAL, the value of the Lagrange factor at XVAL.
%
%    Output, real DWDX, the derivative of W with respect to XVAL.
%
  wval = prod ( xval - xpol(1:npol) );

  dwdx = 0.0;

  for i = 1 : npol

    term = 1.0;

    for j = 1 : npol
      if ( i ~= j )
        term = term * ( xval - xpol(j) );
      end
    end

    dwdx = dwdx + term;

  end

  return
end


function ry = vecroty(angle)
%
% Function Name:
%
%   vecroty - Transformation matrix for a rotation around the y axis.
%
% Calling Sequence:
%
%   ry = vecroty(angle);
%
% Parameters:
%
%   angle		: rotation angle defined in radians
%
%   ry		: (4x4) Transformation matrix.
%
%
% Description:
%
%   Return the (4x4) Transformation matrix for a rotation about the y axis
%   by the defined angle.
%
%   The matrix is:
%
%         [  cos(angle)       0        sin(angle)       0]
%         [      0            1            0            0]
%         [ -sin(angle)       0        cos(angle)       0]
%         [      0            0            0            1]
%
% Examples:
%
%    Rotate the NURBS line (0.0 0.0 0.0) - (3.0 3.0 3.0) by 45 degrees
%    around the y-axis
%
%    line = nrbline([0.0 0.0 0.0],[3.0 3.0 3.0]);
%    trans = vecroty(%pi/4);
%    rline = nrbtform(line, trans);
%
% See:
%
%    nrbtform

%  Dr D.M. Spink
%  Copyright (c) 2000.

sn = sin(angle);
cn = cos(angle);
ry = [cn 0 sn 0; 0 1 0 0; -sn 0 cn 0; 0 0 0 1];


function a=randNestedParenth(n)
%%RANDNESTEDPARENTH Obtain a random character string of randomly nested
%                   parentheses. Such parantheses can represent random
%                   binary trees.
%
%INPUTS: n The number of open-closed parenthesis pairs.
%
%OUTPUTS: a A (2*n)X1 character string of n parenthesis pairs, with the
%           open parenthesis always coming before the close one.
%
%This function implements Algorithm W of Chapter 7.2.1.6 of [1].
%
%EXAMPLE:
% a=randNestedParenth(5).'
%We transpose it to make it easier to read.
%
%REFERENCES
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 4A: Combinatorial
%    Algorithms, Part I, Boston: Addison-Wesley, 2011.
%
%October 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

p=n;
q=n;
m=1;
%Allocate space for the random set of nested parentheses.
a=repmat(' ',2*n,1);

while(q~=0)
    while(1)
        upperBound=(q+p)*(q-p+1);
        X=randi(upperBound-1);

        if(X<(q+1)*(q-p))
            q=q-1;
            a(m)=')';
            m=m+1;
            break;
        end
        p=p-1;
        a(m)='(';
        m=m+1;
    end
end
end

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


function rad=dms2rad(dms)
% DMS2RAD  Converts degrees-minutes-seconds to radians.
%   Vectorized.
% Version: 12 Mar 00
% Useage:  rad=dms2rad(dms)
% Input:   dms - [d m s] array of angles in deg-min-sec, where
%                d = vector of degrees
%                m = vector of minutes
%                s = vector of seconds
% Output: rad - vector of angles in radians

% Copyright (c) 2011, Michael R. Craymer
% All rights reserved.
% Email: mike@craymer.com

d=dms(:,1);
m=dms(:,2);
s=dms(:,3);
dec=abs(d)+abs(m)./60+abs(s)./3600;
rad=dec.*pi./180;
ind=(d<0 | m<0 | s<0);
rad(ind)=-rad(ind);


%................................................................

function stiffness=formStiffness2D(GDof,numberElements,...
    elementNodes,numberNodes,nodeCoordinates,C,thickness)

% compute stiffness matrix
% for plane stress Q8 elements

stiffness=zeros(GDof);

% 3 by 3 quadrature
[gaussWeights,gaussLocations]=gauss2d('3x3');

for e=1:numberElements
  numNodePerElement = length(elementNodes(e,:));
  numEDOF = 2*numNodePerElement;
  elementDof=zeros(1,numEDOF);
  for i = 1:numNodePerElement
      elementDof(2*i-1)=2*elementNodes(e,i)-1;
      elementDof(2*i)=2*elementNodes(e,i);
  end

  % cycle for Gauss point
  for q=1:size(gaussWeights,1)
    GaussPoint=gaussLocations(q,:);
    xi=GaussPoint(1);
    eta=GaussPoint(2);

% shape functions and derivatives
    [shapeFunction,naturalDerivatives]=shapeFunctionQ8(xi,eta);

% Jacobian matrix, inverse of Jacobian,
% derivatives w.r.t. x,y
    [Jacob,invJacobian,XYderivatives]=...
        Jacobian(nodeCoordinates(elementNodes(e,:),:),naturalDerivatives);

%  B matrix
    B=zeros(3,numEDOF);
    B(1,1:2:numEDOF)       = XYderivatives(:,1)';
    B(2,2:2:numEDOF)  = XYderivatives(:,2)';
    B(3,1:2:numEDOF)       = XYderivatives(:,2)';
    B(3,2:2:numEDOF)  = XYderivatives(:,1)';

% stiffness matrix
    stiffness(elementDof,elementDof)=...
        stiffness(elementDof,elementDof)+...
        B'*C*thickness*B*gaussWeights(q)*det(Jacob);
  end
end


function [qp]=zn2fr(input)
% [qp]=zn2fr(input)
% Ziegler-Nichols PID controller for processes of 2nd order.
% This function computes parameters of the controller (q0, q1, q2, p1, p2).
% Controller is based on forward rectangular method of discretization.
% Transfer function of the controller is as follows:
%
%            q0 + q1*z^-1 + q2*z^-2     q0 + q1*z^-1 + q2*z^-2
% G(z^-1) = ------------------------ = ------------------------
%                  1 - z^-1              1 + p1*z^-1 + p2*z^-2
%
% where p1=-1 and p2=0.
%
% Transfer function of the controlled system is:
%
%               b1*z^-1 + b2*z^-2
% Gs(z^-1) = -----------------------
%             1 + a1*z^-1 + a2*z^-2
%
% Input: input ... input parameters
%                  input(1) ... a1
%                  input(2) ... b1
%                  input(3) ... a2
%                  input(4) ... b2
%                  input(5) ... sample time T0
% Output: qp ... controller parameters
%                qp(1) ... q0
%                qp(2) ... q1
%                qp(3) ... q2
%                qp(4) ... -1   (p1 of the controller)
%                qp(5) ... 0    (p2 of the controller)

a1 = input(1);
b1 = input(2);
a2 = input(3);
b2 = input(4);
T0 = input(5);

% compute ultimate gain and frequency
[Kpu, Tu] =  ultim([b1 b2],[a1 a2],T0);

Kp = 0.6*Kpu;
Ti = Tu/2;
Td = Tu/8;

q0 = Kp*(1+Td/T0);
q1 = -Kp*(1-T0/Ti+2*Td/T0);
q2 = Kp*(Td/T0);
p1 = -1;
p2 = 0;

qp=[q0; q1; q2; p1; p2];


function ex2bvp
%EX2BVP  Example 2 of the BVP tutorial.
%   A standard linear problem with a boundary layer at the origin.
%   The differential equation y'' + 3*p*y/(p + t^2)^2 = 0 has the
%   analytical solution y(t) = t/sqrt(p + t^2).  The parameter p
%   is taken to be 1e-5, a common value in tests.  The solution is
%   to have specified values at t = -0.1 and +0.1, values taken from
%   this analytical solution.
%
%   The default RelTol of 1e-3 gives an acceptable solution, but
%   reducing RelTol to 1e-4 resolves better the boundary layer.  A
%   constant guess is used for RelTol = 1e-3.  The same guess could be
%   used for RelTol = 1e-4, but a very much better guess is provided
%   by the solution previously computed for RelTol = 1e-3.

% Copyright 2002, The MathWorks, Inc.

% Evaluate the analytical solution for comparison.
tt = -0.1:0.01:+0.1;
p = 1e-5;
yy = tt ./ sqrt(p + tt .^2);

options = bvpset('stats','on','Fjacobian',@ex2Jac);

% BVPINT is used to specify an initial guess for the mesh of 10
% equally spaced points.  A constant guess based on a straight line
% between the boundary values for y is 0 for y(t) and 10 for y'(t).
solinit = bvpinit(linspace(-0.1,0.1,10),[0 10]);

sol = bvp4c(@ex2ode,@ex2bc,solinit, options);
t = sol.x;
y = sol.y;

figure
plot(t,y(1,:),tt,yy,'*')
axis([-0.1 0.1 -1.1 1.1])
title(['Linear boundary layer problem with RelTol = 1e-3.'])
xlabel('t')
ylabel('y and analytical (*) solutions')

fprintf('\n');

% A smaller RelTol is used to resolve better the boundary layer.
% The previous solution provides an excellent guess.
options = bvpset(options,'RelTol',1e-4);
sol = bvp4c(@ex2ode,@ex2bc,sol,options);
t = sol.x;
y = sol.y;

figure
plot(t,y(1,:),tt,yy,'*')
axis([-0.1 0.1 -1.1 1.1])
title(['Linear boundary layer problem with RelTol = 1e-4.'])
xlabel('t')
ylabel('y and analytical (*) solutions')

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

function dydt = ex2ode(t,y)
%EX2ODE  ODE function for Example 2 of the BVP tutorial.
%   The components of y correspond to the original variables
%   as  y(1) = y, y(2) = y'.
p = 1e-5;
dydt = [ y(2)
        -3*p*y(1)/(p+t^2)^2];

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

function dfdy = ex2Jac(t,y)
%EX2JAC  The Jacobian of the ODE function for Example 2 of the BVP tutorial.
p = 1e-5;
dfdy = [          0        1
         -3*p/(p+t^2)^2    0 ];

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

function res = ex2bc(ya,yb)
%EX2BC  Boundary conditions for Example 2 of the BVP tutorial.
%   The boundary conditions are that the solution should agree
%   with the values of an analytical solution at both a and b.
p = 1e-5;
yatb = 0.1/sqrt(p + 0.01);
yata = - yatb;
res = [ ya(1) - yata
        yb(1) - yatb ];


function coeffsRet=polyIntMultiDim(coeffs,intDim,intConst)
%%POLYINTMULTIDIM Compute the indefinite integral of a multivariate
%                 polynomial with respect to a particular dimension given a
%                 hypermatrix of its coefficients (including cross terms).
%
%INPUTS: coeffs A hypermatrix of the coefficients for the multivariate
%               polynomial. These are arranged such that
%               coeffs(a1,a2,a3...an) corresponds to the coefficient of an
%               x1^(a1-1)*x2^(a2-1)*x3^(a3-1)...xn^(an-1) term.  Thus, the
%               number of indices coeffs takes is equal to the
%               dimensionality of x (not counting singleton dimensions at
%               the end of coeffs). Note that this ordering is the reverse
%               that used in the 1D polyval function that is built into
%               Matlab. The number of elements for each index in coeffs is
%               the maximum order of that dimension +1.
%        intDim The dimension of x (index of coeffs) with respect to which
%               the integral is to be taken.
%      intConst The integration constant. If this parameter is omitted or
%               an empty matrix is passed, a default value of 0 is used.
%
%OUTPUTS: coeffsRet The indefinite integral of the coeffs hypermatrix.
%
%This function is just implemented using the basic rules of polynomial
%integration.
%
%As an example, consider the multivariate polynomial:
%14+3*x1^2-18*x2+12*x1*x3-3*x2*x3
%The integrals with respect to the first, second and third variables are
% coeffs=zeros(3,2,2);
% coeffs(0+1,0+1,0+1)=14;
% coeffs(2+1,0+1,0+1)=3;
% coeffs(0+1,1+1,0+1)=-18;
% coeffs(1+1,0+1,1+1)=12;
% coeffs(0+1,1+1,1+1)=-3;
% intCoeffs1=polyIntMultiDim(coeffs,1);
% intCoeffs2=polyIntMultiDim(coeffs,2);
% intCoeffs3=polyIntMultiDim(coeffs,3);
%One will see that intCoeffs1 corresponds to
%14*x1+x1^3-18*x1*x2+6*x1^2*x3-3*x1*x2*x3
%intCoeffs2 corresponds to
%14*x2*+3*x1^2*x2-9*x2^2+12*x1*x2*x3-(3/2)*x2^2*x3
%and intCoeffs3 corresponds to.
%14*x3+3*x1^2*x3-18*x2*x3+6*x1*x3^2-(3/2)*x2*x3^2
%
%Note that the fucntion can be used with variables that are not present in
%the original polynomial. In the above example,
% intCoeffs4=polyIntMultiDim(coeffs,4);
%provides coefficients corresponding to
%14*x4+3*x1^2*x4-18*x2*x4+12*x1*x3*x4-3*x2*x3*x4
%
%August 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

dimSizeList=size(coeffs);
numIdx=length(dimSizeList);
totalEls=prod(dimSizeList);

%If the dimension of integration is a singleton dimension that has been
%suppressed from the end of dimSizeList, then we must add in all of the
%missing singleton dimensions.
dimRetSizeList=[dimSizeList,ones(1,intDim-numIdx)];
%Integration will increase the maximum degree of the term over which
%integration is performed by one, meaning that the matrix has to be made
%larger.
dimRetSizeList(intDim)=dimRetSizeList(intDim)+1;

%Allocate space for the return coefficients.
coeffsRet=zeros(dimRetSizeList);

%We will now loop through all of the values in the original coefficient
%set, adjusting them and inserting them into the proper location in the new
%modified coefficient set, after multiplication by the appropriate
%constant.

if(intDim>numIdx)
%This is used when integrating over a trailing singleton dimension.
    indicesFull=ones(numIdx,1);
    indicesFull(intDim)=2;
end
for curEl=1:totalEls
    curCoeff=coeffs(curEl);
    indices=index2NDim(dimSizeList,curEl);

    if(intDim<=numIdx)
        constVal=1/indices(intDim);
        indices(intDim)=indices(intDim)+1;
        coeffsRet(nDim2Index(dimRetSizeList,indices))=constVal*curCoeff;
    else%If we are integration over a trailing singleton dimension.
        indicesFull(1:numIdx)=indices;
        coeffsRet(nDim2Index(dimRetSizeList,indicesFull))=curCoeff;
    end
end

%Add in the integration constant. It is the zeroth-order term.
coeffsRet(1)=intConst;

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 = quad_fun ( n )

%*****************************************************************************80
%
%% QUAD_FUN demonstrates MATLAB's PARFOR command for parallel programming.
%
%  Discussion:
%
%    This function estimates an integral using the composite trapezoidal rule.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 March 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points to use.
%
%    Output, real VALUE, the estimate for the integral.
%
  a = 0.0;
  b = 1.0;

  value = 0.0;
  h = ( b - a ) / ( n - 1 );

  parfor i = 1 : n

    x = ( ( n - i ) * a + ( i - 1 ) * b ) / ( n - 1 );

    fx = f ( x );

    if ( i == 1 )
      value = value + 0.5 * fx * h
    elseif ( i < n )
      value = value +       fx * h;
    elseif ( i == n )
      value = value + 0.5 * fx * h;
    end

  end

  return
end
function value = f ( x )

%*****************************************************************************80
%
%% F is the function to be integrated.
%
%  Discussion:
%
%    The integral of F(X) from 0 to 1 is exactly PI.
%
%  Modified:
%
%    17 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the values where the integrand is to be evaluated.
%
%    Output, real VALUE, the integrand values.
%
  value = 4.0 ./ ( 1 + x.^2 );

  return
end


function [center,radius] = minboundsphere(xyz)
% minboundsphere: Compute the minimum radius enclosing sphere of a set of (x,y,z) triplets
% usage: [center,radius] = minboundsphere(xyz)
%
% arguments: (input)
%  xyz - nx3 array of (x,y,z) triples, describing points in R^3
%        as rows of this array.
%
%
% arguments: (output)
%  center - 1x3 vector, contains the (x,y,z) coordinates of
%        the center of the minimum radius enclosing sphere
%
%  radius - scalar - denotes the radius of the minimum
%        enclosing sphere
%
%
% Example usage:
% Sample uniformly from the interior of a unit sphere.
% As the sample size increases, the enclosing sphere
% should asymptotically approach center = [0 0 0], and
% radius = 1.
%
%   xyz = rand(10000,3)*2-1;
%   r = sqrt(sum(xyz.^2,2));
%   xyz(r>1,:) = [];          % 5156 points retained
%   tic,[center,radius] = minboundsphere(xyz);toc
%
%   Elapsed time is 0.199467 seconds.
%
%   center = [0.00017275   8.5006e-05   0.00012015]
%
%   radius = 0.9999
%
% Example usage:
% Sample from the surface of a unit sphere. Within eps
% or so, the result should be center = [0 0 0], and radius = 1.
%
%   xyz = randn(10000,3);
%   xyz = xyz./repmat(sqrt(sum(xyz.^2,2)),1,3);
%   tic,[center,radius] = minboundsphere(xyz);toc
%
%   Elapsed time is 0.614762 seconds.
%
%   center =
%      4.6127e-17  -2.5584e-17   7.2711e-17
%
%   radius =
%       1
%
%
% See also: minboundrect, minboundcircle
%
%
% Author: John D'Errico
% E-mail: woodchips@rochester.rr.com
% Release: 1.0
% Release date: 1/23/07

% not many error checks to worry about
sxyz = size(xyz);
if (length(sxyz)~=2) || (sxyz(2)~=3)
  error 'xyz must be an nx3 array of points'
end
n = sxyz(1);

% start out with the convex hull of the points to
% reduce the problem dramatically. Note that any
% points in the interior of the convex hull are
% never needed.
if n>4
  tri = convhulln(xyz,{'QJ' 'Pp'});

  % list of the unique points on the convex hull itself
  hlist = unique(tri(:));

  % exclude those points inside the hull as not relevant
  xyz = xyz(hlist,:);

end

% now we must find the enclosing sphere of those that
% remain.
n = size(xyz,1);

% special case small numbers of points. If we trip any
% of these cases, then we are done, so return.
switch n
  case 0
    % empty begets empty
    center = [];
    radius = [];
    return
  case 1
    % with one point, the center has radius zero
    center = xyz;
    radius = 0;
    return
  case 2
    % only two points. center is at the midpoint
    center = mean(xyz,1);
    radius = norm(xyz(1,:) - center);
    return
  case 3
    % exactly 3 points. For this odd case, just use enc4,
    % appending a new point at the centroid. This is simpler
    % than other solutions that would have reduced the
    % problem to 2-d. enc4 will do that anyway.
    [center,radius] = enc4([xyz;mean(xyz,1)]);
    return
  case 4
    % exactly 4 points
    [center,radius] = enc4(xyz);
    return
end

% pick a tolerance
tol = 10*eps*max(max(abs(xyz),[],1) - min(abs(xyz),[],1));

% more than 4 points. for no more than 15 points in the hull,
% just do an exhaustive search.
if n <= 15
  % for 15 points, there are only nchoosek(15,4) = 1365
  % sets to look through. this is only about a second.
  asets = nchoosek(1:n,4);

  center = inf(1,3);
  radius = inf;
  for i = 1:size(asets,1)
    aset = asets(i,:);
    iset = setdiff(1:n,aset);

    % get the enclosing sphere for the current set
    [centeri,radiusi] = enc4(xyz(aset,:));

    % are all the inactive set points inside the circle?
    ri = sqrt(sum((xyz(iset,:) - repmat(centeri,n-4,1)).^2,2));

    [rmax,k] = max(ri);
    if ((rmax - radiusi) <= tol) && (radiusi < radius)
      center = centeri;
      radius = radiusi;
    end
  end

else
  % Use an active set strategy, on many different
  % random starting sets.
  center = inf(1,3);
  radius = inf;

  for i = 1:250
    aset = randperm(n); % a random start, but quite adequate
    iset = aset(5:n);
    aset = aset(1:4);

    flag = true;
    iter = 0;
    centeri = inf(1,3);
    radiusi = inf;
    while flag && (iter < 12)
      iter = iter + 1;

      % get the enclosing sphere for the current set
      [centeri,radiusi] = enc4(xyz(aset,:));

      % are all the inactive set points inside the circle?
      ri = sqrt(sum((xyz(iset,:) - repmat(centeri,n-4,1)).^2,2));

      [rmax,k] = max(ri);
      if (rmax - radiusi) <= tol
        % the active set enclosing sphere also enclosed
        % all of the inactive points. We are done.
        flag = false;
      else
        % it must be true that we can replace one member of aset
        % with iset(k). That k'th element was farthest out, so
        % it seems best (a greedy algorithm) to swap it in. The
        % problem with the greedy algorithm, is it gets trapped
        % in a cycle at times. but since we are restarting the
        % algorithm multiple times, this will work.
        s1 = [aset([2 3 4]),iset(k)];
        [c1,r1] = enc4(xyz(s1,:));
        if (norm(c1 - xyz(aset(1),:)) <= r1)
          centeri = c1;
          radiusi = r1;

          % update the active/inactive sets
          swap = aset(1);
          aset = [iset(k),aset([2 3 4])];
          iset(k) = swap;

          % bounce out to the while loop
          continue
        end
        s1 = [aset([1 3 4]),iset(k)];
        [c1,r1] = enc4(xyz(s1,:));
        if (norm(c1 - xyz(aset(2),:)) <= r1)
          centeri = c1;
          radiusi = r1;

          % update the active/inactive sets
          swap = aset(2);
          aset = [iset(k),aset([1 3 4])];
          iset(k) = swap;

          % bounce out to the while loop
          continue
        end
        s1 = [aset([1 2 4]),iset(k)];
        [c1,r1] = enc4(xyz(s1,:));
        if (norm(c1 - xyz(aset(3),:)) <= r1)
          centeri = c1;
          radiusi = r1;

          % update the active/inactive sets
          swap = aset(3);
          aset = [iset(k),aset([1 2 4])];
          iset(k) = swap;

          % bounce out to the while loop
          continue
        end
        s1 = [aset([1 2 3]),iset(k)];
        [c1,r1] = enc4(xyz(s1,:));
        if (norm(c1 - xyz(aset(4),:)) <= r1)
          centeri = c1;
          radiusi = r1;

          % update the active/inactive sets
          swap = aset(4);
          aset = [iset(k),aset([1 2 3])];
          iset(k) = swap;

          % bounce out to the while loop
          continue
        end

        % if we get through to this point, then something went wrong.
        % Active set problem. Increase tol, then try again.
        tol = 2*tol;

      end
    end

    % have we improved over the best set so far?
    if radiusi < radius
      center = centeri;
      radius = radiusi;
    end
  end
end

% =======================================
%  begin subfunctions
% =======================================
function [center,radius] = enc4(xyz)
% minimum radius enclosing sphere for exactly 4 points in R^3
%
% xyz is a 4x3 array
%
% Note that enc4 will attempt to pass a sphere through all
% 4 of the supplied points. When the set of points proves to
% be degenerate, perhaps because of collinearity of 3 or
% more of the points, or because the 4 points are coplanar,
% then the sphere would nominally have infinite radius. Since
% there must be a finite radius sphere to enclose any set of
% finite valued points, enc4 will provide that sphere instead.
%
% In addition, there are some non-degenerate sets of points
% for which the circum-sphere is not minimal. enc4 will always
% try to find the minimum radius enclosing sphere.

% interpoint distance matrix D
% dfun = @(A) (A(:,[1 1 1 1]) - A(:,[1 1 1 1])').^2;
dfun = inline('(A(:,[1 1 1 1]) - A(:,[1 1 1 1])'').^2','A');
D = sqrt(dfun(xyz(:,1)) + dfun(xyz(:,2)) + dfun(xyz(:,3)));

% Find the most distant pair. Test if their circum-sphere
% also encloses the other points. If it does, then we are
% done.
[dij,ij] = max(D(:));
[i,j] = ind2sub([4 4],ij);
others = setdiff(1:4,[i,j]);
radius = dij/2;
center = (xyz(i,:) + xyz(j,:))/2;
if (norm(center - xyz(others(1),:))<=radius) && ...
   (norm(center - xyz(others(2),:))<=radius)
  % we can stop here.
  return
end

% next, we need to test each triplet of points, finding their
% enclosing sphere. If the 4th point is also inside, then we
% are done.
ind = 1:3;
[center,radius,isin] = enc3_4(xyz(ind,:),xyz(4,:),D(ind,ind));
if isin
  % the 4th point was inside this enclosing sphere.
  return
end

ind = [1 2 4];
[center,radius,isin] = enc3_4(xyz(ind,:),xyz(3,:),D(ind,ind));
if isin
  % the 3rd point was inside this enclosing sphere.
  return
end

ind = [1 3 4];
[center,radius,isin] = enc3_4(xyz(ind,:),xyz(2,:),D(ind,ind));
if isin
  % the second point was inside this enclosing sphere.
  return
end

ind = [2 3 4];
[center,radius,isin] = enc3_4(xyz(ind,:),xyz(1,:),D(ind,ind));
if isin
  % the first point was inside this enclosing sphere.
  return
end

% find the circum-sphere that passes through all 4 points
% since we have passed all the other tests, we need not
% worry here about singularities in the system of
% equations.
A = 2*(xyz(2:4,:)-repmat(xyz(1,:),3,1));
rhs = sum(xyz(2:4,:).^2 - repmat(xyz(1,:).^2,3,1),2);
center = (A\rhs)';
radius = norm(center - xyz(1,:));

% =======================================
function [center,radius,isin] = enc3_4(xyz,xyztest,Di)
% minimum radius enclosing sphere for exactly 3 points in R^3
%
% xyz - a 3x3 array, with each row as a point in R^3
%
% xyztest - 1x3 vector, a point to be tested if it is
%       inside the generated enclosing sphere.
%
% Di - 3x3 array of interpoint distances

% test the farthest pair of points. do they form a diameter
% of the sphere?
if Di(1,2)>=max(Di(1,3),Di(2,3))
  center = mean(xyz([1 2],:),1);
  radius = Di(1,2)/2;
  isin = (norm(xyz(3,:) - center)<=radius) && (norm(xyztest - center)<=radius);
elseif Di(1,3)>=max(Di(1,2),Di(2,3))
  center = mean(xyz([1 3],:),1);
  radius = Di(1,3)/2;
  isin = (norm(xyz(2,:) - center)<=radius) && (norm(xyztest - center)<=radius);
elseif Di(2,3)>=max(Di(1,2),Di(1,3))
  center = mean(xyz([2 3],:),1);
  radius = Di(2,3)/2;
  isin = (norm(xyz(1,:) - center)<=radius) && (norm(xyztest - center)<=radius);
end
if isin
  % we found the minimal enclosing sphere already
  return
end

% If we drop down to here, no singularities should
% happen (I've already caught any degeneracies.)

% We transform the three points into a plane, then
% compute the enclosing sphere in that plane.

% translate to the origin
xyz0 = xyz(1,:);
xyzt = xyz(2:3,:) - [xyz0;xyz0];

rot = orth(xyzt');

% uv is composed of 2 points, in 2-d, plus we
% have the origin (after the translation)
uv = xyzt*rot;

A = 2*uv;
rhs = sum(uv.^2,2);
center = (A\rhs)';
radius = norm(center - uv(1,:));

% rotate and translate back
center = center*rot' + xyz0;

% test if the 4th point is enclosed also
isin = (norm(xyztest - center)<=radius);


function [p,s]=v_minspane(x)
%V_MINSPANE calculate minimum spanning tree using euclidean distance [p,s]=X
%
% Inputs:  x(n,d)    d-dimensional data points, one per row
%
% Outputs: p(n-1,1)  indices of the parent of each node within the tree
%                      (data point n is the root)
%          s(n-1,1)  list of the edges in ascending order of euclidean
%                      distance. Thus the shortest edge goes from node
%                      s(1) to node p(s(1))
%
% The minimum spanning tree (or shortest spanning tree ) defines a set of
% n-1 links that interconnect n points (or nodes) with the minimum total
% length. We represent these links in the form of a tree with node n as
% the root. Each node (except node n) has a unique parent node that is
% given in the output vector p; it is possible for several nodes to share
% the same parent.
% It can be useful to know which of the links are the longest, so the output
% argument lists them in ascending order. s could be calculated directly by
% calculaing the length, l, of each link as follows:
%       l=sqrt(sum((x(1:n-1,:) - x(p,:)).^2),2);
%       [v,s]=sort(l);

%      Copyright (C) Mike Brookes 2000-2009
%      Version: $Id: v_minspane.m 10865 2018-09-21 17:22:45Z dmb $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

[np,nd]=size(x);

% first do delauny tessalation to find feasible edges

t=delaunayn(x); % nd+1 vertices per polytope
nt=size(t,1);
cn=v_choosenk(nd+1,2);
nf=size(cn,1);
ee=zeros(nt,nf,2);     % space for all the edges
ee(:,:,1)=t(:,cn(:,1));
ee(:,:,2)=t(:,cn(:,2));
ee=reshape(ee,[],2);
mk=ee(:,1)>ee(:,2);
ee(mk,:)=ee(mk,2:-1:1); % make all edges in ascending order
% ees=sparse(ee(:,1),ee(:,2),1);      % remove duplicates
[er,ec]=find(sparse(ee(:,1),ee(:,2),1));      % remove duplicates
ee=[er,ec];
ne=size(ee,1);

% now apply Kruskal shortest spanning tree algorithm

sz=sum((x(ee(:,1),:)-x(ee(:,2),:)).^2,2);     % length^2 of each edge
[vz,mz]=sort(sz);
ee=ee(mz,:);        % sort edges into ascenging length order
ts=ones(ne,1);      % size of each component
tp=zeros(np,1);     % root node links
ei=zeros(np-1,1);     % index of shortest spanning tree edges
k=0;
for i=1:ne
    i1=ee(i,1);
    j=tp(i1);
    while j         % find root node for ee(i,1)
        i1=j;
        j=tp(i1);
    end
    i2=ee(i,2);
    j=tp(i2);
    while j         % find root node for ee(i,2)
        i2=j;
        j=tp(i2);
    end
    if i1~=i2       % if they are different, merge them
        k=k+1;
        ei(k)=i;    % add to the shortest spanning tree
        if ts(i1)>ts(i2)
            tp(i2)=i1;          % make i2 a sub tree of i1
            ts(i1)=ts(i1)+ts(i2);
        else
            tp(i1)=i2;          % make i1 a sub tree of i2
            ts(i2)=ts(i1)+ts(i2);
        end
    end
end
ee=ee(ei,:);        % refine the edges to include only those in the minimum spanning tree

% now arrange as a tree with point np as the head

eet=sparse(ee(:,1),ee(:,2),1:np-1,np,np);
p=zeros(np-1,1);              % points to parent node
s=zeros(np-1,1);              % sorted index
chn=np;                                 % start with the root node of the tree
[rf,cf]=find(eet(:,chn));               % find any nodes that connect to it
[rg,cg]=find(eet(chn,:));
while ~isempty(rf) || ~isempty(rg)
    p(rf)=chn(cf);                      % set the parents
    rcf=rf(:)+np*(chn(cf(:))-1);
    s(eet(rcf))=rf(:);
    eet(rcf)=0;                         % delete the edges linking them to their parents
    p(cg)=chn(rg);
    rcg=chn(rg(:))+np*(cg(:)-1);
    s(eet(rcg))=cg(:);
    eet(rcg)=0;
    chn=[rf(:); cg(:)];                 % now search for their children
    [rf,cf]=find(eet(:,chn));
    [rg,cg]=find(eet(chn,:));
end


%% A 10x10 tridiagonal matrix, with 2 on the diagonal, -1 on the off diagonal.

A = blktridiag(2,-1,-1,10);

% The sparsity pattern is correct
spy(A)

% and the elements are as designated
full(A)

%% A lower block bidiagonal matrix with replicated blocks

% with 2x2 blocks of ones on the main diagonal, and
% 2x2 blocks of twos on the sub-diagonal

A = blktridiag(ones(2),2*ones(2),zeros(2),5);

spy(A)
full(A)

%% A block tridiagonal matrix with replicated blocks

Amd = reshape(1:9,3,3);
Asub = reshape(11:19,3,3);
Asup = reshape(21:29,3,3);
A = blktridiag(Amd,Asub,Asup,4);

spy(A)
full(A)

%% A tridiagonal matrix with random elements

Amd = rand(1,1,7);
Asub = rand(1,1,6);
Asup = rand(1,1,6);
A = blktridiag(Amd,Asub,Asup);

spy(A)
full(A)

%% A block tridiagonal matrix with distinct elements

Amd = reshape(1:27,[3 3 3]);
Asub = reshape(101:118,[3 3 2]);
Asup = reshape(201:218,[3 3 2]);
A = blktridiag(Amd,Asub,Asup);

spy(A)
full(A)

%% A block tridiagonal matrix with 2x3 fixed non-square blocks

Amd = rand(2,3);
Asub = 2*ones(2,3);
Asup = ones(2,3);
A = blktridiag(Amd,Asub,Asup,3);

spy(A)
full(A)

%% A block tridiagonal matrix with varying 3x2 non-square blocks
Amd = reshape(1:18,[3 2 3]);
Asub = reshape(101:112,[3 2 2]);
Asup = reshape(201:212,[3 2 2]);
A = blktridiag(Amd,Asub,Asup);

spy(A)
full(A)


function lagrange_nd_test07 ( )

%*****************************************************************************80
%
%% LAGRANGE_ND_TEST07 tests LAGRANGE_ND_COMPLETE in 3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 January 2014
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'LAGRANGE_ND_TEST07\n' );
  fprintf ( 1, '  LAGRANGE_COMPLETE determines\n' );
  fprintf ( 1, '  the Lagrange interpolating polynomials L(x)\n' );
  fprintf ( 1, '  for ND points in D dimensions, assuming that\n' );
  fprintf ( 1, '  the number of points exactly coincides with\n' );
  fprintf ( 1, '  R = Pi(D,N), the number of monomials of degree N or less\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The data points are the grid nodes of a tetrahedron.\n' );

  d = 3;
  n = 2;
  r = mono_upto_enum ( d, n );
  nd = 10;
  xd = [ 0.0,  0.0,  0.0; ...
         1.0,  0.0,  0.0; ...
         2.0,  0.0,  0.0; ...
         0.0,  1.0,  0.0; ...
         1.0,  1.0,  0.0; ...
         0.0,  2.0,  0.0; ...
         0.0,  0.0,  1.0; ...
         1.0,  0.0,  1.0; ...
         0.0,  1.0,  1.0; ...
         0.0,  0.0,  2.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension D = %d\n', d );
  fprintf ( 1, '  Maximum degree N = %d\n', n );
  fprintf ( 1, '  Number of monomials R = %d\n', r );
  fprintf ( 1, '  Number of data points ND = %d\n', nd );

  r8mat_transpose_print ( d, nd, xd, '  Data points XD:' );

  [ po, pc, pe ] = lagrange_complete ( d, n, r, nd, xd );
%
%  Print the polynomials.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Lagrange polynomials for XD data points:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : nd
    o = po(i);
    label = sprintf ( '  P(%d)(x) =', i );
    polynomial_print ( d, o, pc(i,1:o), pe(i,1:o), label );
  end
%
%  Evaluate the polynomials at XD.
%
  value = zeros ( nd, nd );

  for j = 1 : nd
    o = po(j);
    label = sprintf ( '  P(%d)(x) =', j );
    value(1:nd,j) = polynomial_value ( d, o, pc(j,1:o), pe(j,1:o), nd, xd );
  end

  err = r8mat_is_identity ( nd, value );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Frobenius norm of Lagrange matrix error = %g\n', err );

  return
end


function c = min_errorbar_scale(stderrs,significance)
% c = min_errorbar_scale(stderrs,significance)
% returns the minimum scale factor c such that any pair of non-overlapping
% error bars represents statistical significance exceeding the given level.
% stderrs is a vector.
% significance is a scalar.
%
% See "Judging significance from error bars" by Tom Minka (2002)
% http://research.microsoft.com/~minka/papers/minka-errorbars.pdf
%
% Examples:
%   min_errorbar_scale(ones(10,1))  % returns 1.16
%   min_errorbar_scale(0:10)        % returns 1.64

% Written by Tom Minka

% Algorithm:
% We want c*(stderr(i)+stderr(j)) >= z*sqrt(stderr(i)^2+stderr(j)^2)
% for all pairs (i,j).  Therefore
% c = max_(i,j)  z*sqrt(stderr(i)^2+stderr(j)^2)/(stderr(i) + stderr(j));

if nargin < 2
  significance = 0.95;
end

z = erfinv(2*significance - 1)*sqrt(2);

n = length(stderrs);
ratio = zeros(n,1);
for i = 1:length(stderrs)
  exact = sqrt(stderrs(i).^2 + stderrs.^2);
  approx = stderrs(i) + stderrs;
  ratio(i) = max(exact./approx);
end
c = z*max(ratio);


function point = projPointOnLine3d(point, line)
%PROJPOINTONLINE3D Project a 3D point orthogonally onto a 3D line.
%
%   PT2 = projPointOnLine3d(PT, LINE).
%   Computes the (orthogonal) projection of 3D point PT onto the 3D line
%   LINE.
%
%   Function works also for multiple points and lines. In this case, it
%   returns multiple points.
%   Point PT1 is a N-by-3 array, and LINE is a N-by-6 array.
%   Result PT2 is a N-by-3 array, containing coordinates of orthogonal
%   projections of PT1 onto lines LINE.
%
%
%   See also
%   projPointOnLine, distancePointLine3d

% ------
% Author: David Legland
% E-mail: david.legland@inrae.fr
% Created: 2012-08-23
% Copyright 2012-2022 INRA - TPV URPOI - BIA IMASTE

% direction vector of the line
vx = line(:, 4);
vy = line(:, 5);
vz = line(:, 6);

% difference of point with line origin
dx = point(:,1) - line(:,1);
dy = point(:,2) - line(:,2);
dz = point(:,3) - line(:,3);

% Position of projection on line, using dot product
delta = vx .* vx + vy .* vy + vz .* vz;
tp = (dx .* vx + dy .* vy + dz .* vz) ./ delta;

% convert position on line to cartesian coordinates
point = [line(:,1) + tp .* vx, line(:,2) + tp .* vy, line(:,3) + tp .* vz];


function [J, grad] = cofiCostFunc(params, Y, R, num_users, num_movies, ...
                                  num_features, lambda)
    %COFICOSTFUNC Collaborative filtering cost function
    %   [J, grad] = COFICOSTFUNC(params, Y, R, num_users, num_movies, ...
    %   num_features, lambda) returns the cost and gradient for the
    %   collaborative filtering problem.
    %

    % Unfold the U and W matrices from params
    X = reshape(params(1:num_movies*num_features), num_movies, num_features);
    Theta = reshape(params(num_movies*num_features+1:end), ...
                    num_users, num_features);

    % You need to return the following values correctly
    J = 0;
    X_Gradient = zeros(size(X));
    Theta_Gradient = zeros(size(Theta));

    % ====================== YOUR CODE HERE ======================
    % Instructions: Compute the cost function and gradient for collaborative
    %               filtering. Concretely, you should first implement the cost
    %               function (without regularization) and make sure it is
    %               matches our costs. After that, you should implement the
    %               gradient and use the checkCostFunction routine to check
    %               that the gradient is correct. Finally, you should implement
    %               regularization.
    %
    % Notes: X - num_movies  x num_features matrix of movie features
    %        Theta - num_users  x num_features matrix of user features
    %        Y - num_movies x num_users matrix of user ratings of movies
    %        R - num_movies x num_users matrix, where R(i, j) = 1 if the
    %            i-th movie was rated by the j-th user
    %
    % You should set the following variables correctly:
    %
    %        X_grad - num_movies x num_features matrix, containing the
    %                 partial derivatives w.r.t. to each element of X
    %        Theta_grad - num_users x num_features matrix, containing the
    %                     partial derivatives w.r.t. to each element of Theta
    %

    J_Temporary = power ((X * Theta' - Y), 2);
    J = sum (sum (J_Temporary (R == 1))) / 2 + ((lambda / 2) .* sum (sum (power (Theta, 2)))) + ((lambda / 2) .* sum (sum (power (X, 2))));

    X_Gradient = ((X * Theta' - Y) .* R) * Theta + lambda .* X;
    Theta_Gradient = ((X * Theta' - Y) .* R)' * X + lambda .* Theta;

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

    grad = [X_Gradient(:); Theta_Gradient(:)];

end


function S = randsym(n, N)
% Generates random symmetric matrices with normal entries.
%
% function S = randsym(n)
% function S = randsym(n, N)
%
% S is an n-by-n-by-N array where each slice S(:, :, i) for i = 1..N is a
% random symmetric matrix with upper triangular entries distributed
% independently following a normal distribution (Gaussian, zero mean, unit
% variance).
%
% By default, N = 1.
%
% See also: randrot randskew randherm randskewh

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, Oct. 23, 2018.
% Contributors:
% Change log:
%       Oct. 23, 2018 (NB):
%           This is not technically necessary for the rotations factory,
%           but it is counter-intuitive to have access to a function called
%           randskew yet not have one for randsym.
%       June 19, 2019 (NB):
%           Now handles the case n = 1 properly.

    if nargin < 2
        N = 1;
    end

    if n == 1
        S = randn(1, 1, N);
        return;
    end

    % Subindices of the (strictly) upper triangular entries of an n-by-n
    % matrix.
    [I, J] = find(triu(ones(n), 1));

    K = repmat(1:N, n*(n-1)/2, 1);

    % Indices of the strictly upper triangular entries of all N slices of
    % an n-by-n-by-N array.
    L = sub2ind([n n N], repmat(I, N, 1), repmat(J, N, 1), K(:));

    % Allocate memory for N random symmetric matrices of size n-by-n and
    % populate each upper triangular entry with a random number following a
    % normal distribution and copy them on the corresponding lower
    % triangular side.
    S = zeros(n, n, N);
    S(L) = randn(size(L));
    S = S + multitransp(S);

    % Now populate the diagonal entries:

    % Subindices of the diagonal entries of an n-by-n matrix.
    [I, J] = find(eye(n));

    K = repmat(1:N, n, 1);

    % Indices of the diagonal entries of all N slices of an n-by-n-by-N
    % array.
    L = sub2ind([n n N], repmat(I, N, 1), repmat(J, N, 1), K(:));

    S(L) = randn(size(L));

end


function [ w, cvx_optval ] = fdla( A ) %#ok

% Computes the fastest distributed linear averaging (FDLA) edge weights
%
% [W,S] = FDLA(A) gives a vector of the fastest distributed linear averaging
% edge weights for a graph described by the incidence matrix A (n x m).
% Here n is the number of nodes and m is the number of edges in the graph;
% each column of A has exactly one +1 and one -1.
%
% The FDLA edge weights are given by the SDP:
%
%   minimize    s
%   subject to  -s*I <= I - L - (1/n)11' <= s*I
%
% where the variables are edge weights w in R^m and s in R.
% Here L is the weighted Laplacian defined by L = A*diag(w)*A'.
% The optimal value is s, and is returned in the second output.
%
% For more details see the references:
% "Fast linear iterations for distributed averaging" by L. Xiao and S. Boyd
% "Convex Optimization of Graph Laplacian Eigenvalues" by S. Boyd
%
% Written for CVX by Almir Mutapcic 08/29/06

[n,m] = size(A); %#ok
I = eye(n,n);
J = I - (1/n) * ones(n,n);
cvx_begin sdp
    variable w(m,1)   % edge weights
    variable s        % epigraph variable
    variable L(n,n) symmetric
    minimize( s )
    subject to
        L == A * diag(w) * A'; %#ok
        -s * I <= J - L <= s * I; %#ok
cvx_end


function varargout = xyy2xyz(varargin)
%XYY2XYZ Convert chromaticity coordinates to XYZ tristimulus values.
%   [X,Y,Z] = XYY2XYZ(x,y,Y) converts the chromaticity coordinates (x
%   and y) and the Y tristimulus value to the tristimulus values X, Y,
%   and Z. Y, x, y, X, Y, and Z are all arrays with the same size.
%
%   XYZ = XYY2XYZ(xyY) performs the conversion on a Px3 input matrix
%   where P(:,1) contains the x values, P(:,2) contains the y values,
%   and P(:,3) contains the Y values. The output matrix is also Px3.

%   Written by Steve Eddins to accompany Digital Image Processing Using
%   MATLAB, 3rd edition, Gatesmark Press, 2020,
%   http://imageprocessingplace.com.
%
%   Copyright 2019 The MathWorks, Inc.
%   License: https://github.com/mathworks/matlab-color-tools/blob/master/license.txt

if nargin == 3
   style = "separate";
   x = varargin{1};
   y = varargin{2};
   Y = varargin{3};
elseif nargin == 1
   style = "3-column";
   xyY = varargin{1};
   x = xyY(:,1);
   y = xyY(:,2);
   Y = xyY(:,3);
end

X = Y .* x ./ y;
Z = Y .* (1 - x - y) ./ y;

% Handle the numerical edge case where y is 0.
X(y == 0) = 0;
Z(y == 0) = 0;

if style == "3-column"
   varargout{1} = [X Y Z];
else
   varargout{1} = X;
   varargout{2} = Y;
   varargout{3} = Z;
end


% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni
%
%
% Problem 8
% Solve the difference equation
% y[n]+1.5y[n-1]+0.5y[n-2]=x[n]+x[n-1] , x[n]=0.8^n u[n]

syms n z Y
x=0.8^n;
X=ztrans(x,z);
X1=z^(-1)*X;
Y1=z^(-1)*Y;
Y2=z^(-2)*Y;
G=Y+1.5*Y1+0.5*Y2-X-X1;
SOL=solve(G,Y);
y=iztrans(SOL,n)

% a)
n_s=0:20;
y_s=subs(y,n,n_s);
stem(n_s,y_s);
legend('Solution y[n]')
xlim([-.5 20.5])
ylim([0 1.1])

% b)
xn=x;
xn_1=0.8^(n-1);
yn=y;
yn_1=subs(y,n,n-1);
yn_2=subs(y,n,n-2);
test=yn+1.5*yn_1+0.5*yn_2-xn-xn_1
simplify(test)


function nperm = perm_enum ( n )

%*****************************************************************************80
%
%% PERM_ENUM enumerates the permutations on N digits.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of values being permuted.
%    N must be nonnegative.
%
%    Output, integer NPERM, the number of distinct elements.
%
  nperm = i4_factorial ( n );

  return
end


function coeff = fourier_comp(func,m,L)
%FOURIER_COMP Numerically evaluate Fourier series coefficient.
% coeff = fourier_comp(func,m,L) tries to approximate the function func
% from -L to L with m term Fourier series using quad (MATLAB functions).
% func is a function handle, should accept a vector argument x and return a
% vector result y
% This function return a structure with these fields:
% coeff.a0
% coeff.an
% coeff.bn
% The Fourier series for function f(x) is given below.
%                       inf
%                      -----
%                      \
%        f(x) = a0/2 +  \  an * sin(n*pi*x/L) + bn * con(n*pi*x/L)
%                       /
%                      /
%                      -----
%                      n = 1
%
%   Example:
%
%   f = @(x)x.*cos(x);
%   coeff = fourier_comp(f,3,pi)
%     coeff =
%     a0: 0
%     an: [-0.5000 1.3333 -0.7500]
%     bn: [1.4136e-016 0 7.0679e-017]
%
%   See also
%   fourier_gui
%
% Author: Amin Bashi
% Created: Jul 2009
% Copyright 2009

% func must be the function handle

for n = 1:m
    an(n) = quad(@fa,-L,L)/L;
    bn(n) = quad(@fb,-L,L)/L;
end
a0 = quad(func,-L,L)/L;
coeff.a0 = a0;
coeff.an = an;
coeff.bn = bn;
    function y = fa(t)
        y = func(t).*sin(n*pi*t/L);
    end
    function y = fb(t)
        y = func(t).*cos(n*pi*t/L);
    end
end


function a = toeplitz_5diag ( n, d1, d2, d3, d4, d5 )

%*****************************************************************************80
%
%% TOEPLITZ_5DIAG returns a pentadiagonal Toeplitz matrix.
%
%  Formula:
%
%    if ( I - J == 2 )
%      A(I,J) = D1
%    elseif ( I - J == 1 )
%      A(I,J) = D2
%    elseif ( I - J == 0 )
%      A(I,J) = D3
%    elseif ( I - J == -1 )
%      A(I,J) = D4
%    elseif ( I - J == -2 )
%      A(I,J) = D5
%    else
%      A(I,J) = 0.0
%
%  Example:
%
%    N = 5, D1 = 1, D2 = -10, D3 = 0, D4 = 10, D5 = 1
%
%      0  10   1   .   .
%    -10   0  10   1   .
%      1 -10   0  10   1
%      .   1 -10   0  10
%      .   .   1 -10   0
%
%  Properties:
%
%    A is generally not symmetric: A' /= A.
%
%    A is Toeplitz: constant along diagonals.
%
%    A is banded, with bandwidth 5.
%
%    A is persymmetric: A(I,J) = A(N+1-J,N+1-I).
%
%    The special data D1 = 1, D2 = -10, D3 = 0, D4 = 10, D5 = 1 corresponds
%    to a matrix of Rutishauser.
%
%    The matrix has eigenvalues lying approximately on the complex line
%    segment 2 * cos ( 2 * t ) + 20 * I * sin ( t ).
%
%    The family of matrices is nested as a function of N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    RM Beam, RF Warming,
%    The asymptotic spectra of banded Toeplitz and quasi-Toeplitz matrices,
%    SIAM Journal on Scientific and Statistical Computing,
%    Volume 14, Number 4, 1993, pages 971-1006.
%
%    Heinz Rutishauser,
%    On test matrices,
%    Programmation en Mathematiques Numeriques,
%    Centre National de la Recherche Scientifique,
%    1966, pages 349-365.
%
%  Parameters:
%
%    Input, integer N, the order of A.  N should be at least 3.
%
%    Input, D1, D2, D3, D4, D5, values that define the nonzero diagonals
%    of the matrix.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

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

      if ( i - j == 2 )
        a(i,j) = d1;
      elseif ( i - j == 1 )
        a(i,j) = d2;
      elseif ( i - j == 0 )
        a(i,j) = d3;
      elseif ( i - j == -1 )
        a(i,j) = d4;
      elseif ( i - j == -2 )
        a(i,j) = d5;
      else
        a(i,j) = 0.0;
      end

    end
  end

  return
end


function [ Grid,varargout ] = CavityGridOperators( N )
%CAVITYGRIDOPERATORS generates the grid and operators
[Grid]=CollocationGrid_q(N);    % grid coordiuantes and indices

if nargout==2
    varargout{1}= CreateOperators_psi( Grid.D,eye(N+1));  %  derivative matrices
end

[~,Grid.wc] = clencurt(N);
 Grid.W = kron(Grid.wc,Grid.wc);   % integration coefficients for computation of Kinetic Energy

end

function [Grid]=CollocationGrid_q(N)

  [Grid.D,Grid.x] = cheb(N);
  [xx,yy]=meshgrid(Grid.x,Grid.x); Grid.xx=xx(:);Grid.yy=yy(:);

% Index positions for walls and interior
  Grid.Walls = find(abs(xx)==1 | abs(yy)==1);
  Grid.LeftWall = find(xx==-1); Grid.RightWall=find(xx==1);
  Grid.BottomWall=find(yy==-1); Grid.TopWall=find(yy==1);
  Grid.Interior = setdiff((1:length(Grid.xx)),Grid.Walls);

  % operators
  I = eye(N+1);
  Grid.D2 = (diag(1-Grid.x.^2)*Grid.D^2 - 4*diag(Grid.x)*Grid.D - 2*I);
  Grid.D4 = (diag(1-Grid.x.^2)*Grid.D^4 - 8*diag(Grid.x)*Grid.D^3 - 12*Grid.D^2); % Trefethen style

     % Propagation function
   Grid.S0 = (1-Grid.xx.^2).*(1-Grid.yy.^2);
   Grid.S1 = Grid.S0;
   Grid.S1(Grid.Walls)=1;

   % plot on cheb grid
   Grid.cplot = @(X) contourf(reshape(xx,N+1,N+1),reshape(yy,N+1,N+1),reshape(X,N+1,N+1),50,'LineStyle','None');

end

  function [x,w] = clencurt(N)
  theta = pi*(0:N)'/N; x = cos(theta);
  w = zeros(1,N+1); ii = 2:N; v = ones(N-1,1);
  if mod(N,2)==0
    w(1) = 1/(N^2-1); w(N+1) = w(1);
    for k=1:N/2-1, v = v - 2*cos(2*k*theta(ii))/(4*k^2-1); end
    v = v - cos(N*theta(ii))/(N^2-1);
  else
    w(1) = 1/N^2; w(N+1) = w(1);
    for k=1:(N-1)/2, v = v - 2*cos(2*k*theta(ii))/(4*k^2-1); end
  end
  w(ii) = 2*v/N;
  end

 function [ Operators_psi ] = CreateOperators_psi( D,I)
%CREATEOPERATORS_q creates the Operator acting on psi(x)
Operators_psi.Dx = kron(D,I);
Operators_psi.Dy = kron(I,D);
D2= D^2; D4=D2^2;
Operators_psi.del2 = kron(D2,I)+kron(I,D2);

Operators_psi.del4 = kron(D4,I)+kron(I,D4)+2*kron(D2,I)*kron(I,D2);

end


function p = hen_polynomial_value ( m, n, x )

%*****************************************************************************80
%
%% HEN_POLYNOMIAL_VALUE evaluates Hen(i,x).
%
%  Discussion:
%
%    Hen(i,x) is the normalized probabilist's Hermite polynomial of degree I.
%
%    These polynomials satisfy the orthonormality condition:
%
%      Integral ( -oo < X < +oo ) exp ( - 0.5 * X^2 ) * Hen(M,X) Hen(N,X) dX
%      = delta ( N, M )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 February 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz, Irene Stegun,
%    Handbook of Mathematical Functions,
%    National Bureau of Standards, 1964,
%    ISBN: 0-486-61272-4,
%    LC: QA47.A34.
%
%    Frank Olver, Daniel Lozier, Ronald Boisvert, Charles Clark,
%    NIST Handbook of Mathematical Functions,
%    Cambridge University Press, 2010,
%    ISBN: 978-0521192255,
%    LC: QA331.N57.
%
%  Parameters:
%
%    Input, integer M, the number of evaluation points.
%
%    Input, integer N, the highest order polynomial to compute.
%    Note that polynomials 0 through N will be computed.
%
%    Input, real X(M,1), the evaluation points.
%
%    Output, real P(M,N+1), the values of the polynomials of index 0 through N.
%
  p = zeros ( m, n + 1 );

  p(1:m,1) = 1.0;

  if ( n == 0 )
    return
  end

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

  for j = 2 : n
    p(1:m,j+1) = x(1:m,1) .* p(1:m,j) - ( j - 1 ) * p(1:m,j-1);
  end
%
%  Normalize.
%
  d = diag ( 1.0 ./ sqrt ( gamma ( 1:n+1) .* sqrt ( 2.0 * pi ) ) );

  p = p * d;

  return
end


function varargout = gabrielGraph(pts)
%GABRIELGRAPH  Gabriel Graph of a set of points.
%
%   EDGES = gabrielGraph(PTS)
%   Computes the Gabriel graph of the input set of points PTS. The Gabriel
%   graph is based on the euclidean Delaunay triangulation, and keeps only
%   edges whose circumcircle does not contain any other input point than
%   the edge extremities.
%
%   [NODES, EDGES] = gabrielGraph(PTS)
%   Also returns the initial set of points;
%
%   Example
%     pts = rand(100, 2);
%     edges = gabrielGraph(pts);
%     figure; drawPoint(pts);
%     hold on; axis([0 1 0 1]); axis equal;
%     drawGraph(pts, edges);
%
%   See also
%     graphs, drawGraph, delaunayGraph
%

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

% compute Delaunay triangulation
if verLessThan('matlab', '8.1')
    % Code for versions before R2013a
    dt = DelaunayTri(pts); %#ok<DDELTRI>
else
    % Code for versions R2013a and later
    dt = delaunayTriangulation(pts);
end

% extract edges (N-by-2 array)
eds = dt.edges();

% radius of the circle circumscribed to each edge
rads = edgeLength([pts(eds(:,1), :) pts(eds(:,2), :)]) / 2;

% extract middle point of each edge
midPts = midPoint(pts(eds(:,1), :), pts(eds(:,2), :));

% distance between midpoints and all points
% closest points should be edge vertices
dists = minDistancePoints(midPts, pts);

% geometric tolerance (adapted to point set extent)
tol = max(max(pts) - min(pts)) * eps;

% keep only edges whose circumcircle does not contain any other point
keep = dists >= rads - tol;
edges = eds(keep, :);

% format output depending on number of output arguments
if nargout < 2
    varargout = {edges};
else
    varargout = {pts, edges};
end


function fx = p01_fun ( option, nvar, x )

%*****************************************************************************80
%
%% P01_FUN evaluates the function for problem 1.
%
%  Title:
%
%    The Freudenstein-Roth function
%
%  Description:
%
%    One way to use a continuation code as a nonlinear root finder
%    is to start with a set of nonlinear equations G(X), and an
%    approximate root A, and create a "homotopy" function F(X,Y)
%    with the properties that F(A,0.0) = 0 and F(X,1.0) = G(X).
%    Thus, the homotopy function F has a known exact solution
%    from which we can start with no difficulty.  If the continuation
%    code can take us from Y = 0 to Y = 1, then we have found
%    an X so that F(X,1.0) = 0, so we have found a solution to G(X)=0.
%
%    The Freudenstein-Roth function F(X) is derived in this way
%    from a homotopy of G(X):
%
%      F ( X(1), X(2), X(3) ) =
%        G ( X(1), X(2) ) - ( 1 - X(3) ) * G ( Y1, Y2 )
%
%    where Y1 and Y2 are some fixed values, and
%
%      G(1) = X(1) - X(2)*X(2)*X(2) + 5*X(2)*X(2) -  2*X(2) - 13
%      G(2) = X(1) + X(2)*X(2)*X(2) +   X(2)*X(2) - 14*X(2) - 29
%
%  Options 1, 2, 3:
%
%    The starting point is X0 = ( 15, -2, 0 ).
%
%    A great deal of information is available about the homotopy curve
%    generated by this starting point:
%
%    The function F(X) has the form
%
%      F(1) = X(1) - X(2)**3 + 5*X(2)**2 -  2*X(2) - 13 + 34*(X(3)-1)
%      F(2) = X(1) + X(2)**3 +   X(2)**2 - 14*X(2) - 29 + 10*(X(3)-1)
%
%    There is a closed form representation of the curve in terms of the
%    second parameter:
%
%      X(1) = (-11*X(2)**3 + 4*X(2)**2 + 114*X(2) + 214) /  6
%      X(2) = X(2)
%      X(3) = (    X(2)**3 - 2*X(2)**2 -   6*X(2) +   4) / 12
%
%    The first option simply requests the production of solution points
%    along the curve until a point is reached whose third component is
%    exactly 1.
%
%    Options 2 and 3 use the same starting point, and also stop when the
%    third component is 1.  However, these options in addition search
%    for limit points in the first and third components of the solution,
%    respectively.
%
%    The target solution has X(3) = 1, and is ( 5, 4, 1 ).
%
%    Limit points for X1:
%
%      ( 14.28309, -1.741377,  0.2585779 )
%      ( 61.66936,  1.983801, -0.6638797 )
%
%    Limit points for X3:
%
%     (20.48586, -0.8968053, 0.5875873)
%     (61.02031,  2.230139, -0.6863528)
%
%    The curve has several dramatic bends.
%
%
%  Options 4, 5, and 6:
%
%    The starting point is (4, 3, 0).
%
%    The function F(X) has the form
%
%      F(1) = X(1) - X(2)**3 + 5*X(2)**2 -  2*X(2) - 13 +  3*(X(3)-1)
%      F(2) = X(1) + X(2)**3 +   X(2)**2 - 14*X(2) - 29 - 31*(X(3)-1)
%
%    There is a closed form representation of the curve in terms of the
%    second parameter:
%
%      X(1) = (14*X(2)**3 -79*X(2)**2 +52*X(2) + 245) / 17
%      X(2) = X(2)
%      X(3) = (   X(2)**3 - 2*X(2)**2 - 6*X(2) +   9) / 17
%
%    The correct value of the solution at X(3)=1 is:
%
%      (5, 4, 1)
%
%    In option 5, limit points in the first component are sought,
%    and in option 6, limit points in the third component are
%    sought.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Ferdinand Freudenstein, Bernhard Roth,
%    Numerical Solutions of Nonlinear Equations,
%    Journal of the Association for Computing Machinery,
%    Volume 10, 1963, Pages 550-556.
%
%  Parameters:
%
%    Input, integer OPTION, the option index.
%
%    Input, integer NVAR, the number of variables.
%
%    Input, real X(NVAR), the argument of the function.
%
%    Output, real FX(NVAR-1), the value of the function at X.
%

%  Get the starting point, Y.
%
  y = p01_start ( option, nvar );
%
%  G is the function value at the starting point,
%  F the function value at the current point.
%
  gy = p01_gx ( y );

  gx = p01_gx ( x );
%
%  The parameter X3 generates the homotopy curve.
%
  fx(1:nvar-1) = gx(1:nvar-1) + ( x(3) - 1.0 ) * gy(1:nvar-1);

  return
end


function value = i4_rise ( x, n )

%*****************************************************************************80
%
%% I4_RISE computes the rising factorial function [X]^N.
%
%  Discussion:
%
%    [X]^N = X * ( X + 1 ) * ( X + 2 ) * ... * ( X + N - 1 ).
%
%    Note that the number of ways of arranging N objects in M ordered
%    boxes is [M]^N.  (Here, the ordering of the objects in each box matters).
%    Thus, 2 objects in 2 boxes have the following 6 possible arrangements:
%
%      -|12, 1|2, 12|-, -|21, 2|1, 21|-.
%
%    Moreover, the number of non-decreasing maps from a set of
%    N to a set of M ordered elements is [M]^N / N!.  Thus the set of
%    nondecreasing maps from (1,2,3) to (a,b,c,d) is the 20 elements:
%
%      aaa, abb, acc, add, aab, abc, acd, aac, abd, aad
%      bbb, bcc, bdd, bbc, bcd, bbd, ccc, cdd, ccd, ddd.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 November 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer X, the argument of the rising factorial function.
%
%    Input, integer N, the order of the rising factorial function.
%    If N = 0, RISE = 1, if N = 1, RISE = X.  Note that if N is
%    negative, a "falling" factorial will be computed.
%
%    Output, integer VALUE, the value of the rising factorial function.
%
  value = 1;

  arg = x;

  if ( 0 < n )

    for i = 1 : n
      value = value * arg;
      arg = arg + 1;
    end

  elseif ( n < 0 )

    for i = -1 : -1 : n
      value = value * arg;
      arg = arg - 1;
    end

  end

  return
end


function Z = xkron(X,Y)
%XKRON Kronecker tensor product.
%
%   XKRON(X,Y), where X and Y are matrices, is the Kronecker tensor product
%   of X and Y.  The result is a large matrix formed by taking all possible
%   products between the elements of X and those of Y.
%
%   For example, if X is 2-by-3, and Y is any N-dimensional array, then
%   KRON(X,Y) is
%
%     [ X(1,1)*Y  X(1,2)*Y  X(1,3)*Y
%       X(2,1)*Y  X(2,2)*Y  X(2,3)*Y ]
%
%   If either X or Y is sparse, and neither X nor Y has dimension
%   greater than 2, then only nonzero elements are multiplied in the
%   computation, and the result is sparse.
%
%   XKRON works also when X and/or Y are N-dimensional arrays.  There does
%   not seem to be a unique definition of an N-dimensional Kronecker tensor
%   product, so I simply picked the one I found most logical.
%
%   If X is 3-by-4-by-2, and Y is any N-dimensional array, then
%
%     cat( 3, [ X(1,1,1)*Y  X(1,2,1)*Y  X(1,3,1)*Y  X(1,4,1)*Y ;  ...
%               X(2,1,1)*Y  X(2,2,1)*Y  X(2,3,1)*Y  X(2,4,1)*Y ;  ...
%               X(3,1,1)*Y  X(3,2,1)*Y  X(3,3,1)*Y  X(3,4,1)*Y ], ...
%             [ X(1,1,2)*Y  X(1,2,2)*Y  X(1,3,2)*Y  X(1,4,2)*Y ;  ...
%               X(2,1,2)*Y  X(2,2,2)*Y  X(2,3,2)*Y  X(2,4,2)*Y ;  ...
%               X(3,1,2)*Y  X(3,2,2)*Y  X(3,3,2)*Y  X(3,4,2)*Y ] )

%   Author:      Peter J. Acklam
%   Time-stamp:  2002-03-03 13:50:29 +0100
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   xs = size(X);
   ys = size(Y);
   xd = length(xs);
   yd = length(ys);

   if ( issparse(X) | issparse(Y) ) & ( xd <= 2 ) & ( yd <= 2 )

      % When at least one input is sparse, and neither argument has
      % dimension greater than 2, the result is sparse.

      mx = xs(1); nx = xs(2);
      my = ys(1); ny = ys(2);

      [ix, jx, sx] = find(X);
      [iy, jy, sy] = find(Y);
      ix = ix(:); jx = jx(:); sx = sx(:);
      iy = iy(:); jy = jy(:); sy = sy(:);
      kx = ones(size(sx));
      ky = ones(size(sy));
      t = my*(ix-1)';
      ik = t(ky,:)+iy(:,kx);
      t = ny*(jx-1)';
      jk = t(ky,:)+jy(:,kx);
      Z = sparse(ik, jk, sy*sx.', mx*my, nx*ny);

   else

      dz = max(xd, yd);
      xs = [ xs ones(1,dz-xd) ];
      ys = [ ys ones(1,dz-yd) ];

      v = reshape( reshape( 1:2*dz, dz, 2 )', 1, 2*dz );
      Z = reshape( Y(:)*X(:).', [ ys xs ] );
      Z = reshape( permute( Z, v ), xs.*ys );

   end


function geometry_test20325 ( )

%*****************************************************************************80
%
%% TEST20325 tests TETRAHEDRON_SIZE_3D, TETRAHEDRON_SHAPE_3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 July 2007
%
%  Author:
%
%    John Burkardt
%
  dim_num = 3;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST20325\n' );
  fprintf ( 1, '  For the tetrahedron,\n' );
  fprintf ( 1, '  TETRAHEDRON_SIZE_3D returns dimension information;\n' );
  fprintf ( 1, '  TETRAHEDRON_SHAPE_3D returns face and order info.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  We will use this information to compute the\n' );
  fprintf ( 1, '  areas and centers of each face.\n' );

  [ point_num, edge_num, face_num, face_order_max ] = ...
    tetrahedron_size_3d ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of points =   %d\n', point_num );
  fprintf ( 1, '  Number of edges =    %d\n', edge_num );
  fprintf ( 1, '  Number of faces =    %d\n', face_num );
  fprintf ( 1, '  Maximum face order = %d\n', face_order_max );

  [ point_coord, face_order, face_point ] = ...
    tetrahedron_shape_3d ( point_num, face_num, face_order_max );

  shape_print_3d ( point_num, face_num, face_order_max, ...
    point_coord, face_order, face_point );
%
%  Compute the area of each face.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Face  Order  Area\n' );
  fprintf ( 1, '\n' );

  for face = 1 : face_num

    for j = 1 : face_order(face)
      point = face_point(j,face);
      v(1:dim_num,j) = point_coord(1:dim_num,point);
    end

    [ area, normal ] = polygon_area_3d ( face_order(face), v );

    fprintf ( 1, '  %6d  %5d  %8f\n', face, face_order(face), area );

  end
%
%  Find the center of each face.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Face  Center\n' );
  fprintf ( 1, '\n' );

  for i = 1 : face_num

    vave(1:dim_num) = 0.0;

    for j = 1 : face_order(i)
      k = face_point(j,i);
      vave(1:dim_num) = vave(1:dim_num) + point_coord(1:dim_num,k)';
    end

    vave(1:dim_num) = vave(1:dim_num) / face_order(i);

    fprintf ( 1, '  %6d  %10f  %10f  %10f\n', i, vave(1:dim_num) );

  end

  return
end


function [ x, w ] = ncc_nested_rule ( n, x_min, x_max )

%*****************************************************************************80
%
%% NCC_NESTED_RULE computes the nested Newton Cotes Closed rule.
%
%  Discussion:
%
%    Nested version of Newton Cotes Closed rule on [-1,+1].
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 February 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the rule.
%
%    Output, real X(N), W(N), the points and weights.
%

%
%  Get N equally spaced points that, in general, include [ 0, 1];
%
  if ( n == 1 )
    x = 0.5;
  elseif ( n == 2 )
    x = [ 0.5, 0.0 ];
  elseif ( n == 3 )
    x = [ 0.5, 0.0, 1.0 ];
  else
    x = vdc_sequence ( n - 2 );
    x(4:n) = x(2:n-2);
    x(2) = 0.0;
    x(3) = 1.0;
  end
%
%  Linear transformation from [0,1] to [-1,+1].
%
  x = 2.0 * x - 1.0;
%
%  Compute weights.
%
  x_min = -1.0;
  x_max = +1.0;

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

  return
end


function v = r8vec_house_column ( n, a, k )

%*****************************************************************************80
%
%% R8VEC_HOUSE_COLUMN defines a Householder premultiplier that "packs" a column.
%
%  Discussion:
%
%    The routine returns a vector V that defines a Householder
%    premultiplier matrix H(V) that zeros out the subdiagonal entries of
%    column K of the matrix A.
%
%       H(V) = I - 2 * v * v'
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 January 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix A.
%
%    Input, real A(N,1), column K of the matrix A.
%
%    Input, integer K, the column of the matrix to be modified.
%
%    Output, real V(N,1), a vector of unit L2 norm which defines an
%    orthogonal Householder premultiplier matrix H with the property
%    that the K-th column of H*A is zero below the diagonal.
%

%
%  Destroy all row vectors!
%
  a = a(:);

  v(1:n,1) = 0.0;

  if ( k < 1 || n <= k )
    return
  end

  s = sqrt ( sum ( a(k:n,1).^2 ) );

  if ( s == 0.0 )
    return
  end

  if ( a(k,1) < 0.0 )
    v(k,1) = a(k,1) - abs ( s ) ;
  else
    v(k,1) = a(k,1) + abs ( s );
  end
  v(k+1:n,1) = a(k+1:n,1);

  s = sqrt ( sum ( v(k:n,1).^2 ) );
  v(k:n,1) = v(k:n,1) / s;

  return
end


function [ pn, dist ] = circle_imp_point_near_2d ( r, center, p )

%*****************************************************************************80
%
%% CIRCLE_IMP_POINT_NEAR_2D: nearest ( implicit circle, point ) in 2D.
%
%  Discussion:
%
%    This routine finds the distance from a point to an implicitly
%    defined circle, and returns the point on the circle that is
%    nearest to the given point.
%
%    If the given point is the center of the circle, than any point
%    on the circle is "the" nearest.
%
%    An implicit circle in 2D satisfies the equation:
%
%      ( X - CENTER(1) )**2 + ( Y - CENTER(2) )**2 = R**2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the radius of the circle.
%
%    Input, real CENTER(2), the center of the circle.
%
%    Input, real P(2), the point to be checked.
%
%    Output, real PN(2), the nearest point on the circle.
%
%    Output, real DIST, the distance of the point to the circle.
%
  ndim = 2;

  if ( p(1:ndim) == center(1:ndim) )
    dist = r;
    pn(1:ndim) = center(1:ndim) + r / sqrt ( ndim );
    return
  end

  r2 = sqrt ( sum ( ( p(1:ndim) - center(1:ndim) ).^2 ) );

  dist = abs (  r2 - r );

  pn(1:ndim) = center(1:ndim) + r * ( p(1:ndim) - center(1:ndim) ) / r2;

  return
end


%% DEMO of vectorization of elementwise matrix vector multiplication in MATLAB
% D(i,:,:) is a 3x3 or 2x2 matrix on the i-th element
% D can be the tensorial diffusion coefficient of a PDE
% v(i,:) is a 3x1 or 2x1 vector on the i-th element
% v can be the elementwise gradient of a certain nodal basis, e.g.,
% v(i,:) = Dphi(i,:,k) which is the k-th nodal basis's gradient
% We want to compute b(i,:) = D(i,:,:)*v(i,:)
% Even though MATLAB greatly improves the efficiency of for loop after 2016b
% using built-in vectorization operation is still faster.
% Depending on your computer the speed up is about 100x to 150x.
%
% see also Maxwell

%% set up mesh and gradient matrix
[node,elem] = cubemesh([0,1,0,1,0,1],1/32);
center = (node(elem(:,1),:) + node(elem(:,2),:) + ...
    node(elem(:,3),:) + node(elem(:,4),:))/4;
Dlambda = gradbasis3(node,elem);
fprintf('\nSize of gradient of lambda (%d, %d, %d)\n', size(Dlambda));
NT = size(elem,1);

%% set up coefficient matrix (unfortunately arrayfun is not vectorization)
tic;
c = @(p) [1+p(:,1).^2/10 p(:,1).*p(:,2) 0.*p(:,1); ...
    p(:,1).*p(:,2) 1+p(:,2).^2/10 0*p(:,2); ...
    0*p(:,2) 0*p(:,2) 1+p(:,3).^2/10];
tmp = arrayfun(@(rowidx) c(center(rowidx,:)), 1:size(center,1), 'UniformOutput',0);
c2elem = cat(3,tmp{:});
c2elem = permute(c2elem,[3,1,2]);
% permute switch the element idx to the 1st dim
% if the Dlambda tensor has D(:,:,j) corresponds to the j-th element
% then this operation is not neccessary
fprintf('Time to generate elementwise coefficient matrix %5.4g s\n',toc);

%% benchmark the elementwise product
tic;
b = zeros(NT,3,4);
for j = 1:4
    for i = 1:size(elem,1)
        b(i,:,j) = Dlambda(i,:,j)*squeeze(c2elem(i,:,:));
    end
end
t1 = toc;
fprintf('Time to perform elementwise operation %5.4g s\n',t1);

%% benchmark the vectorized routine
tic;
b = zeros(NT,3,4);
for j = 1:4
    b(:,:,j) = sum(bsxfun(@times, c2elem, Dlambda(:,:,j)), 2);
end
t2= toc;
fprintf('Time to perform vectorized operation %5.4g s\n',t2);
fprintf('Speed up factor is %4d.\n', floor(t1/t2));

%% benchmark the vectorized routine
% label for K   1 4 6
%               4 2 5
%               5 6 3

tic;
K(:,4) = center(:,1).*center(:,2);
K(:,3) = 1+center(:,3).^2/10;
K(:,1) = 1+center(:,1).^2/10;
K(:,2) = 1+center(:,2).^2/10;
toc;

tic;
% b1 = K1*D1 + K4*D2 + K6*D3
% b2 = K4*D1 + K2*D2 + K5*D3
% b3 = K5*D1 + K6*D2 + K3*D3
b = zeros(NT,3,4);
for j = 1:4
    b(:,1,j) = K(:,1).*Dlambda(:,1,j) + K(:,4).*Dlambda(:,3,j);
    b(:,2,j) = K(:,4).*Dlambda(:,1,j) + K(:,2).*Dlambda(:,2,j);
    b(:,3,j) = K(:,3).*Dlambda(:,3,j);
end
t3= toc;
fprintf('Time to perform vectorized operation %5.4g s\n',t3);
fprintf('Speed up factor is %4d.\n', floor(t1/t3));


function lp = lagrange_derivative ( nd, xd, ni, xi )

%*****************************************************************************80
%
%% LAGRANGE_DERIVATIVE evaluates the derivative of the Lagrange basis polynomials.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 November 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer ND, the number of data points.
%
%    Input, real XD(ND,1), the data nodes.
%
%    Input, integer NI, the number of evaluation points.
%
%    Input, real XI(NI,1), the evaluation points.
%
%    Output, real LP(NI,ND), the value, at the I-th point XI, of the
%    Jth basis function.
%
  lp = zeros ( ni, nd );

  for i = 1 : ni
    for j = 1 : nd

      for j1 = 1 : nd

        if ( j1 ~= j )
          p = 1.0;
          for j2 = 1 : nd
            if ( j2 == j1 )
              p = p / ( xd(j) - xd(j2) );
            elseif ( j2 ~= j )
              p = p * ( xi(i) - xd(j2) ) / ( xd(j) - xd(j2) );
            end
          end
          lp(i,j) = lp(i,j) + p;
        end

      end

    end
  end

  return
end


function [G, nGrids, nDivs] = GridStructure(n, m)
%   GridStructure - Generate a grid deviding the first octant by polar
%   coordinates. Each element of grid is given by (m-1) integer numbers.
%   The structure is similar to that given by polar coordinates.
%
%   [G, nGrids, nDivs] = GridStructure(n, m)
%
%   Input:
%   n - population size
%   m - number of objectives
%
%   Output:
%   G - grid structure
%   nGrids - number of grids (can be larger than provided population size)
%   nDivs - number of divisions in each right angle
%
%   Example:
%   [G, nGrids, nDivs] = GridStructure(225,3)

%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

% This function is written by Roman Denysiuk

% compute number of divisions
nDivs = ceil( power(n, 1/(m-1)) );

% compute number of grids
nGrids = power(nDivs, m-1);

% initialize grids
G = zeros(nGrids, m-1);

% compute grids
D = m-2;
for j = 0:D
    tmp = repmat(1:nDivs, power(nDivs, j), 1);
    G(:,j+1) = repmat( tmp(:), power(nDivs, D-j), 1);
end

end


%%****************************************************************
%% orthbasis: Compute an orthonomal basis from
%%            the power basis {I,A,A^2, .... ,A^m}
%%            via an Arnoldi-type iteration.
%%
%%   [Q,H,C] = orthbasis(A,m);
%%
%%   Output:  Q = a cell array containing the orthonormal basis
%%                obtained from {I,A,A^2, .... ,A^m}.
%%
%% use in chebymat.m, igmres.m
%%
%% SDPT3: version 3.0
%% Copyright (c) 1997 by
%% K.C. Toh, M.J. Todd, R.H. Tutuncu
%% Last modified: 2 Feb 01
%%****************************************************************

  function [Q,H,C] = orthbasis(A,m);

  N = length(A);
  C(1,1) = 1/sqrt(N);
  Q = cell(1,m+1);
  Q{1} = eye(N)/sqrt(N);
  for k = 1:m
      V = A*Q{k};
      Vold = V;
      for j = 1:k
          H(j,k) = sum(sum(conj(Q{j}).*V));
          V = V - H(j,k)*Q{j};
      end;
      if (norm(V,'fro') < norm(Vold,'fro'));
         for j = 1:k
            s(j,1) = sum(sum(conj(Q{j}).*V));
            V = V - s(j)*Q{j};
         end;
         H(1:k,k) = H(1:k,k) + s;
      end;
      nrm = norm(V,'fro');
      H(k+1,k) = nrm;
      Q{k+1} = V/nrm;
      C(1:k+1,k+1) = ([0; C(1:k,k)] - [C(1:k,1:k)*H(1:k,k); 0])/nrm;
  end;
%%================================================================


function quad = fibonacci_lattice_q1 ( k, f )

%*****************************************************************************80
%
%% FIBONACCI_LATTICE_Q1 applies a Fibonacci lattice integration rule in 2D.
%
%  Discussion:
%
%    This is a modification of the algorithm in FIBONACCI_LATTICE_Q.
%    It uses a nonlinear transformation on the integrand, which makes
%    the lattice rule more suitable for nonperiodic integrands.
%
%    The transformation replaces the integration variable X by
%
%      PHI(X) = 3*X^2 - 2*X**3
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 November 2008
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Ian Sloan, Stephen Joe,
%    Lattice Methods for Multiple Integration,
%    Oxford, 1994,
%    ISBN: 0198534728,
%    LC: QA311.S56
%
%  Parameters:
%
%    Input, integer K, the index of the Fibonacci number to be used.
%    K must be at least 3.
%
%    Input, external real F, the name of the user-supplied routine
%    which evaluates the function, of the form:
%    function f ( dim_num, x )
%    integer dim_num
%    real f
%    real x(dim_num)
%    f = ...
%
%    Output, real QUAD, the estimated integral.
%
  dim_num = 2;

  quad = 0.0;

  m = fibonacci ( k );

  z(1) = 1;
  z(2) = fibonacci ( k - 1 );

  for j = 0 : m - 1
    x(1:dim_num) = mod ( j * z(1:dim_num) / m, 1.0 );
    dphi = 1.0;
    for i = 1 : dim_num
      y(i) = ( 3.0 - 2.0 * x(i) ) * x(i) * x(i);
      dphi = dphi * 6.0 * ( 1.0 - x(i) ) * x(i);
    end
    quad = quad + f ( dim_num, y ) * dphi;
  end

  quad = quad / m;

  return
end


classdef DirichletD
%%DIRICHLETD Functions to handle the Dirichlet distribution.
%Implemented methods are: mean, cov, PDF, rand
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(alph)
%%MEAN Obtain the mean of the Dirichlet distribution for the given
%      concentration parameters.
%
%INPUTS: alph An NX1 vector of positive, real concentration parameters.
%             The length of alpha determines the length of the random
%             vector. If one wishes for the mean of all of the parameters
%             to be equal, then just set alph to all ones.
%
%OUTPUTS: val  The mean of the Dirichlet distribution under consideration.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=alph/sum(alph);
end

function covMat=cov(alph)
%%VAR Obtain the covariance matrix of the Dirichlet distribution for the
%     given concentration parameters.
%
%INPUTS: alph An NX1 vector of positive, real concentration parameters. The
%             length of alpha determines the length of the random vector.
%             If one wishes for the mean of all of the parameters to be
%             equal, then just set alph to all ones.
%
%OUTPUTS: covMat The covariance matrix of the Dirichlet distribution under
%                consideration.
%
%Note that since the elements of the Dirichlet random variable must sum to
%one (i.e. are somewhat dependent), the covariance matrix is singular.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    numVals=length(alph);
    alpha0=sum(alph);
    denom=alpha0^2*(alpha0+1);

    %First, fill in the diagonal elements.
    covMat=diag(alph.*(alpha0-alph)/denom);

    %Then, fill in the off-diagonal elements.
    for curRow=1:numVals
       for curCol=(curRow+1):numVals
           covMat(curRow,curCol)=-alph(curRow)*alph(curCol)/denom;
           covMat(curCol,curRow)=covMat(curRow,curCol);
       end
    end
end

function val=PDF(X,alph)
%%PDF Evaluate the PDF of the Dirichlet distribution at a particular vector
%     for the given concentration parameters.
%
%INPUTS: X An NX1 dirichlet random variable. Its elements must sum to one.
%     alph An NX1 vector of positive, real concentration parameters. If one
%          wishes for the mean of all of the parameters to be equal, then
%          just set alph to all ones.
%
%OUTPUTS: val  The value of the Dirichlet distribution at X given alph.
%
%The Dirichlet distribution is given in Appendix B of [1].
%
%REFERENCES:
%[1] C. M. Bishop, Pattern Recognition and Machine Learning. Cambridge,
%    United Kingdom: Springer, 2007.
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    C=gamma(sum(alph))/prod(gamma(alph));
    val=C*prod(X.^(alph-1));
end

function val=rand(alph)
%%RAND Generate a Dirichlet random vector with concentration vector
%      parameter vector alpha.
%
%INPUTS: alph An NX1 vector of positive, real concentration parameters. The
%             length of alpha determines the length of the random vector
%             generated. If one wishes for the mean of all of the
%             parameters to be equal, then just set alph to all ones.
%
%OUTPUTS: val An NX1 Dirichlet random vector.
%
%Dirichlet random vectors have elements that sum to one and whose
%elements are bounded between 0 and 1. Thus, Dirichlet random vectors are
%useful for generating weights for random mixture distributions.
%
%The Dirichlet random vector is generated by transforming a set of gamma
%distributed random variables. The relationship between the Dirichlet
%distribution and the gamma distribution is discussed in [1].
%
%REFERENCES:
%[1] B. A. Frigyik, A. Kapila, and M. R. Gupta, "Introduction to the
%    Dirichlet Distribution and Related processes", University of
%    Washington Technical Report, No. UWEETR-20-0006, Dec. 2010.
%    https://www.ee.washington.edu/techsite/papers/documents/UWEETR-2010-0006.pdf
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    numVals=length(alph);
    gVals=zeros(numVals,1);
    for curVal=1:numVals
       gVals(curVal)=randGamma(1,alph(curVal),1);
    end

    val=gVals/sum(gVals);
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 sysdfod=dfod3(n,T,r)
%
% sysdfod=dfod3(n,T,r): digital fractional - order differentiator (r > 0)
%                       and integrator (r < 0) in form of the IIR filter;
%                       Recommended restriction for order r: (-1 < r < 1)
% Output: =>
% Discrete system in the form of the IIR filter of the given order 'n'
% obtained by power series expansion of the trapezoidal (Tustin) rule.
%
% Inputs: <=
% n: order of truncation (min. n = 20 is recommended) --> filter order
% T: sampling period in [sec]
% r: approximated fractional order (s^r), r is an arbitrary real number
%
% Copyright (c), 2011, Ivo Petras (ivo.petras@tuke.sk)
%
% Note: It requires a Matlab Control System Toolbox (->FILT function<-)
%
% Example: fractional half order integrator for T=0.1 sec and n = 20 :
% >> FHOI=dfod3(20, 0.1, -0.5); bode(FHOI); figure; step(FHOI);

bcN(1)=1.0; bcD(1)=1.0;
for i=1:n
  bcN(i+1)=((-1)^i)*(gamma(abs(r)+1)./(gamma(i+1).*gamma(abs(r)-i+1)));
  bcD(i+1)=gamma(abs(r)+1)./(gamma(i+1).*gamma(abs(r)-i+1));
end
if r>=0
  sysdfod=((2/T)^r)*(filt(bcN,bcD,T));
end
if r<0
  sysdfod=((2/T)^r)*(filt(bcD,bcN,T));
end
%