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 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 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


%%****************************************************************
%% 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
%


%% Examples of Numerical Solutions of PDEs
% We shall use a sequence of examples to introduce basic components of
% numerical solutions of PDEs.

%% Smooth solutions on regular domains
% We solve the Poisson equation $-\Delta u =1$ in the unit square $\Omega =
% (0,1)\times (0,1)$ with homogenous Dirichlet boundary condition
% $u|_{\partial \Omega}=0$ using linear finite element discrization on a
% sequence of uniform and structured grids.

close all; clear all
figure(1); set(gcf,'Units','normal'); set(gcf,'Position',[0,0,0.45,0.3]);
node = [0,0; 1,0; 1,1; 0,1];    % nodes
elem = [2,3,1; 4,1,3];          % elements
subplot(1,3,1); showmesh(node,elem)
[node,elem] = uniformrefine(node,elem);
subplot(1,3,2); showmesh(node,elem)
[node,elem] = uniformrefine(node,elem);
subplot(1,3,3); showmesh(node,elem)

%%
squarePoisson
% See squarePoisson for details of computation.

%% Smooth solutions on irregular domains
% We solve the Poisson equation in a Lake-type domain. This example shows
% the flexibility of FEM to complex domains.

load lakemesh
f = inline('ones(size(x,1),1)');    % right hand side
g_D = inline('zeros(size(x,1),1)'); % Dirichlet boundary condition
u = Poisson(node,elem,[],f,g_D,[]); % Poisson equation
% graphic
figure(1); set(gcf,'Units','normal'); set(gcf,'Position',[0,0,0.45,0.3]);
subplot(1,2,1); showmesh(node,elem); pause(0.05)
subplot(1,2,2); showsolution(node,elem,u,[0,90]);axis equal; colorbar;

%% Tutorial of iFEM

%% Features of iFEM
%
% * Simple data structures
% * Mesh adaptation in two- and three-dimensions
% * Fast solvers of algebraic equations
% * Easy to use, Easy to code, Easy to debug
% * Efficient programming

%% Basic Data Stucture
%
% *Mesh: node and elem.*
%
% Two matrices |node(1:N,1:d)| and |elem(1:NT,1:d+1)| are used to represent
% a d-dimensional triangulation embedded in $R^d$, where |N| is the number
% of vertices and |NT| is the number of elements.
%
% |node(k,1)| and |node(k,2)| are the x- and y-coordinates of the k-th node
% for points in 2-D. In 3-D, |node(k,3)| gives the additional z-coordinates
% of the k-th node.
%
% |elem(t,1:d+1)| are the global indices of |d+1| vertices which form the
% abstract $d$-simplex |t|. By convention, the vertices of a simplex is ordered
% such that the signed volume is positive. Therefore in 2-D, three vertices
% of a triangle is ordered counterclockwise and in 3-D, the ordering of
% vertices follows the right-hand rule.
%
% Related functions: <matlab:doc('fixorientation') fixorientation>,
% <matlab:doc('label') label>, <matlab:doc('label3') label3>
%
% Documentation: <matlab:ifemdoc('meshdoc') meshdoc>

clear all; close all;

%%
% *Example: L-shape domain in 2-D.*

node = [1,0; 1,1; 0,1; -1,1; -1,0; -1,-1; 0,-1; 0,0];
elem = [1,2,8; 3,8,2; 8,3,5; 4,5,3; 7,8,6; 5,6,8];
figure(1)
showmesh(node,elem)
axis on
findnode(node)
findelem(node,elem)

%%
% *Example: Cube in 3-D.*

node = [-1,-1,-1; 1,-1,-1; 1,1,-1; -1,1,-1; -1,-1,1; 1,-1,1; 1,1,1; -1,1,1];
elem = [1,2,3,7; 1,6,2,7; 1,5,6,7; 1,8,5,7; 1,4,8,7; 1,3,4,7];
figure(2)
showmesh3(node,elem,[],'FaceAlpha',0.25);
view([-53,8]);
axis on
findnode3(node)
findelem3(node,elem)

