function theta = vectorAngle3d(v1, v2)
%VECTORANGLE3D Angle between two 3D vectors.
%
%   THETA = vectorAngle3d(V1, V2)
%   Computes the angle between the 2 3D vectors V1 and V2. The result THETA
%   is given in radians, between 0 and PI.
%
%
%   Example
%   % angle between 2 orthogonal vectors
%   vectorAngle3d([1 0 0], [0 1 0])
%   ans =
%       1.5708
%
%   % angle between 2 parallel vectors
%   v0 = [3 4 5];
%   vectorAngle3d(3*v0, 5*v0)
%   ans =
%       0
%
%   See also
%   vectors3d, vectorNorm3d, crossProduct3d
%

% ------
% Author: David Legland
% E-mail: david.legland@inra.fr
% Created: 2010-10-04, using Matlab 7.9.0.529 (R2009b)
% Copyright 2010-2022 INRA - Cepia Software Platform

% compute angle using arc-tangent to get better precision for angles near
% zero, see the discussion in:
% http://www.mathworks.com/matlabcentral/newsreader/view_thread/151925#381952
theta = atan2(vectorNorm3d(crossProduct3d(v1, v2)), sum(bsxfun(@times, v1, v2),2));

% equivalent to:
% v1 = normalizeVector3d(v1);
% v2 = normalizeVector3d(v2);
% theta = acos(dot(v1, v2, 2));


function val=StirlingNumber2(n,k)
%%STIRLINGNUMBER2 Compute the Stirling number of the second kind {n,k},
%                 which is also called a Stirling set number. This is the
%                 number of ways to partition a set of n objects into k
%                 non-empty subsets. The number is computed using a
%                 recursion that will not overflow unless the actual number
%                 overflows. When n is very large, the function can be
%                 slow.
%
%INPUTS: n The integer total number of items in the set n>=0.
%        k The desired integer number of non-empty subsets of the set.
%          k>=0.
%
%OUTPUTS: val The number of ways of partitioning n items into k subsets. If
%             an overflow occurs, this will be infinite.
%
%The implementation uses the recurrence relation from [1].
%
%The more commonly seen expression in terms of a sum of binomials is not
%desirable, because overflows will occur even when the final number does
%not overflow.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Stirling Number of the Second Kind." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/StirlingNumberoftheSecondKind.html
%
%October 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(n<k)
    val=0;
    return;
end

curN=zeros(k+1,1);
prevN=zeros(k+1,1);

prevN(0+1)=1;%{0,0}=1
for nCur=1:n
    for kCur=1:min(nCur,k)
        curN(kCur+1)=prevN(kCur-1+1)+kCur*prevN(kCur+1);
    end
    prevN=curN;
end
val=prevN(k+1);

end

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


function val=doubleFactorial(x)
%%DOUBLEFACTORIAL Evaluate x!!, which is the double factorial (also known
%                 as semifactorial) of x. If x is odd, then the double
%                 factorial is defined as x*(x-2)*(x-4)*...*5*3*1. If x is
%                 even, then it is x(x-2)*(x-4)*...*6*4*2. The double
%                 factorials of 0 and -1 are defined to be 1.
%
%INPUTS: x A scalar or matrix, where the double factorial of each
%          element should be evaluated. The values must be positive
%          integers, or 0 or -1.
%
%OUTPUTS: val The double factorial of each value of x.
%
%The gamma function/factorial representations of the double factorial for
%even and odd values are taken from [1].
%
%Values <=50 are tabulated. For other values, the functions are implemented
%using logarithmic functions so as to minimize the effects of overflow with
%intermediate results.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Double Factorial." From MathWorld--A Wolfram Web
%    Resource. http://mathworld.wolfram.com/DoubleFactorial.html
%
%October 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

numEl=length(x(:));

val=zeros(size(x));
for curEl=1:numEl
    xCur=x(curEl);

    if(xCur<=50)
        %If we can use a tabulated formula.
        if(xCur<-1)
            error('xCur must be >=-1.')
        end
        table=[1,1,1,2,3,8,15,48,105,384,945,3840,10395,46080,135135,645120,2027025,10321920,34459425,185794560,654729075,3715891200,13749310575,81749606400,316234143225,1961990553600,7905853580625,51011754393600,213458046676875,1428329123020800,6190283353629375,42849873690624000,191898783962510625,1371195958099968000,6332659870762850625,46620662575398912000,221643095476699771875,1678343852714360832000,8200794532637891559375,63777066403145711616000,319830986772877770815625,2551082656125828464640000,13113070457687988603440625,107145471557284795514880000,563862029680583509947946875,4714400748520531002654720000,25373791335626257947657609375,216862434431944426122117120000,1192568192774434123539907640625,10409396852733332453861621760000,58435841445947272053455474390625,520469842636666622693081088000000];

        val(curEl)=table(xCur+2);
    else
        if(xCur==0||xCur==-1)
            val(curEl)=1;
        elseif(mod(xCur,2)==0)%If it is divisible by 2.
            k=xCur/2;
            val(curEl)=exp(k*log(2)+gammaln(k+1));
        else%Assume that it is odd.
            n=(xCur+1)/2;
            val(curEl)=exp(gammaln(xCur+2)-(n*log(2)+gammaln(n+1)));
        end
    end
end

end

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


function [ c, s ] = spherical_harmonic ( l, m, theta, phi )

%*****************************************************************************80
%
%% SPHERICAL_HARMONIC evaluates spherical harmonic functions.
%
%  Discussion:
%
%    The spherical harmonic function Y(L,M,THETA,PHI)(X) is the
%    angular part of the solution to Laplace's equation in spherical
%    coordinates.
%
%    Y(L,M,THETA,PHI)(X) is related to the associated Legendre
%    function as follows:
%
%      Y(L,M,THETA,PHI)(X) = FACTOR * P(L,M)(cos(THETA)) * exp ( i * M * PHI )
%
%    Here, FACTOR is a normalization factor:
%
%      FACTOR = sqrt ( ( 2 * L + 1 ) * ( L - M )! / ( 4 * PI * ( L + M )! ) )
%
%    In Mathematica, a spherical harmonic function can be evaluated by
%
%      SphericalHarmonicY [ l, m, theta, phi ]
%
%    Note that notational tradition in physics requires that THETA
%    and PHI represent the reverse of what they would normally mean
%    in mathematical notation; that is, THETA goes up and down, and
%    PHI goes around.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 March 2005
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%    Eric Weisstein,
%    CRC Concise Encyclopedia of Mathematics,
%    CRC Press, 1999.
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input, integer L, the first index of the spherical harmonic function.
%    Normally, 0 <= L.
%
%    Input, integer M, the second index of the spherical harmonic function.
%    Normally, -L <= M <= L.
%
%    Input, real THETA, the polar angle, for which
%    0 <= THETA <= PI.
%
%    Input, real PHI, the longitudinal angle, for which
%    0 <= PHI <= 2*PI.
%
%    Output, real C(1:L+1), S(1:L+1), the real and imaginary
%    parts of the functions Y(L,0:L,THETA,PHI).
%
  m_abs = abs ( m );

  plm(1:l+1) = legendre_associated_normalized ( l, m_abs, cos ( theta ) );

  c(1:l+1) = plm(1:l+1) * cos ( m * phi );
  s(1:l+1) = plm(1:l+1) * sin ( m * phi );

  if ( m < 0 )
    c(1:l+1) = -c(1:l+1);
    s(1:l+1) = -s(1:l+1);
  end

  return
end


function y=atanSlope3(x)
%%ATANSLOPE3 Evaluate the function -3*(atan(x)-x)/x^3 avoiding problems at
%            the point x=0, where the limit equals 1. This function arises
%            in range enclosure algorithms for interval arithmetic.
%
%INPUTS: x A vector of matrix of real values at which the function should
%          be evaluated.
%
%OUTPUTS: y The value(s) of the function -3*(atan(x)-x)/x^3 at the point(s)
%           in x.
%
%For values of x having magnitude over 1e-2 or for complex values, the
%function is evaluated as written. For smaller values, a Taylor series
%expansion is used to avoid the singularity near the origin.
%
%This is one of the slope function in Table 10.6 of Section 10.6.2 of [1].
%This file implements the function for non-intervals. See the Interval
%class for an implementation for Interval arithmetic.
%
%REFERENCES:
%[1] IEEE Standard for Interval Arithmetic," in IEEE Std 1788-2015,
%    pp.1-97, June 30 2015.
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Allocate space
y=zeros(size(x));

%For large enough values, use the standard function.
sel=abs(x)>1e-2|~isreal(x);
x1=x(sel);
y(sel)=-3*(atan(x1)-x1)./x1.^3;

%For smaller magnitude values, use an eigth-order Taylor series expansion.
%The relative error at 10^-2 is on the order of 1e-23, which is less than
%the precision of a double floating point number at that value. The series
%is given in Horner form.
x1=x(~sel);
y(~sel)=1+x1.^2.*(-(3/5)+x1.^2.*(3/7+x1.^2.*(-(1/3)+(3*x1.^2)/11)));

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 [ n_data, n, area ] = sphere_unit_area_values ( n_data )

%*****************************************************************************80
%
%% SPHERE_UNIT_AREA_VALUES returns some areas of the unit sphere in ND.
%
%  Discussion:
%
%    The formula for the surface area of the unit sphere in N dimensions is:
%
%      Sphere_Unit_Area ( N ) = 2 * PI**(N/2) / Gamma ( N / 2 )
%
%    Some values of the function include:
%
%       N   Area
%
%       2    2        * PI
%       3  ( 4 /    ) * PI
%       4  ( 2 /   1) * PI**2
%       5  ( 8 /   3) * PI**2
%       6  ( 1 /   1) * PI**3
%       7  (16 /  15) * PI**3
%       8  ( 1 /   3) * PI**4
%       9  (32 / 105) * PI**4
%      10  ( 1 /  12) * PI**5
%
%    For the unit sphere, Area(N) = N * Volume(N)
%
%    In Mathematica, the function can be evaluated by:
%
%      2 * Pi^(n/2) / Gamma[n/2]
%
%  Modified:
%
%    19 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Stephen Wolfram,
%    The Mathematica Book,
%    Fourth Edition,
%    Wolfram Media / Cambridge University Press, 1999.
%
%  Parameters:
%
%    Input/output, integer N_DATA.
%    On input, if N_DATA is 0, the first test data is returned, and
%    N_DATA is set to the index of the test data.  On each subsequent
%    call, N_DATA is incremented and that test data is returned.  When
%    there is no more test data, N_DATA is set to 0.
%
%    Output, integer N, the spatial dimension.
%
%    Output, real AREA, the area of the unit sphere
%    in that dimension.
%
  n_max = 20;

  area_vec = [ ...
     0.2000000000000000E+01, ...
     0.6283185307179586E+01, ...
     0.1256637061435917E+02, ...
     0.1973920880217872E+02, ...
     0.2631894506957162E+02, ...
     0.3100627668029982E+02, ...
     0.3307336179231981E+02, ...
     0.3246969701133415E+02, ...
     0.2968658012464836E+02, ...
     0.2550164039877345E+02, ...
     0.2072514267328890E+02, ...
     0.1602315322625507E+02, ...
     0.1183817381218268E+02, ...
     0.8389703410491089E+01, ...
     0.5721649212349567E+01, ...
     0.3765290085742291E+01, ...
     0.2396678817591364E+01, ...
     0.1478625959000308E+01, ...
     0.8858104195716824E+00, ...
     0.5161378278002812E+00 ];

  n_vec = [ ...
     1, ...
     2, ...
     3, ...
     4, ...
     5, ...
     6, ...
     7, ...
     8, ...
     9, ...
    10, ...
    11, ...
    12, ...
    13, ...
    14, ...
    15, ...
    16, ...
    17, ...
    18, ...
    19, ...
    20 ];

  if ( n_data < 0 )
    n_data = 0;
  end

  n_data = n_data + 1;

  if ( n_max < n_data )
    n_data = 0;
    n = 0;
    area = 0.0;
  else
    n = n_vec(n_data);
    area = area_vec(n_data);
  end

  return