%%
% *Boundary: bdEdge or bdFace.*
%
% For 2-D triangulations, we use |bdEdge(1:NT,1:3)| to record the type of
% three edges of each element. Similarly in 3-D, we use |bdFace(1:NT,1:4)|
% to record the type of four faces of each element.
% The value is the type of boundary condition listed as follows.
%
% * 0: non-boundary, i.e., an interior edge or face.
% * 1: first type, i.e., a Dirichlet boundary edge or face.
% * 2: second type, i.e., a Neumann boundary edge or face.
% * 3: third type, i.e., a Robin boundary edge or face.
%
% We label three edges of a triangle such that |bdEdge(t,i)| is the edge
% opposite to the i-th vertex. Similarly |bdFace(t,i)| is the face opposite
% to the i-th vertex.
%
% Related functions: <matlab:doc('findboundary') findboundary>,
% <matlab:doc('setboundary') setboundary>, <matlab:doc('findboundary3') findboundary3>
% <matlab:doc('setboundary3') setboundary3>.
%
% Documentation: <matlab:ifemdoc('bddoc') bddoc>

node = [1,0; 1,1; 0,0];
elem = [1 2 3];
edge = [2 3; 1 3; 1 2];
subplot(1,2,1);
showmesh(node,elem);
findedge(node,edge);
findnode(node);
node = [1,1,1; 0,0,0; 1,1,0; 1,0,0];
elem = [1,2,3,4];
subplot(1,2,2);
showmesh3(node,elem,[],'FaceAlpha',0.35); view([-10,18]);
findnode3(node);
findelem3(node,[2,3,4; 1,3,4; 1,2,4; 1,2,3])

%% Finite Element Method
%
%
%%
% * Example 1: The Poisson equation in 2-D
% * Example 2: The Poisson equation: complex domains
% * Example 2: The Poisson equation in 3-D with multigrid solvers

%% Adaptive Finite Element Method
%
%
%%
% * Example 1: The Poisson equation on a 2-D L-shaped domain
% * Example 2: The Poisson equation in 3-D with jump diffusion coefficients

%% Time-dependent Problems
%%
% * Example 1: Heat equation
% * Example 2: Moving interface


function [node,elem] = cubehexmesh(cube,h)
%% CUBEHEXMESH uniform mesh of cube
%
% [node,elem] = cubehexmesh([x0,x1,y0,y1,z0,z1],h) generates a uniform
% cubic mesh of the cube [x0,x1]*[y0,y1]*[z0,z1] with mesh size h.
%
% Example
%  [node,elem] = cubehexmesh([0 1 0 2 0 3],0.5);
%
% See also: squarequadmesh, cubehexgradmesh
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

x0 = cube(1); x1 = cube(2);
y0 = cube(3); y1 = cube(4);
z0 = cube(5); z1 = cube(6);
[z,x,y] = ndgrid(z0:h:z1,x0:h:x1,y0:h:y1);
node = [x(:),y(:),z(:)];
% findnode3(node); view([83 10]);

%% Generate elements
ni = size(x,1); % number of rows
nj = size(x,2); % number of columns
nk = size(x,3); % number of pages
nij = ni*nj;    % number of elements in one page
N = size(node,1);
nodeidx = reshape(1:N,ni,nj,nk);
t2nidxMap = nodeidx(1:ni-1,1:nj-1,1:nk-1);
s = t2nidxMap(:);
elem = [s s+ni s+ni+nij s+nij s+1 s+ni+1 s+ni+nij+1 s+nij+1];
% s+1 s+ni*nj
%  | /
%  s - s + ni


function K = curvature_2D(X,Y,degree)
% CURVATURE_2D estimate curvature of a curve defined by points
%
%   K = CURVATURE_2D(X, Y, DEGREE)
%
%   DEGREE is the degree of the polynom used for the interpolation
%

%
%   Created by Alexandre Gramfort on 2008-12-15.
%   Copyright (c) 2007 Alexandre Gramfort. All rights reserved.
%

% $Id: curvature_2D.m 2 2009-06-16 19:24:10Z gramfort $
% $LastChangedBy: gramfort $
% $LastChangedDate: 2009-06-16 15:24:10 -0400 (Mar, 16 jui 2009) $
% $Revision: 2 $

if nargin<3
    % default values
    degree = 5; % degree of polynum used for interpolation
end

% Find a parametrization of the curve
t = cumsum(sqrt(diff(X).^2 + diff(Y).^2));
t = [0,t];
t = t / t(end); % normalize between 0 and 1

% compute coefficients of interpolation functions
x0 = polyfit(t, X, degree);
y0 = polyfit(t, Y, degree);

% compute coefficients of first and second derivatives. In the case of a
% polynom, it is possible to compute coefficient of derivative by
% multiplying with a matrix.
derive = diag(degree:-1:0);
xp = circshift(x0*derive, [0 1]);
yp = circshift(y0*derive, [0 1]);
xs = circshift(xp*derive, [0 1]);
ys = circshift(yp*derive, [0 1]);

% compute values of first and second derivatives for needed points
xprime = polyval(xp, t);
yprime = polyval(yp, t);
xsec = polyval(xs, t);
ysec = polyval(ys, t);

% compute value of curvature
K = (xprime.*ysec - xsec.*yprime)./ ...
    power(xprime.*xprime + yprime.*yprime, 3/2);


% Return the total number of edges given the adjacency matrix
% INPUTs: adjacency matrix, nxn
% OUTPUTs: m - total number of edges/links
%
% Note: Valid for both directed and undirected, simple or general graph
% Other routines used: selfLoops.m, isSymmetric.m
% GB, last updated Sep 19, 2012

function m = numEdges(adj)

sl=selfLoops(adj); % counting the number of self-loops

if isSymmetric(adj) && sl==0    % undirected simple graph
    m=sum(sum(adj))/2;

elseif isSymmetric(adj) && sl>0
    m=(sum(sum(adj))-sl)/2+sl; % counting the self-loops only once

elseif not(isSymmetric(adj))   % directed graph (not necessarily simple)
    m=sum(sum(adj));

end


%% Example A.1: Linear Advection in a Periodic Domain
%
% The linear advection problem with periodic boundary conditions
%
% $$u_t + u_x = 0, \qquad u(x,0)=u_0(x), \qquad u(0,t)=u(1,t)$$
%
% is well suited for studying error mechanisms in numerical schemes for
% hyperbolic conservation laws. In particular, to study dissipative and
% oscillatory errors, we will use initial data consisting of a combination
% of a smooth, squared cosine wave and double step function.

%%
% We consider two first-order methods (Lax-Friedrichs and the upwind
% method) and two second-order methods (Lax-Wendroff and MacCormack)
T  = 10;
N  = 100; h=1/N; x=h*(1:N);
u0 = (abs(x-.25)<=0.15).*(cos(pi*(10/3)*(x-0.25))).^2 + ...
   1.0*(abs(x-0.75)<0.15);
xx  = linspace(0,1,1001);
uf  = (abs(xx-.25)<=0.15).*(cos(pi*(10/3)*(xx-0.25))).^2 + ...
   1.0*(abs(xx-0.75)<0.15);

method = {'LxF', 'upwind', 'LxW', 'McC'};
name   = {'Lax-Friedrichs', 'Upwind', 'Lax-Wendroff', 'MacCormack'};
for i=1:4
   u=finvol('linearfunc',u0,T,h,1,'periodic',method{i},.9);
   subplot(2,2,i);
   plot(xx,uf,'-',x,u,'o','MarkerSize',2); axis([0 1 -0.2 1.3]);
   title(name{i});