end


function chi = chi_measure ( dim_num, n, z, ns, sample_routine, seed_init )

%*****************************************************************************80
%
%% CHI_MEASURE determines the pointset quality measure CHI.
%
%  Discussion:
%
%    The CHI measure of point distribution quality for a set Z of
%    N points in an DIM_NUM-dimensional region is defined as follows:
%
%    Assign every point X in the region to the nearest element
%    Z(I) of the point set.  For each Z(I), let H(I) be the maximum
%    distance between Z(I) and any point assigned to it by this process.
%
%    For each point Z(I), we determine the nearest distinct element of
%    the pointset by
%
%      GAMMA(I) = minimum ( 1 <= J <= N, I /= J ) distance ( Z(I), Z(J) )
%
%    Then
%
%      CHI(I) = 2 * H(I) / GAMMA(I)
%
%    and
%
%      CHI = maximum ( 1 <= I <= N ) CHI(I)
%
%    This quantity can be estimated by using sampling to pick a large
%    number of points in the region, rather than all of them.
%
%    For an ideally regular mesh, all the CHI(I)'s will be equal.
%    Any deviation from regularity increases the value of some entries
%    of CHI; thus, given two meshes, the one with a lower value of
%    CHI is to be recommended.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 November 2004
%
%  Author:
%
%    Max Gunzburger
%    John Burkardt
%
%  Reference:
%
%    Max Gunzburger and John Burkardt,
%    Uniformity Measures for Point Samples in Hypercubes.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real ( kind = 8 ) Z(DIM_NUM,N), the points.
%
%    Input, integer NS, the number of sample points.
%
%    Input, character SAMPLE_ROUTINE, the name of the function to be used to
%    return sample points in the region.  The function must have the form
%      [ x, seed ] = sample_routine ( dim_num, n, seed )
%
%    Input, integer SEED_INIT, the initial value of the random number seed.
%
%    Output, real CHI, the CHI quality measure.
%
  seed = seed_init;
  h(1:n) = 0.0;

  for k = 1 : ns

    [ x, seed ] = feval ( sample_routine, dim_num, 1, seed );

    closest = find_closest ( dim_num, n, 1, x, z );

    dist = sum ( ( x(1:dim_num) - z(1:dim_num,closest(1)) ).^2 );

    h(closest(1)) = max ( h(closest(1)), dist );

  end

  gamma = pointset_spacing ( dim_num, n, z );

  chi_vec(1:n) = 2.0 * sqrt ( h(1:n) ) ./ gamma(1:n);

  chi = max ( chi_vec(1:n) );

  return
end


function y=sinhSlope3(x)
%%SINHSLOPE3 Evaluate the function 6*(sinh(x)-x)/x^3 avoiding
%            problems at the point x=0, where the limit equals 1. This
%            function arises in range enclosure algorithms for interval
%            arithmetic.
%
%INPUTS: x A vector of matrix of real values at which the function should
%          be evaluated.
%
%OUTPUTS: y The value(s) of the function 6*(sinh(x)-x)/x^3 at the
%           point(s) in x.
%
%For values of x having magnitude over 1e-2 or for complex values, the
%function is evaluated as written. For smaller values, a Taylor series
%expansion is used to avoid the singularity near the origin.
%
%This is two times one of the slope function in Table 10.6 of Section
%10.6.2 of [1]. As the standard says the value at 0 is 1, but the value of
%the function in the standard at 0 is 1/2, it is assumed that there is a
%typo in the standard. Hence this function is twice that listed in [1].
%This file implements the function for non-intervals. See the Interval
%class for an implementation for Interval arithmetic.
%
%REFERENCES:
%[1] IEEE Standard for Interval Arithmetic," in IEEE Std 1788-2015,
%    pp.1-97, June 30 2015.
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Allocate space
y=zeros(size(x));

%For large enough values, use the standard function.
sel=abs(x)>1e-2|~isreal(x);
x1=x(sel);
y(sel)=6*(sinh(x1)-x1)./x1.^3;

%For smaller magnitude values, use an sixth-order Taylor series expansion.
%The relative error at 10^-2 is on the order of 1e-23, which is less than
%the precision of a double floating point number at that value. The series
%is given in Horner form.
x1=x(~sel);
y(~sel)=1+x1.^2.*(1/20+x1.^2.*(1/840+x1.^2/60480));

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 [xx, yy] = secdraw(start_angle, sector_angle, radius)

%  usage: [xx, yy]  = secdraw(start_angle, sector_angle, radius, clk_wise)
%
%  Input:
%            start_angle  - starting angle in degrees, [0 is default]
%                           NOTE: this can be positive or negative
%            sector_angle - central angle of sector in degrees
%                           NOTE: if negative, plotting will be clockwise
%                                 direction.
%            radius       - radius of sector (default 1)
%
% Output:
%            returns the corner points (xx, yy) of a patch for a sector,
%            which can plotted using the patch(...) function
%            NOTE:
%              1. if less than 2 or NO output variables are given,
%                 secdraw(...) draws the sector on the current (or a new)
%                 figure
%              2. if one argument is given,
%                 the argument is taken as the central angle
%
% Example 1 > [xx, yy]  = secdraw(45, 90, 10);
%             patch( xx, yy, 'b', 'EdgeColor', 'b', 'EraseMode', 'none') ;
%             set( gca, 'DataAspectRatio', [1 1 1] );
%             - this will draw a sector from 45 to 90 degrees with radius=1
%
% Example 2 > secdraw( 60 )
%             - this will draw a sector from 0 to 60 degrees counter
%               clockwise
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% author: Laine Berhane Kahsay
%
% date  : 19-Feb-2004
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin < 1 | isempty( nargin )
    %disp '';
    disp '-- error in usage --------------------------------';
    disp '      Not enough input arguments.';
    help secdraw;
    return;
elseif nargin == 1
    sector_angle   = start_angle;
    start_angle = 0;
    radius      = 1;
else nargin == 2
    radius  = 1;
end

theta0 = pi*0/180;              % offset angle in radians
theta1 = pi*start_angle/180;    % starting angle in radians
theta  = pi*sector_angle/180;   % central angle in radians

angle_ratio = theta/(2*pi);     % ratio of the sector to the complete circle
rho = abs(radius);              % abs(...) can be removed
MaxPts = 100;                   % maximum number of points in a whole circle.
                                % if set to small # (e.g 10) the resolution
                                % of the curve will be poor.
                                % generally values greater than 50
                                % will give (very) good resolution

n = abs( ceil( MaxPts*angle_ratio ) );
r = [ 0; rho*ones(n+1,1); 0 ];
theta = theta0 + theta1 + [ 0; angle_ratio*(0:n)'/n; 0 ]*2*pi;

% output
[xx,yy] = pol2cart(theta,r);

% plot if not enough output variable are given
if nargout < 2,
    hh=patch(xx, yy, 'b','EdgeColor','b','EraseMode','none');
end


classdef HypergeometricD
%%HYPERGEOMETRICD Functions to handle the scalar hypergeometric
%                 distribution. Given an urn containg N1+N2 objects, N2 of
%                 type 1 and N2 of type 2, choose N balls. The number of
%                 balls of type 1 that is chosen is given by a
%                 hypergeometric distribution with parameters n, N1 and N2.
%Implemented methods are: mean, var, PMF, CDF, rand
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)
function val=mean(n,N1,N2)
%%MEAN Obtain the mean of the hypergeometric distribution.
%
%INPUTS: n The total number of objects drawn. n<=N1+N2.
%       N1 The number of objects of type 1.
%       N2 The number of objectes of type 2.
%
%OUTPUTS: val The mean of the hypergeometric distribution under
%             consideration.
%
%The hypergeometric distribution is given in Chapter 2.8 of [1].
%
%EXAMPLE:
%We verify that the computed variance by comparing it to the sample
%variance.
% n=20;
% N1=63;
% N2=28;
% varVal=HypergeometricD.mean(n,N1,N2)
% numSamp=1e3;
% sampVarVal=mean(HypergeometricD.rand([1,numSamp],n,N1,N2))
%One will find both values are about 13.836
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=n*N1/(N1+N2);
end

function val=var(n,N1,N2)
%%VAR Obtain the variance of the hypergeometric distribution.
%
%INPUTS: n The total number of objects drawn. n<=N1+N2.
%       N1 The number of objects of type 1.
%       N2 The number of objectes of type 2.
%
%OUTPUTS: val The variance of the hypergeometric distribution under
%             consideration.
%
%The hypergeometric distribution is given in Chapter 2.8 of [1].
%
%EXAMPLE:
%We verify that the computed variance by comparing it to the sample
%variance.
% n=20;
% N1=63;
% N2=28;
% varVal=HypergeometricD.var(n,N1,N2)
% numSamp=1e3;
% sampVarVal=var(HypergeometricD.rand([1,numSamp],n,N1,N2))
%One will find both values are about 3.36.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=n*N1*N2/(N1+N2)^2*(1-(n-1)/(N1+N2-1));
end

function val=PMF(x,n,N1,N2)
%%PMF Evaluate the hypergeometric probability mass function (PMF) at given
%     points.
%
%INPUTS: x The point(s) at which the hypergeometric PMF is evaluated.
%        n The total number of objects drawn. n<=N1+N2.
%        N1 The number of objects of type 1.
%        N2 The number of objectes of type 2.
%
%OUTPUTS: val The PMF of the hypergeometric distribution evaluated at the
%             desired point(s).
%
%The hypergeometric distribution is given in Chapter 2.8 of [1].
%
%EXAMPLE:
%Here, we validate the PMF by generating random samples and comparing the
%PMF plot with a histogram of the random samples.
% n=20;
% N1=25;
% N2=15;
% numSamples=1e5;
% figure(1)
% clf
% histogram(HypergeometricD.rand([numSamples,1],n,N1,N2),'BinWidth',1,'Normalization','pdf')
% hold on
% x=0:20;
% vals=HypergeometricD.PMF(x,n,N1,N2);
% stem(x,vals,'linewidth',2)
% h1=xlabel('x');
% h2=ylabel('PDF(x)');
% set(gca,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h1,'FontSize',14,'FontWeight','bold','FontName','Times')
% set(h2,'FontSize',14,'FontWeight','bold','FontName','Times')
%One will see that the histogram matches well with the plot.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

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

    denom=binomial(N1+N2,n);
    for curEl=1:numEls
        i=x(curEl);
        if(i>0&&i<=n)
            val(curEl)=binomial(N1,i).*binomial(N2,n-i)/denom;
        end
    end
end