end
%%
% We see that the two first-order schemes smear both the smooth part and
% the discontinuous path of the advected profile and that the
% Lax-Friedrichs method is more diffusive than the upwind method. The
% second-order schemes, on the other hand, preserve the smooth profile
% quite accurately, but introduce spurious oscillations around the two
% discontinuities.


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:
%
%    23 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix A.
%
%    Input, real A(N), column K of the matrix A.
%
%    Input, integer K, the column of the matrix to be modified.
%
%    Output, real V(N), 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.
%
  v(1:n) = 0.0;

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

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

  if ( s == 0.0 )
    return
  end

  v(k) = a(k) + abs ( s ) * r8_sign ( a(k) );
  v(k+1:n) = a(k+1:n);

  v(k:n) = v(k:n) / sqrt ( v(k:n).^2 );

  return
end


function [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters)
%GRADIENTDESCENTMULTI Performs gradient descent to learn theta
%   theta = GRADIENTDESCENTMULTI(x, y, theta, alpha, num_iters) updates theta by
%   taking num_iters gradient steps with learning rate alpha

% Initialize some useful values
m = length(y); % number of training examples
J_history = zeros(num_iters, 1);

for iter = 1:num_iters

    % ====================== YOUR CODE HERE ======================
    % Instructions: Perform a single gradient step on the parameter vector
    %               theta.
    %
    % Hint: While debugging, it can be useful to print out the values
    %       of the cost function (computeCostMulti) and gradient here.
    %

    predictions =  X * theta;
    updates = X' * (predictions - y);
    theta = theta - alpha * (1/m) * updates;

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

    % Save the cost J in every iteration
    J_history(iter) = computeCostMulti(X, y, theta);

end

end


%book : Signals and Systems Laboratory with MATLAB
%by Alex Palamides & Anastasia Veloni

% Fourier Series properties

%time shifting

t0=0;
T=10;
w=2*pi/T;
syms t
x=t*exp(-5*t)
k=-5:5;
a=(1/T)*int(x*exp(-j*k*w*t),t,t0,t0+T);
a1=eval(a);
subplot(211);
stem(k,abs(a1));
title(' Coefficients of x(t)=te^-^5^t');
legend('Magnitude');
subplot(212);
stem(k,angle(a1));
legend('Angle');

figure
t1=3;
right= exp(-j*k*w*t1).*a;
right =eval(right);
subplot(211);
stem(k,abs(right));
legend('Magnitude');
title('Right part');
subplot(212);
stem(k,angle(right));
legend('Angle');

figure
x=(t-t1).*exp(-5*(t-t1));
a=(1/T)*int(x*exp(-j*k*w*t),t,t0+t1,t0+T+t1);
coe=eval(a);
subplot(211);
stem(k,abs(coe));
legend('Magnitude');
title(' Coefficient of (t-3)exp(-5(t-3)) ');
subplot(212);
stem(k,angle(coe));
legend('Angle');


function y=PSNR(noisyImage,restoredImage)

% Compute the PSNR of two gray scale image
% Traditional progarmming using loops
% Class input : [0,1]
% july, 25 , 2012
% KHMOU Youssef

N=size(noisyImage);
if length(N)> 2
    error('Input must be grayscale image');
end
if size(noisyImage)~=size(restoredImage)
    error('The images must have the same size');
end

%if ~isa(noisyImage,'double')
%   noisyImage=double(noisyImage)./255.00;
%end
%if  ~isa(restoredImage,'double')
%    restoredImage=double(restoredImage)./255.00;
%end

% begin

d1=max(noisyImage(:));
d2=max(restoredImage(:));
d=max(d1,d2);

MSE=0;
for i=1:N(1)
    for j=1:N(2)
        if isnan(noisyImage(i,j)) || isinf(restoredImage(i,j))...
                || isnan(restoredImage(i,j)) || isinf(noisyImage(i,j))
            continue;
        end
        MSE=MSE+((abs(noisyImage(i,j)-restoredImage(i,j))).^2);
    end
end

MSE=MSE./(N(1)*N(2));

y=10*log10((d.^2) /MSE)


function [x,y] = EquiNodes2D(N);

% function [x,y] = EquiNodes2D(N);
% Purpose  : Compute (x,y) nodes in equilateral triangle for polynomial of order N

% total number of nodes
Np = (N+1)*(N+2)/2;

% Create equidistributed nodes on equilateral triangle
L1 = zeros(Np,1); L2 = zeros(Np,1); L3 = zeros(Np,1);
sk = 1;
for n=1:N+1
  for m=1:N+2-n
    L1(sk) = (n-1)/N; L3(sk) = (m-1)/N;
    sk = sk+1;
  end
end
L2 = 1.0-L1-L3;

x = -L2+L3; y = (-L2-L3+2*L1)/sqrt(3.0);
return


function value = r4_atanh ( x )

%*****************************************************************************80
%
%% R4_ATANH evaluates the arc-hyperbolic tangent of an R4 argument.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 September 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real VALUE, the arc-hyperbolic tangent of X.
%
  persistent atnhcs;
  persistent dxrel;
  persistent nterms;
  persistent sqeps;

  if ( isempty ( nterms ) )
    atnhcs = [ ...
    0.094395102393195492E+00;
    0.049198437055786159E+00;
    0.002102593522455432E+00;
    0.000107355444977611E+00;
    0.000005978267249293E+00;
    0.000000350506203088E+00;
    0.000000021263743437E+00;
    0.000000001321694535E+00;
    0.000000000083658755E+00;
    0.000000000005370503E+00;
    0.000000000000348665E+00;
    0.000000000000022845E+00;
    0.000000000000001508E+00;
    0.000000000000000100E+00;
    0.000000000000000006E+00 ];
    nterms = r4_inits ( atnhcs, 15, 0.1 * r4_mach ( 3 ) );
    dxrel = sqrt ( r4_mach ( 4 ) );
    sqeps = sqrt ( 3.0 * r4_mach ( 3 ) );
  end

  y = abs ( x );

  if ( y <= sqeps )
    value = x;
  elseif ( y <= 0.5 )
    value = x * ( 1.0 ...
      + r4_csevl ( 8.0 * x * x - 1.0, atnhcs, nterms ) );
  elseif ( y < 1.0 )
    value = 0.5 * log ( ( 1.0 + x ) / ( 1.0 - x ) );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R4_ATANH - Fatal error!\n' );
    fprintf ( 1, '  1 <= |X|.\n' );
    error ( 'R4_ATANH - Fatal error!' )
  end

  return
end


function halton_dataset ( )