function val=CDF(x,n,N1,N2)
%%CDF Evaluate the cumulative distribution function of the hypergeometric
%     distribution at desired points.
%
%INPUTS: x The point(s) at which the hypergeometric CDF is evaluated.
%        n The total number of objects drawn. n<=N1+N2.
%        N1 The number of objects of type 1.
%        N2 The number of objectes of type 2.
%
%OUTPUTS: val The CDF of the hypergeometric distribution evaluated at the
%             desired point(s).
%
%The hypergeometric distribution is given in Chapter 2.8 of [1].
%
%EXAMPLE:
%We validate the CDF value by comparing it to a value computed from random
%samples.
% n=20;
% N1=25;
% N2=15;
% x=12;
% numSamples=1e5;
% prob=HypergeometricD.CDF(x,n,N1,N2)
% probSamp=mean(HypergeometricD.rand([numSamples,1],n,N1,N2)<=x)
%One will find the values of both be about 0.5.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

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

    denom=binomial(N1+N2,n);
    for curEl=1:numEls
        i=floor(x(curEl));
        if(i>0&&i<=n)
            %Just sum the numerators in the PDF and normalize. This is
            %slow if N1+N2 is large.

            sumVal=0;
            for k=0:i
                sumVal=sumVal+binomial(N1,k).*binomial(N2,n-k);
            end
            val(curEl)=sumVal/denom;
        elseif(i>n)
           val(curEl)=1;
        end
    end
end

function x=rand(N,n,N1,N2)
%%RAND Generate hypergeometric random variables.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row vector, then rand
%          returns an MXN1 matrix of random variables.
%        n The total number of objects drawn. n<=N1+N2.
%        N1 The number of objects of type 1.
%        N2 The number of objectes of type 2.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated hypergeometric random variables.
%
%The inverse transform method fo Chapter 4.1 of [1] is used.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, 4th ed. Amsterdam: Academic Press, 2006.
%
%March 2017 David F. Crouse, Naval Research Laboratory, Washington D.C.

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

    denom=binomial(N1+N2,n);

    x=zeros(dims);
    numEls=prod(dims);

    for curEl=1:numEls
        U=rand();
        cumProb=0;
        for k=0:n
            cumProb=cumProb+binomial(N1,k).*binomial(N2,n-k)/denom;

            if(U<=cumProb)
                break;
            end
        end
        x(curEl)=k;
    end
end
end
end

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


% 样条插值举例
clear; clc

X = [27.7, 28, 29, 30];
Y = [4.1, 4.3, 4.1, 3.0];
df0 = 3.0; dfn = -4.0;  % 第一类边界条件

n = length(X) - 1;
H = diff(X); % 每个插值小区间的长度
mu = H(1:n-1) ./ (H(1:n-1) + H(2:n));
lambda = 1 - mu;
% 计算二阶差商
Y1 = diff(Y) ./ diff(X);  % 一阶差商
Y2 = diff(Y1) ./ ( X(3:end) - X(1:end-2) );  % 二阶差商
% 计算右端项
d = 6*Y2;
d0 = 6/H(1) * (Y1(1) - df0);
dn = 6/H(end) * (dfn - Y1(end));
% 给出系数矩阵
A = 2*eye(n+1) + diag([mu(:);1],-1) +diag([1;lambda(:)],1);
b = [d0; d(:); dn];
M = A\b;

% 计算 s_k(x) 的系数, 两种形式
p = zeros(n,4); p0 = zeros(n,4);
for k = 1 : n
    p(k,1) = (M(k+1) - M(k))/(6*H(k));
    p(k,2) = M(k)/2;
    p(k,3) = (Y(k+1) - Y(k))/ H(k) - H(k)/6 * (2*M(k) + M(k+1));
    p(k,4) = Y(k);
    p0(k,1) = M(k)/(6*H(k));
    p0(k,2) = M(k+1)/(6*H(k));
    p0(k,3) = (Y(k) - M(k)*H(k)*H(k)/6) / H(k);
    p0(k,4) = (Y(k+1) - M(k+1)*H(k)*H(k)/6) / H(k);
end

% 调用 Matlab 的三次样条插值函数
pp = spline(X, [df0;Y(:);dfn]);

%输出结果
fprintf('按形式一输出: \n'); disp(p0);
fprintf('按形式二输出: \n'); disp(p);
fprintf('spline的结果(形式二): \n'); disp(pp.coefs);


function val=numInvolutions(n)
%%NUMINVOLUTIONS Determine the number of involutions of length n. An
%                involution is a permution of items 1:n such that the
%                permutation is its own inverse. The number of involutions
%                also equals the number of possible Young tableau having n
%                cells.
%
%INPUTS: n A positive integer >=0.
%
%OUTPUTS: val The number of involutions of length n. For n=0, this is
%             defined as 1.
%
%This function uses the recurrence relation given in Equation 40 in Section
%5.1.4 of [1].
%
%REFERENCES:
%[1] D. Knuth, The Art of Computer Programming: Sorting and Searching, 2nd
%    ed. Boston: Addison-Wesley, 2018, vol. 3.
%
%November 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(n<0)
    error('n must be >=0.')
end

if(n<=1)
    val=1;
    return;
end

an1=1;
an=1;
for k=2:n
    an2=an1;
    an1=an;
    an=an1+(k-1)*an2;