%*****************************************************************************80
%
%% HALTON_DATASET generates a Halton dataset and writes it to a file.
%
%  Discussion:
%
%    This program is meant to be used interactively.  It's also
%    possible to prepare a simple input file beforehand and use it
%    in batch mode.
%
%    The program requests input values from the user:
%
%    * NDIM, the spatial dimension,
%    * N, the number of points to generate,
%    * STEP, the index of the first subsequence element to be computed.
%    * SEED(1:NDIM), the Halton sequence index corresponding
%      to STEP = 0.
%    * LEAP(1:NDIM), the successive jumps in the Halton sequence.
%    * BASE(1:NDIM), the Halton bases (usually distinct primes).
%
%    The program generates the data, writes it to the file
%
%      halton_NDIM_N.txt
%
%    where "NDIM" and "N" are the numeric values specified by the user,
%    and then asks the user for more input.   To indicate that no further
%    computations are desired, it is enough to input a nonsensical
%    value, such as -1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 October 2008
%
%  Author:
%
%    John Burkardt
%
  timestamp ( );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'HALTON_DATASET\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Generate a Halton dataset.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This program is meant to be used interactively.\n' );
  fprintf ( 1, '  It is also possible to prepare a simple input \n' );
  fprintf ( 1, '  file beforehand and use it in batch mode.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The program requests input values from the user:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  * NDIM, the spatial dimension,\n' );
  fprintf ( 1, '  * N, the number of points to generate,\n' );
  fprintf ( 1, '  * STEP, the index of the first subsequence element.\n' );
  fprintf ( 1, '  * SEED(1:NDIM), the Halton sequence element\n' );
  fprintf ( 1, '    corresponding to STEP = 0\n' );
  fprintf ( 1, '  * LEAP(1:NDIM), the successive jumps in the\n' );
  fprintf ( 1, '    Halton sequence.\n' );
  fprintf ( 1, '  * BASE(1:M), the Halton bases,\n' );
  fprintf ( 1, '    usually distinct primes.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The program generates the data, writes it to the file\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '    halton_NDIM_N.txt\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  where "NDIM" and "N" are the numeric values specified\n' );
  fprintf ( 1, '  by the user, and then asks the user for more input.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  To indicate that no further computations are \n' );
  fprintf ( 1, '  desired, it is enough to input a nonsensical value, \n' );
  fprintf ( 1, '  such as -1.\n' );

  while ( 1 )

    fprintf ( 1, '  *\n' );
    fprintf ( 1, ' *\n' );
    fprintf ( 1, '*  Ready to generate a new dataset:\n' );
    fprintf ( 1, ' *\n' );
    fprintf ( 1, '  *\n' );
    fprintf ( 1, '\n' );
    fprintf ( 1, '  NDIM is the spatial dimension.\n' );
    fprintf ( 1, '  (Try ''2'' if you have no preference.)\n' );
    fprintf ( 1, '  Any value less than 1 terminates execution.\n' );
    ndim = input ( '  Enter NDIM:  ' );

    fprintf ( 1, '  User input NDIM = %d\n', ndim );

    if ( ~halham_ndim_check ( ndim ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The input value of NDIM = %d\n', ndim );
      fprintf ( 1, '  is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
      break
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  N is the number of points.\n' );
    fprintf ( 1, '  (Try ''25'' if you have no preference.)\n' );
    fprintf ( 1, '  Any value less than 1 terminates execution.\n' );
    n = input ( '  Enter N:  ' );

    fprintf ( 1, '  User input N = %d\n', n );

    if ( ~halham_n_check ( n ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The input value of N = %d\n', n );
      fprintf ( 1, '  is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
      break
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  STEP is the index of the first subsequence element.\n' );
    fprintf ( 1, '  (Try ''0'' or ''1'' if you have no preference.)\n' );
    fprintf ( 1, '  Any value less than 0 terminates execution.\n' );
    step = input ( '  Enter STEP:  ' );

    fprintf ( 1, '  User input STEP = %d\n', step );

    if ( ~halham_step_check ( step ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The input value of STEP = %d\n', step );
      fprintf ( 1, '  is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
      break
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  SEED(1:NDIM) is the starting element index\n' );
    fprintf ( 1, '  for each coordinate.\n' );
    fprintf ( 1, '  (Try ''[0,0,...,0]'' if you have no preference.)\n' );
    fprintf ( 1, '  (Any value less than 0 terminates execution.)\n' );
    seed = [];
    seed(1:ndim) = input ( '  Enter SEED(1:NDIM):  ' );

    fprintf ( 1, '\n' );
    i4vec_transpose_print ( ndim, seed, 'SEED:' );

    if ( ~halham_seed_check ( ndim, seed ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The negative input value of at least one entry of\n' );
      fprintf ( 1, '  SEED is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  LEAP(1:NDIM) is the leaping multiplier\n' );
    fprintf ( 1, '  for each coordinate.\n' );
    fprintf ( 1, '  (Try ''[1,1,...,1]'' if you have no preference.)\n' );
    fprintf ( 1, '  (Another choice is a prime bigger than all the bases.)\n' );
    fprintf ( 1, '  (Any value less than 1 terminates execution.)\n' );
    leap = [];
    leap(1:ndim) = input ( '  Enter LEAP(1:NDIM):  ' );

    fprintf ( 1, '\n' );
    i4vec_transpose_print ( ndim, leap, 'LEAP:' );

    if ( ~halham_leap_check ( ndim, leap ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The input value of at least one entry of\n' );
      fprintf ( 1, '  LEAP is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, '  BASE(1:NDIM) is the base for each coordinate,\n' );
    fprintf ( 1, '  usually distinct primes.\n' );
    fprintf ( 1, '  (Try ''[2,3,5,7,11,13,...]'' if you have no preference.)\n' );
    fprintf ( 1, '  (Any value less than 2 terminates execution.)\n' );
    base = [];
    base(1:ndim) = input ( '  Enter BASE:  ' );

    fprintf ( 1, '\n' );
    i4vec_transpose_print ( ndim, base, 'BASE:' );

    if ( ~halton_base_check ( ndim, base ) )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'HALTON_DATASET\n' );
      fprintf ( 1, '  The input value of at least one entry of\n' );
      fprintf ( 1, '  BASE is interpreted as a request for termination.\n' );
      fprintf ( 1, '  Normal end of execution.\n' );
    end

    r = i4_to_halton_sequence ( ndim, n, step, seed, leap, base );

    file_out_name = ...
      strcat ( 'halton_', num2str ( ndim ), '_', num2str ( n ), '.txt' );

    halham_write ( ndim, n, step, seed, leap, base, r, file_out_name );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  The data was written to the file "%s".\n', ...
      file_out_name );

  end

  fprintf ( 1, '\n' );
  timestamp ( );

  return
end


function turn = angle_turn_2d ( p1, p2, p3 )

%*****************************************************************************80
%
%% ANGLE_TURN_2D computes a turning angle in 2D.
%
%  Discussion:
%
%    This routine is most useful when considering the vertices of a
%    polygonal shape.  We wish to distinguish between angles that "turn
%    in" to the shape, (between 0 and 180 degrees) and angles that
%    "turn out" (between 180 and 360 degrees), as we traverse the boundary.
%
%    If we compute the interior angle and subtract 180 degrees, we get the
%    supplementary angle, which has the nice property that it is
%    negative for "in" angles and positive for "out" angles, and is zero if
%    the three points actually lie along a line.
%
%    Assuming P1, P2 and P3 define an angle, the TURN can be
%    defined to be either:
%
%    * the supplementary angle to the angle formed by P1=P2=P3, or
%
%    * the angle between the vector ( P3-P2) and the vector -(P1-P2),
%      where -(P1-P2) can be understood as the vector that continues
%      through P2 from the direction P1.
%
%    The turning will be zero if P1, P2 and P3 lie along a straight line.
%
%    It will be a positive angle if the turn from the previous direction
%    is counterclockwise, and negative if it is clockwise.
%
%    The turn is given in radians, and will lie between -PI and PI.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 March 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(2), P2(2), P3(2), the points that form
%    the angle.
%
%    Output, real TURN, the turn angle, between -PI and PI.
%
  p(1) = ( p3(1) - p2(1) ) * ( p1(1) - p2(1) ) ...
       + ( p3(2) - p2(2) ) * ( p1(2) - p2(2) );

  p(2) = ( p3(1) - p2(1) ) * ( p1(2) - p2(2) ) ...
       - ( p3(2) - p2(2) ) * ( p1(1) - p2(1) );

  if ( p(1) == 0.0 & p(2) == 0.0 )
    turn = 0.0;
  else
    turn = pi - r8_atan ( p(2), p(1) );
  end

  return
end


function area = polygon_area_3d_2 ( n, v, area )

%*****************************************************************************80
%
%% POLYGON_AREA_3D_2 computes the area of a polygon in 3D.
%
%  Discussion:
%
%    The computation is not valid unless the vertices of the polygon
%    lie in a plane, so that the polygon that is defined is "flat".
%
%    The polygon does not have to be "regular", that is, neither its
%    sides nor its angles need to be equal.
%
%    The area is computed as the sum of the areas of the triangles
%    formed by the last node with consecutive pairs of nodes (1,2),
%    (2,3), ..., and (N-2,N-1).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 October 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Adrian Bowyer and John Woodwark,
%    A Programmer's Geometry,
%    Butterworths, 1983.
%
%  Parameters:
%
%    Input, integer N, the number of vertices of the polygon.
%
%    Input, real V(3,N), the coordinates of the vertices.
%
%    Output, real AREA, the area of the polygon.
%
  area_vector(1:3) = 0.0;

  for i = 1 : n - 2

    t(1:3,1:3) = [ v(1:3,i)'; v(1:3,i+1)'; v(1:3,n)' ]';

    area_vector_triangle = triangle_area_vector_3d ( t );

    area_vector(1:3) = area_vector(1:3) + area_vector_triangle(1:3);

  end

  area = 0.5 * sqrt ( sum ( area_vector(1:3).^2 ) );

  return
end


function rotated=uniform_rotation_3D(v)
% This function perform a unformly random rotation 3D.
% It is clear that in 2 dimensions that this means the
% rotation angle is uniformly distributed between (0, 2pi).
% However, it is NOT correct and does NOT carry over to
% higher dimensions.
%
% More information see Le?n, Carlos A.; Mass?, Jean-Claude;
% Rivest, Louis-Paul (February 2006), "A statistical model
% for random rotations", Journal of Multivariate Analysis 97
% (2): 412?430, doi:10.1016/j.jmva.2005.03.009, ISSN 0047-259X

% Arguments (input):
%   v - 3*1 vector needs to be rotated
%
%
% arguments (output):
%   rotated - 3*1 vector after unformly random rotation
%
%
% References: J. Arvo (1992), Fast Random Rotation Matrices
%
% Author: Yaming Wang. ETH Zurich.
% email: yaming.wang@sed.ethz.ch
% Release: 1.00
% Release data: 18.09.2012

rot_1=2*pi*rand(1);
matrix_1=[cos(rot_1),sin(rot_1),0;...
    -sin(rot_1),cos(rot_1),0;...
    0,0,1];

rot_2a=2*pi*rand(1);
rot_2b=rand(1);

Householder_v=[cos(rot_2a)*sqrt(rot_2b)
    sin(rot_2a)*sqrt(rot_2b)
    sqrt(1-rot_2b)];

% Householder matrix
matrix_2=eye(3)-2*Householder_v*Householder_v';

rotated=-matrix_2*matrix_1*v;

fprintf(1,'rotation finished.\n');

% ====================================================
%      end of function
% ====================================================


% LegendrePoly.m by David Terr, Raytheon, 5-10-04

% Given nonnegative integer n, compute the
% Legendre polynomial P_n. Return the result as a vector whose mth
% element is the coefficient of x^(n+1-m).
% polyval(LegendrePoly(n),x) evaluates P_n(x).

function pk = LegendrePoly(n)

if n==0
    pk = 1;
elseif n==1
    pk = [1 0]';
else

    pkm2 = zeros(n+1,1);
    pkm2(n+1) = 1;
    pkm1 = zeros(n+1,1);
    pkm1(n) = 1;

    for k=2:n

        pk = zeros(n+1,1);

        for e=n-k+1:2:n
            pk(e) = (2*k-1)*pkm1(e+1) + (1-k)*pkm2(e);
        end

        pk(n+1) = pk(n+1) + (1-k)*pkm2(n+1);
        pk = pk/k;

        if k<n
            pkm2 = pkm1;
            pkm1 = pk;
        end

    end

end