end
val=an;
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 [optN, C, N] = sshist(x,N)
% [optN, C, N] = sshist(x,N)
%
% Function `sshist' returns the optimal number of bins in a histogram
% used for density estimation.
% Optimization principle is to minimize expected L2 loss function between
% the histogram and an unknown underlying density function.
% An assumption made is merely that samples are drawn from the density
% independently each other.
%
% The optimal binwidth D* is obtained as a minimizer of the formula,
% (2K-V) / D^2,
% where K and V are mean and variance of sample counts across bins with width D.
% Optimal number of bins is given as (max(x) - min(x)) / D*.
%
% For more information, visit
% http://2000.jukuin.keio.ac.jp/shimazaki/res/histogram.html
%
% Original paper:
% Hideaki Shimazaki and Shigeru Shinomoto
% A method for selecting the bin size of a time histogram
% Neural Computation 19(6), 1503-1527, 2007
% http://dx.doi.org/10.1162/neco.2007.19.6.1503
%
% Example usage:
% optN = sshist(x); hist(x,optN);
%
% Input argument
% x:    Sample data vector.
% N (optinal):
%       A vector that specifies the number of bins to be examined.
%       The optimal number of bins is selected from the elements of N.
%       Default value is N = 2:50.
%       * Do not search binwidths smaller than a sampling resolution of data.
%
% Output argument
% optN: Optimal number of bins.
% N:    Bin numbers examined.
% C:    Cost function of N.
%
% See also SSKERNEL
%
% Copyright (c) 2009 2010, Hideaki Shimazaki All rights reserved.
% http://2000.jukuin.keio.ac.jp/shimazaki

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Parameters Setting
x = reshape(x,1,numel(x));
x_min = min(x);
x_max = max(x);

if nargin < 2
    buf = abs(diff(sort(x)));
    dx = min(buf(logical(buf ~= 0)));
    N_MIN = 2;              % Minimum number of bins (integer)
                            % N_MIN must be more than 1 (N_MIN > 1).
    N_MAX = min(floor((x_max - x_min)/(2*dx)),50);
                            % Maximum number of bins (integer)
    N = N_MIN:N_MAX;        % # of Bins
end

SN = 30;                    % # of partitioning positions for shift average
D = (x_max - x_min) ./ N;   % Bin Size Vector

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Computation of the Cost Function
Cs = zeros(length(N),SN);
for i = 1: length(N)

       shift = linspace(0,D(i),SN);
       for p = 1 : SN
               edges = linspace(x_min+shift(p)-D(i)/2,...
                        x_max+shift(p)-D(i)/2,N(i)+1);   % Bin edges

               ki = histc(x,edges);               % Count # of events in bins
               ki = ki(1:end-1);

               k = mean(ki);                      % Mean of event count
               v = sum( (ki-k).^2 )/N(i);         % Variance of event count

               Cs(i,p) = ( 2*k - v ) / D(i)^2;    % The Cost Function
       end

end
C = mean(Cs,2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Optimal Bin Size Selectioin
[Cmin idx] = min(C);
optN = N(idx);                         % Optimal number of bins
%optD = D(idx);                         % *Optimal binwidth
%edges = linspace(x_min,x_max,N(idx));  % Optimal segmentation


function [ ] = montyhall(n,d,o)
%montyhall(n,d,o) Simulates n rounds of the Monty Hall problem and
%                 gives win/loss ratio
%
%                n   : Number of rounds to simulate (Any positive integer)
%                d   : Number of doors (Positive integer >= 3)
%                o=0 : Show final win/loss score and estimated probability
%                o=1 : Show win/loss tally chart and estimated probability
%                o=2 : Show results for each round
%
% All parameters are optional, by default they will take the values:
%  n=1, d=3, o=0.
%
% The Monty Hall problem is a probability puzzle based on the American
% television game show Let's Make a Deal. The name comes from the show's
% host, Monty Hall. The problem is also called the Monty Hall paradox,
% as it is a veridical paradox in that the result appears absurd but is
% demonstrably true.
% http://en.wikipedia.org/wiki/Monty_Hall_problem
%
%
%------------------------%

win=0;lose=0;tally=[0;0];Monty=0;
%-- Check for nonexistent variables and set to defaults
if exist('n')~=1, n=1; end
if exist('d')~=1 || d<3 || d~=round(d), d=3; end
if exist('o')~=1, o=0; end
%--

if o==2
    for i = 1:n
        %-- Picks a random door for the car to be behind
        Car = randi(d)-1;
        %-- Player picks a random door
        Choose = randi(d)-1;
        %-- Monty recursively picks a random door until he has chosen
        %   the door that neither has the car behind it or has been
        %   chosen by the player
        while (Monty==Car || Monty==Choose), Monty=randi(d)-1; end
        %-- If you originally choose the car, no matter what door Monty
        %   opens, you will lose by switching.
        %   If you originally choose a goat, Monty has to open a door to
        %   reveal the other goat, and switching will switch to the car
        %   meaning you win.
        %   Simply put, if you originally choose the car, switching wins
        %   and if you don't, switching loses.
        %   This is the basis of the score tally system
        if Choose==Car, lose=lose+1; else win=win+1; end
        %-- Display round results after game has been played.
        disp(['Round ',num2str(i)]);
        disp('Chosen door:');disp([zeros(1,Choose),1,zeros(1,(d-1)-Choose)]);
        if Car<Choose, disp('Monty opens:');disp([ones(1,Car),0,ones(1,Choose-Car-1),0,ones(1,(d-1)-Choose)]); end
        if Car>Choose, disp('Monty opens:');disp([ones(1,Choose),0,ones(1,Car-Choose-1),0,ones(1,(d-1)-Car)]); end
        if Car==Choose
            if Car<Monty, disp('Monty opens:');disp([ones(1,Car),0,ones(1,Monty-Car-1),0,ones(1,(d-1)-Monty)]); else disp('Monty opens:');disp([ones(1,Monty),0,ones(1,Car-Monty-1),0,ones(1,(d-1)-Car)]); end
        end
        disp('Car is behind:');disp([zeros(1,Car),1,zeros(1,(d-1)-Car)]);
        if Choose==Car, disp('Switching loses'); else disp('Switching wins'); end
        disp(' ');disp('   Win | Lose');disp([win,lose]);
        disp('---------------------');
    end
else
    for i = 1:n
        %-- When detail~=2, the next few lines simulate the game
        %   instead. This is a lot simpler as all unnecessary commands are
        %   removed. In the original block of code (where detail=2), the
        %   code can be summarised as;
        %   Pick 2 random numbers (Car and Choose), pick a random number
        %   not equal to those numbers (Monty) and finally check if the two
        %   original numbers are equal.
        %   The number that is chosen for Monty does not affect whether a
        %   win or a loss is tallied, so it is not needed for the simulation.
        Car = randi(d)-1;
        Choose = randi(d)-1;
        %-- Defining 'Monty' is not needed to decide a win or a loss.
        %   while (Monty==Car || Monty==Choose), Monty=randi(d)-1; end
        if Choose==Car, lose=lose+1; else win=win+1; end
        tally=[tally,[win;lose]];
    end
end
if o==1
    disp(['W: ',num2str(tally(1,1:n+1))]);
    disp(['L: ',num2str(tally(2,1:n+1))]);
else
    disp(['Won  ',num2str(win)]);
    disp(['Lost ',num2str(lose)]);
end
if n>=10, disp(['Estimated Chance Of Winning After Switch: ',num2str(win/n)]); end
end


function M = Pythagor_tree(m,n,Colormap)
% function M = Pythagor_tree(m,n,Colormap)
% Compute Pythagoras_tree
% The Pythagoras Tree is a plane fractal constructed from squares.
% It is named after Pythagoras  because each triple of touching squares
% encloses a right triangle, in a configuration traditionally used to
% depict the Pythagorean theorem.
% http://en.wikipedia.org/wiki/Pythagoras_tree
%
% Input :
%       - m ( double m> 0) is the relative length of one of the side
%         right-angled triangle. The second side of the right-angle is
%         taken to be one.
%         To have a symmetric tree, m has to be 1.
%       - n ( integer ) is the level of recursion.
%         The number of elements of tree is equal to 2^(n+1)-1.
%         A reasonnable number for n is 10.
%       - Colormap: String used to generate color of the different levels
%         of the tree.
%       All these arguments are optional: the function can run with
%       argument.
% Output :
%       - Matrix M: Pyhagoras tree is stored in a matrix M.
%         This matrix has 5 columns.
%         Each row corresponds to the cordinate of each square of the tree
%         The two first columns give the bottom-left position of each
%         square. The third column corresponds to the orientation angle of
%         each square. The fourth column gives the size of each square. The
%         fifth column specifies the level of recursion of each square.
%         The first row corresponds to the root of the tree. It is always
%         the same
%         M(1,:) = [0 -1 0 1 1];
%         The leaf located at row i will give 2 leaves located at 2*i and
%         2*i+1.
%       - A svg file giving a vectorial display of the tree. The name of
%         file is generated from the parameter m,n,Colormap. The file is
%         stored in the current folder.
%
% 2010 02 29
% Guillaume Jacquenot
% guillaume dot jacquenot at gmail dot com

%% Check inputs
narg = nargin;
if narg <= 2
    % Colormap = 'jet';
    Colormap = 'summer';
    if narg <= 1
        n = 12; % Recursion level
        if nargin == 0
            m = 0.8;
        end
    end
end
if m <= 0
	error([mfilename ':e0'],'Length of m has to be greater than zero');
end
if rem(n,1)~=0
	error([mfilename ':e0'],'The number of level has to be integer');
end
if ~iscolormap(Colormap)
	error([mfilename ':e1'],'Input colormap is not valid');
end
%% Compute constants
d      = sqrt(1+m^2);                  %
c1     = 1/d;                          % Normalized length 1
c2     = m/d;                          % Normalized length 2
T      = [0 1/(1+m^2);1 1+m/(1+m^2)];  % Translation pattern
alpha1 = atan2(m,1);                   % Defines the first rotation angle
alpha2 = alpha1-pi/2;                  % Defines the second rotation angle
pi2    = 2*pi;                         % Defines pi2
nEle   = 2^(n+1)-1;                    % Number of elements (square)
M      = zeros(nEle,5);                % Matrice containing the tree
M(1,:) = [0 -1 0 1 1];                 % Initialization of the tree

%% Compute the level of each square contained in the resulting matrix
Offset = 0;
for i = 0:n
    tmp = 2^i;
    M(Offset+(1:tmp),5) = i;
    Offset = Offset + tmp;
end
%% Compute the position and size of each square wrt its parent
for i = 2:2:(nEle-1)
    j          = i/2;
    mT         = M(j,4) * mat_rot(M(j,3)) * T;
    Tx         = mT(1,:) + M(j,1);
    Ty         = mT(2,:) + M(j,2);
    theta1     = rem(M(j,3)+alpha1,pi2);
    theta2     = rem(M(j,3)+alpha2,pi2);
    M(i  ,1:4) = [Tx(1) Ty(1) theta1 M(j,4)*c1];
    M(i+1,1:4) = [Tx(2) Ty(2) theta2 M(j,4)*c2];
end
%% Display the tree
Pythagor_tree_plot(M,n);

%% Write results to an SVG file
Pythagor_tree_write2svg(m,n,Colormap,M);

function Pythagor_tree_write2svg(m,n,Colormap,M)
% Determine the bounding box of the tree with an offset
% Display_metadata = false;
Display_metadata = true;

nEle    = size(M,1);
r2      = sqrt(2);
LOffset = M(nEle,4) + 0.1;
min_x   = min(M(:,1)-r2*M(:,4)) - LOffset;
max_x   = max(M(:,1)+r2*M(:,4)) + LOffset;
min_y   = min(M(:,2)          ) - LOffset;  % -r2*M(:,4)
max_y   = max(M(:,2)+r2*M(:,4)) + LOffset;

% Compute the color of tree
ColorM = zeros(n+1,3);
eval(['ColorM = flipud(' Colormap '(n+1));']);
co   = 100;
Wfig = ceil(co*(max_x-min_x));
Hfig = ceil(co*(max_y-min_y));
filename = ['Pythagoras_tree_1_' strrep(num2str(m),'.','_') '_'...
             num2str(n) '_' Colormap '.svg'];
fid  = fopen(filename, 'wt');
fprintf(fid,'<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n');
if ~Display_metadata
    fprintf(fid,'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"\n');
    fprintf(fid,'  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n');
end
fprintf(fid,'<svg width="%d" height="%d" version="1.1"\n',Wfig,Hfig); %
% fprintf(fid,['<svg width="12cm" height="4cm" version="1.1"\n']); % Wfig,

% fprintf(fid,['<svg width="15cm" height="10cm" '...
%              'viewBox="0 0 %d %d" version="1.1"\n'],...
%              Wfig,Hfig);
if Display_metadata
    fprintf(fid,'\txmlns:dc="http://purl.org/dc/elements/1.1/"\n');
    fprintf(fid,'\txmlns:cc="http://creativecommons.org/ns#"\n');
    fprintf(fid,['\txmlns:rdf="http://www.w3.org/1999/02/22'...
                 '-rdf-syntax-ns#"\n']);
end
fprintf(fid,'\txmlns:svg="http://www.w3.org/2000/svg"\n');
fprintf(fid,'\txmlns="http://www.w3.org/2000/svg"\n');
fprintf(fid,'\txmlns:xlink="http://www.w3.org/1999/xlink">\n');

if Display_metadata
    fprintf(fid,'\t<title>Pythagoras tree</title>\n');
    fprintf(fid,'\t<metadata>\n');
    fprintf(fid,'\t\t<rdf:RDF>\n');
    fprintf(fid,'\t\t\t<cc:Work\n');
    fprintf(fid,'\t\t\t\trdf:about="">\n');
    fprintf(fid,'\t\t\t\t<dc:format>image/svg+xml</dc:format>\n');
    fprintf(fid,'\t\t\t\t<dc:type\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://purl.org/dc/dcmitype/StillImage" />\n');
    fprintf(fid,'\t\t\t\t<dc:title>Pythagoras tree</dc:title>\n');
    fprintf(fid,'\t\t\t\t<dc:creator>\n');
    fprintf(fid,'\t\t\t\t\t<cc:Agent>\n');
    fprintf(fid,'\t\t\t\t\t\t<dc:title>Guillaume Jacquenot</dc:title>\n');
    fprintf(fid,'\t\t\t\t\t</cc:Agent>\n');
    fprintf(fid,'\t\t\t\t</dc:creator>\n');
    fprintf(fid,'\t\t\t\t<cc:license\n');
    fprintf(fid,'\t\t\t\t\t\trdf:resource="http://creativecommons.org/licenses/by-nc-sa/3.0/" />\n');
    fprintf(fid,'\t\t\t</cc:Work>\n');
    fprintf(fid,'\t\t\t<cc:License\n');
    fprintf(fid,'\t\t\t\trdf:about="http://creativecommons.org/licenses/by-nc-sa/3.0/">\n');
    fprintf(fid,'\t\t\t\t<cc:permits\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#Reproduction" />\n');
    fprintf(fid,'\t\t\t\t<cc:permits\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#Reproduction" />\n');
    fprintf(fid,'\t\t\t\t<cc:permits\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#Distribution" />\n');
    fprintf(fid,'\t\t\t\t<cc:requires\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#Notice" />\n');
    fprintf(fid,'\t\t\t\t<cc:requires\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#Attribution" />\n');
    fprintf(fid,'\t\t\t\t<cc:prohibits\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#CommercialUse" />\n');
    fprintf(fid,'\t\t\t\t<cc:permits\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#DerivativeWorks" />\n');
    fprintf(fid,'\t\t\t\t<cc:requires\n');
    fprintf(fid,'\t\t\t\t\trdf:resource="http://creativecommons.org/ns#ShareAlike" />\n');
    fprintf(fid,'\t\t\t</cc:License>\n');
    fprintf(fid,'\t\t</rdf:RDF>\n');
    fprintf(fid,'\t</metadata>\n');
end
fprintf(fid,'\t<defs>\n');
fprintf(fid,'\t\t<rect width="%d" height="%d" \n',co,co);
fprintf(fid,'\t\t\tx="0" y="0"\n');
fprintf(fid,'\t\t\tstyle="fill-opacity:1;stroke:#00d900;stroke-opacity:1"\n');
fprintf(fid,'\t\t\tid="squa"\n');
fprintf(fid,'\t\t/>	\n');
fprintf(fid,'\t</defs>\n');
fprintf(fid,'\t<g transform="translate(%d %d) rotate(180) " >\n',...
                round(co*max_x),round(co*max_y));
for i = 0:n
    fprintf(fid,'\t\t<g style="fill:#%s;" >\n',...
                generate_color_hexadecimal(ColorM(i+1,:)));
    Offset = 2^i-1;
    for j = 1:2^i
        k = j + Offset;
        fprintf(fid,['\t\t\t<use xlink:href="#squa" ',...
                     'transform="translate(%+010.5f %+010.5f)'...
                     ' rotate(%+010.5f) scale(%8.6f)" />\n'],...
                    co*M(k,1),co*M(k,2),M(k,3)*180/pi,M(k,4));
    end
    fprintf(fid,'\t\t</g>\n');
end
fprintf(fid,'\t</g>\n');
fprintf(fid,'</svg>\n');
fclose(fid);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function M = mat_rot(x)
c = cos(x);
s = sin(x);
M=[c -s; s c];

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function H = Pythagor_tree_plot(D,ColorM)
if numel(ColorM) == 1
    ColorM = flipud(summer(ColorM+1));
end
H = figure('color','w');
hold on
axis equal
axis off
for i=1:size(D,1)
    cx    = D(i,1);
    cy    = D(i,2);
    theta = D(i,3);
    si    = D(i,4);
    M     = mat_rot(theta);
    x     = si*[0 1 1 0 0];
    y     = si*[0 0 1 1 0];
    pts   = M*[x;y];
    fill(cx+pts(1,:),cy+pts(2,:),ColorM(D(i,5)+1,:));
    % plot(cx+pts(1,1:2),cy+pts(2,1:2),'r');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Scolor = generate_color_hexadecimal(color)
Scolor = '000000';
for i=1:3
    c = dec2hex(round(255*color(i)));
    if numel(c)==1
        Scolor(2*(i-1)+1) = c;
    else
        Scolor(2*(i-1)+(1:2)) = c;
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function  res = iscolormap(cmap)
% This function returns true if 'cmap' is a valid colormap
LCmap = {...
    'autumn'
    'bone'
    'colorcube'
    'cool'
    'copper'
    'flag'
    'gray'
    'hot'
    'hsv'
    'jet'
    'lines'
    'pink'
    'prism'
    'spring'
    'summer'
    'white'
    'winter'
};

res = ~isempty(strmatch(cmap,LCmap,'exact'));


function xyz = rtp_to_xyz ( r, theta, phi )

%*****************************************************************************80
%
%% RTP_TO_XYZ converts (R,Theta,Phi) to (X,Y,Z) coordinates.
%
%  Discussion:
%
%    R measures the distance of the point to the origin.
%
%    Theta measures the "longitude" of the point, between 0 and 2 PI.
%
%    PHI measures the angle from the "north pole", between 0 and PI.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, THETA, PHI, the radius, longitude, and
%    declination of a point.
%
%    Output, real XYZ(3,1), the corresponding Cartesian coordinates.
%
  xyz = zeros ( 3, 1 );

  xyz(1,1) = r * cos ( theta ) * sin ( phi );
  xyz(2,1) = r * sin ( theta ) * sin ( phi );
  xyz(3,1) = r *                 cos ( phi );

  return
end


function h = circle_segment_height_from_area ( r, area )

%*****************************************************************************80
%
%% CIRCLE_SEGMENT_HEIGHT_FROM_AREA: height of a circle segment from area.
%
%  Discussion:
%
%    Begin with a circle of radius R.  Choose two points P1 and P2 on the
%    circle, and draw the chord P1:P2.  This chord divides the circle
%    into two pieces, each of which is called a circle segment.
%    Consider one of the pieces.  The "angle" of this segment is the angle
%    P1:C:P2, where C is the center of the circle.  Let Q be the point on
%    the chord P1:P2 which is closest to C.  The "height" of the segment
%    is the distance from Q to the perimeter of the circle.
%
%    This function is given the radius R and area of the segment, and
%    determines the corresponding height.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 May 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the radius of the circle.
%    0 < R.
%
%    Input, real AREA, the area of the circle segment.
%    0 <= AREA <= 2.0 * PI * R^2.
%
%    Output, real H, the height of the circle segment.
%
  if ( area < 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!\n' );
    fprintf ( 1, '  AREA < 0.0.\n' );
    error ( 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!' );
  end

  area_circle = 2.0 * pi * r^2;

  if ( area == 0.0 )
    h = 0.0;
    return
  end

  if ( area == area_circle )
    h = 2.0 * r;
    return
  end

  if ( area_circle < area )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!\n' );
    fprintf ( 1, '  2.0 * pi * r^2 < AREA.\n' );
    error ( 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!' );
  end

  if ( r <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!\n' );
    fprintf ( 1, '  R <= 0.0.\n' );
    error ( 'CIRCLE_SEGMENT_HEIGHT_FROM_AREA - Fatal error!' );
  end

  h1 = 0.0;
  a1 = circle_segment_area_from_height ( r, h1 );
  h2 = 2.0 * r;
  a2 = circle_segment_area_from_height ( r, h2 );

  it = 0;

  while ( it < 30 )

    h = 0.5 * ( h1 + h2 );
    a = circle_segment_area_from_height ( r, h );
    it = it + 1;

    if ( abs ( a - area ) < sqrt ( eps ) * area )
      break
    end

    if ( a < area )
      h1 = h;
      a1 = a;
    else
      h2 = h;
      a2 = a;
    end

  end

  return
end


function HaarTransformationMatrix=ConstructHaarWaveletTransformationMatrix(WidthOfSquareMatrix)
%--------------------------------------------------------------------------
%Create Haarwavelet transformation matrix H for the matrix vector
%mulplication implimentation of Haar wavelet transformation.
%This function uses the following nice formula to create the Haar
%transformation matrix:
%               H_n=1/sqrt(2)[H_(n/2) kron (1 1)
%                             I_(n/2) kron (1 -1)],
%                              where 'kron' denotes the kronecker product.
%The iteration starts with H_1=[1]. The normalization constant 1/sqrt(2)
%ensure that H_n^T*H_n=I, where I is identity matrix. Haar wavelets are the
%rows of H_n.
%--------------------------------------------------------------------------
%function HaarTransformationMatrix=ConstructHaarWaveletTransformationMatrix(WidthOfSquareMatrix)
% Input:
%       WidthOfSquareMatrix: the width of sqaure Haar wavelet
%                                  transformation matrix.
% Output:
%       HaarTransformationMatrix: Ceated Haar transformation matrix and
%       it's size is the power of 2,i.e., 2, 4,
%       8,16,32,64,128,256,512,1024,2048,4096,etc.
%--------------------------------------------------------------------------
%Author: Jin Qi
%Email: jqichina@hotmail.com
%Date:  11/4/2011
%--------------------------------------------------------------------------
%Test function for one dimentional signal
%
% n=8;
% S=rand(n,1); % for one dimentional signal
% H=ConstructHaarWaveletTransformationMatrix(n);
% C=H*S; %Haar wavelet transformation
% RS=H'*C;% Reconstruct signal
% fprintf('reconstruction error is %f',norm(S-RS));%plot reconstruction error
%--------------------------------------------------------------------------
%Test for two dimentional signal,ie. image
%
% n=8;
% S=rand(n,n); % for one dimentional signal
% H=ConstructHaarWaveletTransformationMatrix(n);
% C=H*S*H'; %Haar wavelet transformation
% RS=H'*C*H;% Reconstruct signal
% fprintf('reconstruction error is %f',norm(S-RS,'fro'));%plot reconstruction error

n=WidthOfSquareMatrix; % copy the parameter

% check input parameter and make sure it's the power of 2
Level=log2(n);
if 2^Level<n, error('please ensure the value of input parameter is the power of 2');end

%Initialization
H=[1];
NC=1/sqrt(2);%normalization constant
LP=[1 1];
HP=[1 -1];

% iteration from H=[1]
for i=1:Level
    H=NC*[kron(H,LP);kron(eye(size(H)),HP)];
end
HaarTransformationMatrix=H;


% Euclidean projection on a hyperplane
% Section 8.1.1, Boyd & Vandenberghe "Convex Optimization"
% Joelle Skaf - 10/04/05
%
% The projection of x0 on a hyperplane C = {x | a'*x = b} is given by
%           minimize || x - x0 ||^2
%               s.t.    a'*x = b
% It is also given by P_C(x0) = x0 + (b - a'*x0)*a/||a||^2

% Input data
randn('seed',0);
n  = 10;
a  = randn(n,1);
b  = randn(1);
x0 = randn(n,1);

% Analytical solution
fprintf(1,'Computing the analytical solution ...');
pc_x0 = x0 + (b - a'*x0)*a/norm(a)^2;
fprintf(1,'Done! \n');

% Solution via QP
fprintf(1,'Computing the optimal solution by solving a QP ...');

cvx_begin quiet
    variable x(n)
    minimize ( square_pos(norm(x - x0)) )
    a'*x == b;
cvx_end

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

% Verification
disp('--------------------------------------------------------------------------------');
disp('Verifying that p_C(x0) and x_star belong to the hyperplane C: ');
disp(['a^T*p_C(x0) - b = ' num2str(a'*pc_x0 - b)]);
disp(['a^T*x_star - b  = ' num2str(a'*x - b)]);
disp('Computing the distance between x0 and the hyperplane in each case');
disp(['||x0 - p_C(x0)|| = ' num2str(norm(x0 - pc_x0))]);
disp(['||x0 - x_star || = ' num2str(norm(x0 - x))]);
disp('Verifying that the analytical solution and the solution obtained via QP are equal: ');
[pc_x0 x]


function yi = LagrangeInter(x,y,xi)

% SYNTAX:
%   yi = LagrangeInter(x,y,xi);
%
% INPUT:
%   x,y = row-vectors of (n+1) data values (x,y)
%   xi  = a row-vector of x-values, where interpolation is to be found (could be a single value)
%
% OUTPUT:
%   yi = a row-vector of interpolated y-values
%
% DESCRIPTION:
%   Lagrange interpolation algorithm.

%----------------------------------------------------------------------------------------------
%
% Author: Dmitry Pelinovsky
% Available online at: http://dmpeli.mcmaster.ca/Matlab/Math4Q3/Lecture2-1/LagrangeInter.m
%
%----------------------------------------------------------------------------------------------

n = length(x) - 1; % the degree of interpolation polynomial
ni = length(xi); % the number of x-values, where interpolation is to be found

L = ones(n+1,ni); % the matrix for Lagrange interpolating polynomials L_(n,k)(x)
                    % has (n+1) rows for each polynomial at k = 0,1,...,n
                    % has ni column for each x-value of xi

% Note: the algorithm uses the MATLAB capacities for matrix handling!
% The two nested loops below are designed to compute in parallel
% the values of Lagrange interpolating polynomials at each x-value of xi !

for k = 0 : n % start the outer loop through the data values for x

    for kk = 0 : (k-1) % start the inner loop through the data values for x (if k = 0 this loop is not executed)
        L(kk+1,:) = L(kk+1,:).*(xi - x(k+1))/(x(kk+1)-x(k+1)); % see the Lagrange interpolating polynomials
    end % end of the inner loop

    for kk = k+1 : n % start the inner loop through the data values (if k = n this loop is not executed)
        L(kk+1,:) = L(kk+1,:).*(xi - x(k+1))/(x(kk+1)-x(k+1));
    end % end of the inner loop

end % the end of the outer loop

% Now multiply the values for Lagrange interpolating polynomials by the data values for y
yi = y * L; % use matrix multiplication of row-vector y and the matrix L, the output is the row-vector


function [d,F,G]=principalAngVec(A,B)
%%PRINCANGPRINCVEC Given an mXp matrix and an mXq matrix with p>=q, compute
%           the principal angles and vectors between the matrices. This can
%           be used in canonical correlation analysis to find combinations
%           of variables with maximum correlation between each other.
%           Specifically, the principle angles are defined recursively by
%           d(k)=cos(theta_k)=F(:,k)'*G(:,k)=
%               max_{F(:,k)} max_{G(:,k)} F(:,k)'*G(:,k)
%           where in the optimization F(:,k)  is a unit vector in the space
%           spanned by A that is orthogonal to all F(:,i) with i<k, and
%           G(:,k) is similarly a unit vector in the space spanned by B
%           that is orthogonal to all G(,i) with i<k.
%
%INPUTS: A An mXp matrix with independent columns.
%        B An mXq matrix with independent columns q<=p.
%
%OUTPUTS: d A qX1 vector of the cosine values of the principle angles (Use
%           acos to get the angles). The angles all satisfy 0<=theta<=pi/2.
%         F mXq The first set of principal vectors.
%         G mXq The second set of principal vectors.
%
%This function implements Algorithm 6.4.3 in Chapter 6.4 of [1].
%
%EXAMPLE:
%This function can be used to quickly tell if two matrices are identicle
%except for a reordering and scaling of the columns. If they are, then the
%principal angles will all be zero (the cosines will all be 1). We
%demonstrate this here:
% A=[8,0,1;
%    9,2,9;
%    1,5,9;
%    9,9,4;
%    6,9,8];
% B=-4*A(:,[3,1,2]);%Scale and permute the columns.
% [d,F,G]=principalAngVec(A,B)
%One will see that the three d values are all 1 within finite precision
%bounds.
%
%REFERENCES:
%[1] G. H. Golub and C. F. Van Loan, Matrix Computations, 4th ed.
%    Baltimore: Johns Hopkins University Press, 2013.
%
%November 2015 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

q=size(B,2);

if(q>size(A,2))
    error('The number of columns of B must be <= the number of columns of A.')
end

[QA,~]=qr(A,0);
[QB,~]=qr(B,0);
[Y,D,Z]=svd(QA'*QB);
F=QA*Y(:,1:q);
G=QB*Z(:,1:q);
d=diag(D);

end

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


function val=greatestCommonDivisor(m,n)
%%GREATESTCOMMONDIVISOR Given two integers m and n, determine the integer
%           that is the greatest common divisor. This is like the gcd
%           function that is built into Matlab, but it can be useful to
%           have an explcit function if one wishes to use a different data
%           type with appropriately overloaded operators, such as for
%           extended precision arithmetic.
%
%INPUTS: m, n Two positive real integers.
%
%OUTPUTS: val The greatest common divisor of the integers.
%
%This function implements Algorithm F in Problem 3 of Section 1.1 of [1].
%
%EXAMPLE:
% val=greatestCommonDivisor(24,32)
%One will get val=8.
%
%REFERENCES:
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 1: Fundamental
%    Algorithms, 3rd Edition, Boston: Addison-Wesley, 2011.
%
%October 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

while(1)
    %Step F1
    m=rem(m,n);

    %Step F2
    if(m==0)
        val=n;
        return
    end

    %Step F3
    n=rem(n,m);

    %Step F4
    if(n==0)
        val=m;
        return
    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 dists = eucl(crds1,crds2)
% EUCL: Calculates the euclidean distances among a set of points, or between a
%       reference point and a set of points, or among all possible pairs of two
%       sets of points, in P dimensions.  Returns a single distance for two points.
%
%     Syntax: dists = eucl(crds1,crds2)
%
%        crds1 = [N1 x P] matrix of point coordinates.  If N=1, it is taken to
%                   be the reference point.
%        crds2 = [N2 x P] matrix of point coordinates.  If N=1, it is taken to
%                   be the reference point.
%        -----------------------------------------------------------------------
%        dists = [N1 x N1] symmetric matrix of pairwise distances (if only crds1
%                   is specified);
%                [N1 x 1]  col vector of euclidean distances (if crds1 & ref
%                   are specified);
%                [1 x N2]  row vector of euclidean distances (if ref & crds2
%                   are specified);
%                [N1 x N2] rectangular matrix of pairwise distances (if crds1
%                   & crds2 are specified);
%                [1 x 1]   scalar (if crds1 is a [2 x P] matrix or ref1 & ref2
%                   are specified);
%

% RE Strauss, 5/4/94
%   10/28/95 - output row (rather than column) vector for the (reference
%               point)-(set of points) case; still outputs column vector for the
%               (set of points)-(reference point) case.
%   10/30/95 - for double for-loops, put one matrix-col access in outer loop
%               to increase speed.
%   10/12/96 - vectorize inner loop to increase speed.
%    6/12/98 - allow for P=1.
%   11/11/03 - initialize dists to NaN for error return.

  if nargin == 0, help eucl; return; end
  dists = NaN;

  if (nargin < 2)                     % If only crds1 provided,
    [N,P] = size(crds1);
    if (N<2)
      error('  EUCL: need at least two points');
    end

    crds1 = crds1';                     % Transpose crds
    dists = zeros(N,N);                 % Calculate pairwise distances

    for i = 1:N-1
      c1 = crds1(:,i) * ones(1,N-i);
      if (P>1)
        d = sqrt(sum((c1-crds1(:,(i+1:N))).^2));
      else
        d = abs(c1-crds1(:,(i+1:N)));
      end
      dists(i,(i+1:N)) = d;
      dists((i+1:N),i) = d';
    end
    if (N==2)                            % Single distance for two points
      dists = dists(1,2);
    end

  else                                % If crds1 & crds2 provided,
    [N1,P1] = size(crds1);
    [N2,P2] = size(crds2);
    if (P1~=P2)
      error('  EUCL: sets of coordinates must be of same dimension');
    else
      P = P1;
    end

    crds1 = crds1';                     % Transpose crds
    crds2 = crds2';

    if (N1>1 && N2>1)                    % If two matrices provided,
      dists = zeros(N1,N2);               % Calc all pairwise distances between them
      for i = 1:N1
        c1 = crds1(:,i) * ones(1,N2);
        if (P>1)
          d = sqrt(sum((c1-crds2).^2));
        else
          d = abs(c1-crds2);
        end
        dists(i,:) = d;
      end
    end

    if (N1==1 && N2==1)                  % If two vectors provided,
      dists = sqrt(sum((crds1-crds2).^2));  % Calc scalar
    end

    if (N1>1 && N2==1)                   % If matrix && reference point provided,
      crds1 = crds1 - (ones(N1,1)*crds2')'; % Center points on reference point
      if (P>1)                              % Calc euclidean distances in P-space
         dists = sqrt(sum(crds1.^2))';
      else
         dists = abs(crds1)';
      end
    end;                                    % Return column vector

    if (N1==1 && N2>1)                   % If reference point && matrix provided,
      crds2 = crds2 - (ones(N2,1)*crds1')'; % Center points on reference point
      if (P>1)                              % Calc euclidean distances in P-space
        dists = sqrt(sum(crds2.^2));
      else
        dists = abs(crds2);
      end
    end;                                    % Return row vector
  end

  return;


function [P,R,S] = lagrangepoly(X,Y,XX)
%LAGRANGEPOLY  Lagrange interpolation polynomial fitting a set of points
%   [P,R,S] = LAGRANGEPOLY(X,Y)  where X and Y are row vectors
%   defining a set of N points uses Lagrange's method to find
%   the N-1th order polynomial in X that passes through these
%   points.  P returns the N coefficients defining the polynomial,
%   in the same order as used by POLY and POLYVAL (highest order first).
%   Then, polyval(P,X) = Y.  R returns the x-coordinates of the N-1
%   extrema of the resulting polynomial (roots of its derivative),
%   and S returns the y-values  at those extrema.
%
%   YY = LAGRANGEPOLY(X,Y,XX) returns the values of the polynomial
%   sampled at the points specified in XX -- the same as
%   YY = POLYVAL(LAGRANGEPOLY(X,Y)).
%
%   Example:
%   To find the 4th-degree polynomial that oscillates between
%   1 and 0 across 5 points around zero, then plot the interpolation
%   on a denser grid inbetween:
%     X = -2:2;  Y = [1 0 1 0 1];
%     P = lagrangepoly(X,Y);
%     xx = -2.5:.01:2.5;
%     plot(xx,polyval(P,xx),X,Y,'or');
%     grid;
%   Or simply:
%     plot(xx,lagrangepoly(X,Y,xx));
%
%   Note: if you are just looking for a smooth curve passing through
%   a set of points, you can get a better fit with SPLINE, which
%   fits piecewise polynomials rather than a single polynomial.
%
%   See also: POLY, POLYVAL, SPLINE

% 2006-11-20 Dan Ellis dpwe@ee.columbia.edu
% $Header: $

%  For more info on Lagrange interpolation, see Mathworld:
%  http://mathworld.wolfram.com/LagrangeInterpolatingPolynomial.html

% Make sure that X and Y are row vectors
if size(X,1) > 1;  X = X'; end
if size(Y,1) > 1;  Y = Y'; end
if size(X,1) > 1 || size(Y,1) > 1 || size(X,2) ~= size(Y,2)
  error('both inputs must be equal-length vectors')
end

N = length(X);

pvals = zeros(N,N);

% Calculate the polynomial weights for each order
for i = 1:N
  % the polynomial whose roots are all the values of X except this one
  pp = poly(X( (1:N) ~= i));
  % scale so its value is exactly 1 at this X point (and zero
  % at others, of course)
  pvals(i,:) = pp ./ polyval(pp, X(i));
end

% Each row gives the polynomial that is 1 at the corresponding X
% point and zero everywhere else, so weighting each row by the
% desired row and summing (in this case the polycoeffs) gives
% the final polynomial
P = Y*pvals;

if nargin==3
  % output is YY corresponding to input XX
  YY = polyval(P,XX);
  % assign to output
  P = YY;
end

if nargout > 1
  % Extra return arguments are values where dy/dx is zero
  % Solve for x s.t. dy/dx is zero i.e. roots of derivative polynomial
  % derivative of polynomial P scales each power by its power, downshifts
  R = roots( ((N-1):-1:1) .* P(1:(N-1)) );
  if nargout > 2
    % calculate the actual values at the points of zero derivative
    S = polyval(P,R);
  end
end


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

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

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

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

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

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

end


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

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

if nargin < 3,
  sigma = 1;
end

if nargin < 2;
  mu = 0;
end

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

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


function area = triangle_area ( t )

%*****************************************************************************80
%
%% TRIANGLE_AREA returns the area of a triangle.
%
%  Location:
%
%    http://people.sc.fsu.edu/~jburkardt/m_src/triangle_integrals/triangle_area.m
%
%  Discussion:
%
%    If the vertices are given in counter clockwise order, the area
%    will be positive.
%
%  Licensing:
%
%    This code is distributed under the GNU GPL license.
%
%  Modified:
%
%    18 April 2015
%
%  Author:
%
%    John Burkardt.
%
%  Parameters:
%
%    Input, real T(2,3), the vertices of the triangle.
%
%    Output, real AREA, the area of the triangle.
%
  area = 0.5 * ...
    ( ...
        ( t(1,2) - t(1,1) ) * ( t(2,3) - t(2,1) ) ...
      - ( t(1,3) - t(1,1) ) * ( t(2,2) - t(2,1) ) ...
    );

  return
end


function varargout = randomAngle3d(varargin)
%RANDOMANGLE3D Return a 3D angle uniformly distributed on unit sphere.
%
%   usage
%   [THETA PHI] = randomAngle3d
%   Generate an angle unformly distributed on the surface of the unit
%   sphere.
%
%   "Mathematical" convention is used: theta is the colatitude (angle with
%   vertical axis, 0 for north pole, +pi for south pole, pi/2 for points at
%   equator) with z=0.
%   phi is the same as matlab cart2sph: angle from Ox axis, counted
%   positively counter-clockwise.
%
%   [THETA PHI] = randomAngle3d(N)
%   generates N random angles (N is a scalar). The result is a N-by-2
%   array.
%
%   Example:
%     % Draw some points on the surface of a sphere
%     figure;
%     drawSphere; hold on;
%     drawPoint3d(pts, '.');
%     axis equal;
%
%   See also:
%   angles3d, sph2cart2, cart2sph2
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% created the 18/02/2005.
% Copyright INRA - Cepia Software platform

%   HISTORY
%   2007-01-04 change angle order, update doc
%   2011-06-27 fix bug in input parsing, add doc

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

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

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


% Euclidean projection on a hyperplane
% Section 8.1.1, Boyd & Vandenberghe "Convex Optimization"
% Joelle Skaf - 10/04/05
%
% The projection of x0 on a hyperplane C = {x | a'*x = b} is given by
%           minimize || x - x0 ||^2
%               s.t.    a'*x = b
% It is also given by P_C(x0) = x0 + (b - a'*x0)*a/||a||^2

% Input data
randn('seed',0);
n  = 10;
a  = randn(n,1);
b  = randn(1);
x0 = randn(n,1);

% Analytical solution
fprintf(1,'Computing the analytical solution ...');
pc_x0 = x0 + (b - a'*x0)*a/norm(a)^2;
fprintf(1,'Done! \n');

% Solution via QP
fprintf(1,'Computing the optimal solution by solving a QP ...');

cvx_begin quiet
    variable x(n)
    minimize ( norm(x-x0)^2 )
    a'*x == b; %#ok
cvx_end

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

% Verification
disp('--------------------------------------------------------------------------------');
disp('Verifying that p_C(x0) and x_star belong to the hyperplane C: ');
disp(['a^T*p_C(x0) - b = ' num2str(a'*pc_x0 - b)]);
disp(['a^T*x_star - b  = ' num2str(a'*x - b)]);
disp('Computing the distance between x0 and the hyperplane in each case');
disp(['||x0 - p_C(x0)|| = ' num2str(norm(x0 - pc_x0))]);
disp(['||x0 - x_star || = ' num2str(norm(x0 - x))]);
disp('Verifying that the analytical solution and the solution obtained via QP are equal: ');
disp([pc_x0 x])


%
% Author:  Stilian Stoev (C), sstoev@math.bu.edu
%
% This function computes the discrete convolution of the vectors
% a and b, efficiently, by using the FFT algorithm.
%
% input:
%  a <- a vector
%  b <- a vector with the same dimensions as a
%  force <- if force == 1, then the FFT's are "forced" to be
%           of dyadic complexity.
%
% output:
%  c <- the discrete convolution of a and b, that is,
%       (a(1)*b(1), a(1)*b(2)+a(2)*b(1), ...)
%
% usage:
%   c = fftconv(a,b,force);
%
% Written by sstoev@math.bu.edu
%
function c = fftconv(a,b,force);

na = length(a);
nb = length(b);

if force,
 n = 2^(fix(log2(na+nb))+1);
else
 n=na+nb;
end;
A = fft(a,n);
B = fft(b,n);

c = ifft(A.*B,n);
c = real(c(1:na+nb-1));


function [x,y]=henon(n,level,a,b,x0,y0)
%Syntax: [x,y]=henon(n,level,a,b,x0,y0)
%______________________________________
%
% Simulation of the Henon map.
%    x'=1-a*x^2+y
%    y'=b*x
%
% x and y are the simulated time series.
% n is the number of the simulated points.
% level is the noise standard deviation divided by the standard deviation of the
%   noise-free time series. We assume Gaussian noise with zero mean.
% a is the a parameter.
% b is the b parameter.
% x0 is the initial value for x.
% y0 is the initial value for y.
%
%
% Reference:
%
% Henon M (1976):A two-dimensional mapping with a strange attractor.
% Communications in Mathematical Physics 50: 69-77
%
%
% Alexandros Leontitsis
% Department of Education
% University of Ioannina
% 45110 - Dourouti
% Ioannina
% Greece
%
% University e-mail: me00743@cc.uoi.gr
% Lifetime e-mail: leoaleq@yahoo.com
% Homepage: http://www.geocities.com/CapeCanaveral/Lab/1421
%
% 5 Nov 2001

if nargin<1 | isempty(n)==1
    n=500;
else
    % n must be scalar
    if sum(size(n))>2
        error('n must be scalar.');
    end
    % n must be positive
    if n<0
        error('n must be positive.');
    end
    % n must be an integer
    if round(n)-n~=0
        error('n must be an integer.');
    end
end

if nargin<2 | isempty(level)==1
    level=0;
else
    % level must be scalar
    if sum(size(level))>2
        error('level must be scalar.');
    end
    % level must be positive
    if level<0
        error('level must be positive.');
    end
end

if nargin<3 | isempty(a)==1
    a=1.4;
else
    % a must be scalar
    if sum(size(a))>2
        error('a must be scalar.');
    end
end

if nargin<4 | isempty(b)==1
    b=0.3;
else
    % b must be scalar
    if sum(size(b))>2
        error('s must be a scalar.');
    end
end

if nargin<5 | isempty(x0)==1
    x0=0.1;
else
    % x0 must be scalar
    if sum(size(x0))>2
        error('x0 must be scalar.');
    end
end

if nargin<6 | isempty(y0)==1
    y0=0.1;
else
    % y0 must be scalar
    if sum(size(y0))>2
        error('y0 must be scalar.');
    end
end

% Initialize
x(1,1)=1-a*x0^2+b*y0;
y(1,1)=b*x0;

% Simulate
for i=2:n
    x(i,1)=1-a*x(i-1,1)^2+y(i-1,1);
    y(i,1)=b*x(i-1,1);
end

% Add normal white noise
x=x+randn(n,1)*level*std(x);
y=y+randn(n,1)*level*std(y);


function [theta] = normalEqn(X, y)
%NORMALEQN Computes the closed-form solution to linear regression
%   NORMALEQN(X,y) computes the closed-form solution to linear
%   regression using the normal equations.

theta = zeros(size(X, 2), 1);

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the code to compute the closed form solution
%               to linear regression and put the result in theta.
%

% ---------------------- Sample Solution ----------------------

theta = pinv(X' * X) * X' * y;

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

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

end


function [x,y,z] = hilbert3(n)
% Hilbert 3D curve.
%
% function [x,y,z] = hilbert3(n) gives the vector coordinates of points
% in n-th order Hilbert curve of area 1.
%
% Example: plot the 3-rd order curve
%
% [x,y,z] = hilbert3(3); plot3(x,y,z)
%
% Inputs:
%   n  number of subdivision iterations
% Outputs:
%   x  list of x coordinates
%   y  list of y coordinates
%   z  list of z coordinates
%
% Example:
%   n=3;
%   [x,y,z] = hilbert3(n);
%   P = [x;y;z]';
%   [V,F] = wire_mesh(P,[1:size(P,1)-1;2:size(P,1)]','Thickness',2^(1-n)/6);
%   [V,F] = loop(V,F,2);
%   tsurf(F,V);
%

%   Copyright (c) by Ivan Martynov
%   Inspired by function [x,y] = hilbert(n) made by Federico Forte
%   Date: September 17, 2009

if nargin ~= 1
    n = 2;
end

if n <= 0
    x = 0;
    y = 0;
    z = 0;
else
    [xo,yo,zo] = hilbert3(n-1);
    x = .5*[.5+zo .5+yo -.5+yo -.5-xo -.5-xo -.5-yo .5-yo .5+zo];
    y = .5*[.5+xo .5+zo .5+zo .5+yo -.5+yo -.5-zo -.5-zo -.5-xo];
    z = .5*[.5+yo -.5+xo -.5+xo .5-zo .5-zo -.5+xo -.5+xo .5-yo];
end

%{
Copyright (c) 2009, Ivan Martynov
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
%}


% Section 4.5.4: Frobenius norm diagonal scaling (GP)
% Boyd & Vandenberghe "Convex Optimization"
% Joelle Skaf - 01/29/06
% Updated to use GP mode by Almir Mutapcic 02/08/06
%
% Given a square matrix M, the goal is to find a vector (with dii > 0)
% such that ||DMD^{-1}||_F is minimized, where D = diag(d).
% The problem can be cast as an unconstrained geometric program:
%           minimize sqrt( sum_{i,j=1}^{n} Mij^2*di^2/dj^2 )
%

rs = randn( 'state' );
randn( 'state', 0 );

% matrix size (M is an n-by-n matrix)
n = 4;
M = randn(n,n);

% formulating the problem as a GP
cvx_begin gp
  variable d(n)
  minimize( sqrt( sum( sum( diag(d.^2)*(M.^2)*diag(d.^-2) ) ) ) )
  % Alternate formulation: norm( diag(d)*abs(M)*diag(1./d), 'fro' )
cvx_end

% displaying results
D = diag(d);
disp('The matrix D that minimizes ||DMD^{-1}||_F is: ');
disp(D);
disp('The minimium Frobenius norm achieved is: ');
disp(norm(D*M*inv(D),'fro'));
disp('while the Frobunius norm of the original matrix M is: ');
disp(norm(M,'fro'));


function theta = vectorAngle3d(v1, v2)
%VECTORANGLE3D Angle between two 3D vectors.
%
%   THETA = vectorAngle3d(V1, V2)
%   Computes the angle between the 2 3D vectors V1 and V2. The result THETA
%   is given in radians, between 0 and PI.
%
%
%   Example
%   % angle between 2 orthogonal vectors
%   vectorAngle3d([1 0 0], [0 1 0])
%   ans =
%       1.5708
%
%   % angle between 2 parallel vectors
%   v0 = [3 4 5];
%   vectorAngle3d(3*v0, 5*v0)
%   ans =
%       0
%
%   See also
%   vectors3d, vectorNorm3d, crossProduct3d
%

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

% 2011-03-10 improve computation precision

% compute angle using arc-tangent to get better precision for angles near
% zero, see the discussion in:
% http://www.mathworks.com/matlabcentral/newsreader/view_thread/151925#381952
theta = atan2(vectorNorm3d(crossProduct3d(v1, v2)), sum(bsxfun(@times, v1, v2),2));

% equivalent to:
% v1 = normalizeVector3d(v1);
% v2 = normalizeVector3d(v2);
% theta = acos(dot(v1, v2, 2));


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

%*****************************************************************************80
%
%% PHI_VALUES returns some values of the PHI function.
%
%  Definition:
%
%    PHI(N) is the number of integers between 1 and N which are
%    relatively prime to N.  I and J are relatively prime if they
%    have no common factors.  The function PHI(N) is known as
%    "Euler's totient function".
%
%    By convention, 1 and N are relatively prime.
%
%  First values:
%
%     N  PHI(N)
%
%     1    1
%     2    1
%     3    2
%     4    2
%     5    4
%     6    2
%     7    6
%     8    4
%     9    6
%    10    4
%    11   10
%    12    4
%    13   12
%    14    6
%    15    8
%    16    8
%    17   16
%    18    6
%    19   18
%    20    8
%
%  Formula:
%
%    PHI(U*V) = PHI(U) * PHI(V) if U and V are relatively prime.
%
%    PHI(P**K) = P**(K-1) * ( P - 1 ) if P is prime.
%
%    PHI(N) = N * Product ( P divides N ) ( 1 - 1 / P )
%
%    N = Sum ( D divides N ) PHI(D).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Milton Abramowitz and Irene Stegun,
%    Handbook of Mathematical Functions,
%    US Department of Commerce, 1964.
%
%  Parameters:
%
%    Input, integer N_DATA, indicates the index of the previous test data
%    returned, or is 0 if this is the first call.  For repeated calls,
%    set the input value of N_DATA to the output value of N_DATA_NEW
%    from the previous call.
%
%    Output, integer N_DATA_NEW, the index of the test data.
%
%    Output, integer N, the argument of the PHI function.
%
%    Output, integer C, the value of the PHI function.
%
  n_max = 20;
  c_vec = [ ...
      1,   1,   2,   2,   4,   2,   6,   4,   6,   4, ...
      8,   8,  16,  20,  16,  40, 148, 200, 200, 648 ];
  n_vec = [ ...
      1,   2,   3,   4,   5,   6,   7,   8,   9,  10, ...
     20,  30,  40,  50,  60, 100, 149, 500, 750, 999 ];

  n_data_new = n_data;

  if ( n_data_new < 0 )
    n_data_new = 0;
  end

  n_data_new = n_data_new + 1;

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

  return
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Author: Nicholas A. Battista
% Institution: The College of New Jersey (TCNJ)
% Created: March 20, 2018
% Date of Last Revision: March 22, 2018
%
% Written for use in MAT 331: Numerical Analysis
%
% PURPOSE:  -To compute the error ssociated with applying Trapezoid Rule to
%            two different integral cases:
%                (1) a periodic integrand on a periodic integration domain
%                (2) non-periodic integrand
%
%           -To demonstrate exponential convergence of Trap. Rule in Case (1)
%            above
%
% Inputs:
%
% Returns:
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function Trap_Rule_Error()

% Number of subintervals to test
NVec = [1e0:1e0:9e0 1e1:1e1:9e1 1e2:1e2:9e2 1e3:1e3:9e3 1e4:1e4:9e4 1e5:1e5:9e5 1e6:1e6:9e6];

%
% Storage Initialization
ErrVecPeriodic = zeros(length(NVec));
ErrVecNonPeriodic = ErrVecPeriodic;

%
% Compute Integral Approximation for Different #'s of Subintervals
%
for i=1:length(NVec)

   flag = 1; % For Periodic
   ErrVecPeriodic(i) = Trap_Rule( NVec(i), 0, 1, flag);

   flag = 0; % For Non-Periodic
   ErrVecNonPeriodic(i) = Trap_Rule( NVec(i), 0, 1, flag);

end

%
% Print Convergence Rate Information to Screen
slopeNonPeriodic = give_Me_Slope( ErrVecNonPeriodic,40,50 );
fprintf('\nConvergence Rate for Periodic Functions Appears to be Exponential, e.g.,\n');
fprintf('     we see a linear relationship between log(error) and # of subintervals, N\n');
fprintf('\nConvergence Rate for Non-Periodic Functions Appears to be: %d\n\n',slopeNonPeriodic);

%
% PLOT THE ABSOLUTEL ERROR -> GIVE CONVERGENCE PLOTS!
%
fs = 18;
ms = 30;
figure(1) % PERIODIC CASE
semilogy(NVec(1:45),ErrVecPeriodic(1:45),'b.','MarkerSize',ms); hold on;
%loglog(NVec(1:45),ErrVecPeriodic(1:45),'b.','MarkerSize',ms); hold on;
title('Periodic Case');
ylabel('Absolute Error');
xlabel('Number of Sub-Intervals');
set(gca,'FontSize',fs);

figure(2) % NON-PERIODIC CASE
loglog(NVec,ErrVecNonPeriodic,'b.','MarkerSize',ms); hold on;
title('Non-Periodic Case');
ylabel('Absolute Error');
xlabel('Number of Sub-Intervals');
set(gca,'FontSize',fs);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: computes the absolute error using the trapezoid rule for a
%           particular number of subintervals, N.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function err = Trap_Rule(N,a,b,flagCase)

% Uniformly spaced integration nodes
x = a:(b-a)/N:b;

% Compute trapezoid rule for periodic function
int = 0;
for i=1:N
   int = int + (b-a)/(2*N)*( f(x(i),flagCase) + f(x(i+1),flagCase) );
end

%
% Return Error for Particular Case
%
if flagCase == 1

    % PERIODIC CASE
    intExactPeriodic = 0.132214293037990;
    err = abs( int - intExactPeriodic );

else

    % NON-PERIODIC CASE
    intExactNonPeriodic = 0.455122322888408;
    err = abs( int - intExactNonPeriodic );

end

% PLOT!
%x=a:0.001:b;
%for i=1:length(x)
%    plot( x(i) , f(x(i)), '*'); hold on;
%end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: returns integrand function value
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function val = f(x,flagCase)

%
% Return Function Value for Particular Case
%
if flagCase == 1

    % PERIODIC: f(x) = (cos(2*pi*x))^2 / ( 1 + e^(sin(2*pi*x)) )^2;
    val = ( cos(2*pi*x) )^2 / ( 1 + exp( sin(2*pi*x) ) )^2;

else

    % NON-PERIODIC: f(x) = (x^2+3)(cos(2*pi*x))^2 / ( 1 + e^(sin(2*pi*x)) )^2;
    val = (x^2+3)*(cos(2*pi*x))^2 / ( 1 + exp(sin(2*pi*x)) )^2;

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% FUNCTION: give me slope of convergence plot
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function m = give_Me_Slope( errVec, val1, val2 )

m = ( log( errVec(val1) ) - log( errVec(val2) ) ) / (log(val1) - log(val2));


function line = medianLine(varargin)
%MEDIANLINE Create a median line between two points
%
%   L = medianLine(P1, P2);
%   Create the median line of points P1 and P2, that is the line containing
%   all points located at equal distance of P1 and P2.
%
%   L = medianLine(PTS);
%   Creates the median line of 2 points, given as a 2*2 array. Array has
%   the form:
%   [ [ x1 y1 ] ; [ x2 y2 ] ]
%
%   L = medianLine(EDGE);
%   Creates the median of the edge. Edge is a 1*4 array, containing [X1 Y1]
%   coordinates of first point, and [X2 Y2], the coordinates of the second
%   point.
%
%   Example
%   % Draw the median line of two points
%     P1 = [10 20];
%     P2 = [30 50];
%     med = medianLine(P1, P2);
%     figure; axis square; axis([0 100 0 100]);
%     drawEdge([P1 P2], 'linewidth', 2, 'color', 'k');
%     drawLine(med)
%
%   % Draw the median line of an edge
%     P1 = [50 60];
%     P2 = [80 30];
%     edge = createEdge(P1, P2);
%     figure; axis square; axis([0 100 0 100]);
%     drawEdge(edge, 'linewidth', 2)
%     med = medianLine(edge);
%     drawLine(med)
%
%
%   See also:
%   lines2d, createLine, orthogonalLine
%
%   ---------
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 31/10/2003.
%

% history
% 2010-08-06 vectorize and change behaviour for N-by-4 inputs

nargs = length(varargin);

if nargs == 1
    tab = varargin{1};
    if size(tab, 2)==2
        % input is an array of two points
        x0 = tab(1,1);
        y0 = tab(1,2);
        dx = tab(2,1)-x0;
        dy = tab(2,2)-y0;
    else
        % input is an edge
        x0 = tab(:, 1);
        y0 = tab(:, 2);
        dx = tab(:, 3) - tab(:, 1);
        dy = tab(:, 4) - tab(:, 2);
    end

elseif nargs==2
    % input is given as two points, or two point arrays
    p1 = varargin{1};
    p2 = varargin{2};
    x0 = p1(:, 1);
    y0 = p1(:, 2);
    dx = bsxfun(@minus, p2(:, 1), x0);
    dy = bsxfun(@minus, p2(:, 2), y0);

else
    error('Too many input arguments');
end

% compute median using middle point of the edge, and the direction vector
% rotated by 90 degrees counter-clockwise
line = [bsxfun(@plus, x0, dx/2), bsxfun(@plus, y0, dy/2), -dy, dx];


function M = softMin( D, sigma )
% Calculates the softMin of a vector.
%
% Let D be a vector.  Then the softMin of D is defined as:
%   s = exp(-D/sigma^2) / sum( exp(-D/sigma^2) )
% The softMin is a way of taking a dissimilarity (distance) vector D and
% converting it to a similarity vector s, such that sum(s)==1. If D is an
% NxK array, is is treated as N K-dimensional vectors, and the return is
% likewise an NxK array.  This is useful if D is a distance matrix,
% generated by the likes of pdist2.
%
% Note that as sigma->0, softMin's behavior tends toward that of the
% standard min function.  That is the softMin of a vector D has all zeros
% with a single 1 in the location of the smallest value of D. For example,
% "softMin([.2 .4 .1 .3],eps)" returns "[0 0 1 0]".  As sigma->inf, then
% softMin(D,sigma) tends toward "ones(1,n)/n", where n==length(D).
%
% If D contains the squared euclidean distance between a point y and k
% points xi, then there is a probabilistic interpretation for softMin.  If
% we think of the k points representing equal variant gaussians each with
% mean xi and std sigma, then the softMin returns the relative probability
% of y being generated by each gaussian.
%
% USAGE
%  M = softMin( D, sigma )
%
% INPUTS
%  D       - NxK dissimilarity matrix
%  sigma   - controls 'softness' of softMin
%
% OUTPUTS
%  M       - the softMin (indexes into D)
%
% EXAMPLE - 1
%  C = [0 0; 1 0; 0 1; 1 1]; x=[.7,.3; .1 .2];
%  D = pdist2( x, C ), M = softMin( D, .25 )
%
% EXAMPLE - 2
%  fplot( 'softMin( [0.5 0.2 .4], x )', [0 5] );
%  xlabel('sigma'); ylabel('assignments')
%
% See also PDIST2, SOFTMAX
%
% Piotr's Image&Video Toolbox      Version 2.0
% Copyright 2012 Piotr Dollar.  [pdollar-at-caltech.edu]
% Please email me if you find bugs, or have suggestions or questions!
% Licensed under the Simplified BSD License [see external/bsd.txt]

if( sigma==0 ) % special case, make fast
  [~, inds] = min(D,[],2); [n, k] = size(D);
  M = subsToArray( [(1:n)' inds], ones(n,1), [n k] );

else % general case
  M = exp( -D / sigma^2 );
  M(isinf(M))=1e50;
  sumM = sum( M, 2 );
  sumMzero = (sumM==0);
  if( any(sumMzero) )
    [~, inds] = min(D,[],2); [n, k] = size(D);
    Mhard = subsToArray( [(1:n)' inds], ones(n,1), [n k] );
    M( sumMzero, : ) = Mhard( sumMzero, : );
    sumM = sum( M, 2 );
  end
  M = M ./ sumM( :, ones(1,size(M,2)) );
end


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

% analytical computation of the convolution between
% x(t)=1,0<t<2 and h(t)=1-t,0<t<1

 tx1=-2:.1:0;
 tx2=0:.1:2;
 tx3=2:.1:4;
 tx=[tx1 tx2 tx3];
 x1=zeros(size(tx1));
 x2=ones(size(tx2));
 x3=zeros(size(tx3));
 x=[x1 x2 x3];

 th1=-2:.1:0;
 th2=0:.1:1;
 th3=1:.1:4;
 th=[th1 th2 th3];
 h1=zeros(size(th1));
 h2=1-th2;
 h3=zeros(size(th3));
 h=[h1 h2 h3];

 plot(tx,x,th,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(\tau)')
 grid

 %reflection
 figure
 plot(tx,x,-th,h,':*')
 legend('x(\tau)','h(-\tau)')
 ylim([-.1 1.1])

 %shifting
 figure
 t=-2;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

 %zero-overlap
 figure
 t=-2;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

 %partial-overlap
 figure
 t= 0.5;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

 T=1;
 r=0:.1:t;
 a=1/T*r+1-t/T;
 hold on; area(r,a);
 hold off;

%complete-overlap
 figure
 t=1.6;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

 r=t-T:.1:t;
 a=1/T*r+1-t/T;
 hold on; area(r,a);
 hold off;

%partial-overlap
 figure
 t=2.4;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

 r=t-T:.1:2;
 a=1/T*r+1-t/T;
 hold on; area(r,a);
 hold off;

 %zero-overlap
 figure
 t=3.6;
 plot(tx,x,-th+t,h,':*')
 ylim([-.1 1.1])
 legend('x(\tau)','h(t-\tau)')

%convolution calculation
 syms t r
 f=1-t+r;
 y=int(f,r,0,t)

 y=int(f,r,t-1,t)
 simplify(y)

 y=int(f,r,t-1,2)

 t1=0:.1:1;
 t2=1:.1:2;
 t3=2:.1:3;
 y1=t1-(t1.^2)/2;
 y2=0.5*ones(size(t2));
 y3=0.5*((3-t3).^2);

 figure
 plot(t1,y1,t2,y2,'.',t3,y3,':')
 ylim([0 0.6])
 title('Output signal y(t)');


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

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

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

rowsz = size(X, 1);
colsz = size(X, 2);
mu = mean(X);
sigma = std(X);
mu_matrix = (ones(size(X))) * ((ones(colsz, 1) * mu) .* eye(colsz));
sigma_matrix = ((ones(colsz, 1) * (1./sigma)) .* eye(colsz));
X_norm = (X-mu_matrix) * sigma_matrix;

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

end