% Entropy: Returns entropy (in bits) of each column of 'X'
% by Will Dwinnell
%
% H = Entropy(X)
%
% H = row vector of calculated entropies (in bits)
% X = data to be analyzed
%
% Example: Measure sample entropy of observations of variables with
%   1, 2, 3 and 4 bits of entropy.
%
% Note: Estimated entropy values are slightly less than true, due to
% finite sample size.
%
% X = ceil(repmat([2 4 8 16],[1e3,1]) .* rand(1e3,4));
% Entropy(X)
%
% Last modified: Nov-12-2006

function H = Entropy(X)

% Establish size of data
[n m] = size(X);

% Housekeeping
H = zeros(1,m);

for Column = 1:m,
    % Assemble observed alphabet
    Alphabet = unique(X(:,Column));

    % Housekeeping
    Frequency = zeros(size(Alphabet));

    % Calculate sample frequencies
    for symbol = 1:length(Alphabet)
        Frequency(symbol) = sum(X(:,Column) == Alphabet(symbol));
    end

    % Calculate sample class probabilities
    P = Frequency / sum(Frequency);

    % Calculate entropy in bits
    % Note: floating point underflow is never an issue since we are
    %   dealing only with the observed alphabet
    H(Column) = -sum(P .* log2(P));
end

% God bless Claude Shannon.

% EOF


function JTotal=polAngGradient(xG,systemType,lRx)
%%POLANGGRADIENT Determine the gradient of the angle of a 2D polar
%           measurement with respect to position (gradient components for
%           velocity etc. are zero and are not provided).Atmospheric and
%           other propagation effects are not taken into account. The
%           measurement can be monostatic or bistatic, but the location of
%           the transmitter does not matter.
%
%INPUTS: xG A 2XN set of Cartesian locations in the format [x;y] where the
%          gradient is desired.
% systemType An optional parameter specifying the axis from which the
%          azimuth angle is measured. It is assumed that the azimuth
%          angle is given in radians. Possible values are
%          0 (The default if omitted) The azimuth angle is
%             counterclockwise from the x axis.
%          1 The azimuth angle is measured clockwise from the y axis.
%      lRx The 2X1 [x;y] location vector of the receiver in Cartesian
%          coordinates. If this parameter is omitted or an empty matrix is
%          passed, then the receiver is assumed to be at the origin.
%
%OUTPUTS: JTotal A 1X2XN set of gradient matrices of the polar angle taken
%           with respect to the components [x,y] in 2D in that order for
%           each of the N points in xG.
%
%The conversion utilizing bistatic polar measurements in 2D is similar to
%that using bistatic r-u-v measurements in 3D, which is discussed in [1].
%Basic differentiation was analytically performed to obtain the expressions
%used in this file.
%
%Note that normally we would convert the point to the local coordinate
%system as
%xLocal=M*(xG(1:2,curPoint)-lRx(1:2))
%then compute the gradient J, and then undo the effects of the rotation
%matrix M in the end to the global coordinates as JTotal=J*M.
%However, that is not necessary with polar angles, due to cancellations.
%Say that M=[m11,m12;m21,m22] is a rotation matrix. Then, the partial
%derivative with respect to x is explicitly:
%((m12*m21-m11*m22)*y)/((m11^2+m21^2)*x^2+2*(m11*m12+m21*m22)*x*y+(m12^2+m22^2)*y^2)
%However, one will see that because M is a rotation matrix and M*M'=eye(2)
%then m12*m21-m11*m22=-1, m11^2+m21^2=m12^2+m22^2=1, and m11*m12+m21*m22=0,
%which is the same as if no rotation matrix were present. Basically, all M
%does is add a constant to the direction angle; it does not change any of
%the derivatives. Thus, M does not matter for the Jacobian.
%
%EXAMPLE:
%Here, we verify that a numerically differentiated Jacobian is consistent
%with the analytic one produced by this function.
% x=[100;-1000];
% lRx=[500;20];
% epsVal=1e-5;
% systemType=0;
% M=randRotMat(2);
% J=polAngGradient(x,systemType,lRx);
%
% theta=getPolAngle(x,systemType,lRx,M);
% thetadX=getPolAngle(x+[epsVal;0],systemType,lRx,M);
% thetadY=getPolAngle(x+[0;epsVal],systemType,lRx,M);
%
% JNumDiff=[(thetadX-theta)/epsVal;(thetadY-theta)/epsVal];
% max(abs((J(:)-JNumDiff(:))./J(:)))
%The relative error will be on the order of 1e-8, indicating good agreement
%between the numerical Jacobian vector and the actual Jacobian vector.
%
%REFERENCES:
%[1] David F. Crouse , "Basic tracking using nonlinear 3D monostatic and
%    bistatic measurements," IEEE Aerospace and Electronic Systems
%    Magazine, vol. 29, no. 8, Part II, pp. 4-53, Aug. 2014.
%
%February 2017 David F.Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

N=size(xG,2);

%M does not matter, so we do not need to check whether it is given.

if(nargin<3||isempty(lRx))
    lRx=zeros(2,1);
end

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

JTotal=zeros(1,2,N);
for curPoint=1:N
    %Convert the point into the local coordinate system of the receiver.
    xLocal=xG(1:2,curPoint)-lRx(1:2);

    xL=xLocal(1);
    yL=xLocal(2);

    J=zeros(1,2);
    switch(systemType)
        case 0
            %Derivative with respect to x.
            J(1,1)=-yL/(xL^2+yL^2);

            %Derivative with respect to y.
            J(1,2)=xL/(xL^2+yL^2);
        case 1
            %Derivative with respect to x.
            J(1,1)=yL/(xL^2+yL^2);

            %Derivative with respect to y.
            J(1,2)=-xL/(xL^2+yL^2);
        otherwise
            error('Invalid system type specified.')
    end

    %Undo the rotation to move the gradient into the global coordinate
    %system.
    JTotal(:,:,curPoint)=J;
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 PaV = calc_Pa(H0,betaV,dkV)
%Actuarial probability of complication using Cox model

PaV = 1 - exp(-H0 .* exp(betaV.*dkV));

%Test-1:
% tol = 10^-5;
% expectedp10 = 0.1;
% H0=0.01;
% B = 0.05;
% d10 = 47.096;
% p10 = calc_Pa(H0,B,d10);
% assertAlmostEqual(p10,expectedp10,tol);

end


function Rets = Simulate_Jump_Diffusion_Log_Returns_func( N_sim, dt, r, q, sigma, jumpModel, jumpParams )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% About: Simulates Log Returns of Jump Diffusion Models with jumps (including simple Black-Scholes, no jumps)
% Returns: paths of dimension (N_sim, M+1), since they include S_0
%          ... Simulates N_sim paths, each row is a full path starting from S_0, ending with S_M (M+1 points in path)
% Author: Justin Lars Kirkby
%
% -----------------
% Params
% -----------------
% N_sim = # paths
% M = #time steps on [0,T], time step is dt=T/M, so each path has M+1 points
% T = time to maturity, ie path is on [0,T]
% S_0 = initial underlying value (e.g. S_0=100)
% r = interst rate (e.g. r = 0.05)
% q = dividend yield (e.g. q = 0.05)
% sigma = diffusion parameter (e.g. sigma = 0.2)
%
%===================================
% jumpModel: 0 = NoJumps, 1 = NormalJumps, 2 = DEJumps, 3 = MixedNormalJumps
%===================================
% jumpParams = paramters container containing all necessary params for models,
%            : if jumpModel = 0, no jump params are needed
%            : if jumpModel > 0, jumpParams must contain lambda, kappa, and any other model specific params (see below)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%==============================
% Initialize Jump Model Params and JumpFunc (function handle)
%==============================
%%% NOTE:  Jump Model is of the form in LOG space
%%% X(m+1) = X(m) + drift + Brownian Component + sum(Jumps on [m,m+1])
%%% By Jump we mean log(Y), e.g. in Merton Model, Jump ~ Normal (since we are in log space )

if jumpModel > 0 %ie if there are jumps in the model
    lambda = jumpParams.lambda;
    kappa  = jumpParams.kappa;

    Zeta = r - q - lambda*kappa;  %NOTE: we are redefining r to include compensation for jump component
    lamdt = lambda*dt;

    if jumpModel == 1 %Normal Jumps, e.g. Merton
        muJ  = jumpParams.muJ;
        sigJ = jumpParams.sigJ;
        JumpFunc = @(n) sum(muJ +sigJ*randn(n,1)); %Generates n independent jumps and sums them

    elseif jumpModel == 2 %Double Exponenial Jumps
        p_up = jumpParams.p_up;
        eta1 = jumpParams.eta1;
        eta2 = jumpParams.eta2;
        JumpFunc = @(n) sum(DoubleExpoRnd(n,p_up, eta1,eta2));

    elseif jumpModel == 3 %Mixed normal Jumps
        p_up = jumpParams.p_up;
        a1 = jumpParams.a1;  b1 = jumpParams.b1;
        a2 = jumpParams.a2;  b2 = jumpParams.b2;
        JumpFunc = @(n) sum(MixedNormalRnd(n, p_up, a1,b1,a2,b2));
    end
else
    Zeta = r - q;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Sigsqdt = sigma*sqrt(dt);
drift = (Zeta - .5*sigma^2)*dt;

if jumpModel == 0  % Just a drifted Brownian motion
    Rets = drift + Sigsqdt*randn(N_sim,1);
else
    Poi = PoissonRnd(N_sim, lamdt);  %Generate Poisson Column Vector of size N_Sim
    for n = 1:N_sim
        if Poi(n)>0
            Poi(n) = JumpFunc(Poi(n));  %JumpFunc(Poi(n)) sums up Poi(n) many jumps from the jump distribution
        end
    end

    Rets = drift + Poi + Sigsqdt*randn(N_sim,1);
end

end


function quad = gauss_legendre_integrate_fast ( f, n )

%*****************************************************************************80
%
%% GAUSS_LEGENDRE_INTEGRATE_FAST applies a Gauss-Legendre quadrature rule.
%
%  Discussion:
%
%    The integration is carried out on the standard interval [-1,1].
%
%    The computation should be very efficient in MATLAB.
%
%  Modified:
%
%    03 March 2007
%
%  Author:
%
%    Lloyd Trefethen
%
%  Reference:
%
%    Lloyd Trefethen,
%    Is Gauss Quadrature Better than Clenshaw-Curtis?
%    SIAM Review,
%    Volume 50, Number 1, 2008, pages 67-87.
%
%  Parameters:
%
%    Input, function F ( x ), the function to be integrated.
%
%    Input, integer N, the order of the quadrature rule.
%
%    Output, real QUAD, the estimate for the integral of F(X).
%
  beta = 0.5 ./ sqrt ( 1 - ( 2 * ( 1:n ) ) .^ (-2) );

  tridiag = diag ( beta, 1 ) + diag ( beta, -1 );

  [ eigval, eigvec ] = eig ( tridiag );

  x = diag ( eigvec );
  [ x, i ] = sort ( x );
  w = 2 * eigval(1,i) .^ 2;

  quad = w * feval ( f, x );

  return
end


function value = c8mat_norm_fro ( m, n, a )

%*****************************************************************************80
%
%% C8MAT_NORM_FRO returns the Frobenius norm of a C8MAT.
%
%  Discussion:
%
%    The Frobenius norm is defined as
%
%      C8MAT_NORM_FRO = sqrt (
%        sum ( 1 <= I <= M ) sum ( 1 <= j <= N ) A(I,J) * A(I,J) )
%
%    The matrix Frobenius norm is not derived from a vector norm, but
%    is compatible with the vector L2 norm, so that:
%
%      c8vec_norm_l2 ( A * x ) <= c8mat_norm_fro ( A ) * c8vec_norm_l2 ( x ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows in A.
%
%    Input, integer N, the number of columns in A.
%
%    Input, complex A(M,N), the matrix whose norm is desired.
%
%    Output, real VALUE, the norm of A.
%
  value = ...
    sqrt ...
    ( ...
      sum ...
      ( ...
        sum ...
        ( ...
          ( ...
            abs ...
            ( ...
              a(1:m,1:n) ...
            ) ...
          ) .^ 2 ...
        ) ...
      ) ...
   );

  return
end


function jac = p12_jac ( neqn, t, y )

%*****************************************************************************80
%
%% P12_JAC evaluates the jacobian for problem p12.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 February 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NEQN, the number of equations.
%
%    Input, real T, Y(NEQN), the arguments of the jacobian.
%
%    Output, real JAC(NEQN,NEQN), the jacobian matrix.
%
  jac = zeros ( neqn, neqn );

  for i = 1 : neqn - 1
    jac(i,i) = - i;
  end

  for i = 2 : neqn
    jac(i,i-1) = i - 1;
  end

  return
end


function geometry_test068 ( )

%*****************************************************************************80
%
%% GEOMETRY_TEST068 tests the SPHERE_DISTANCE routines.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
  ntest = 6;

  name = [ ...
       'Atlanta, Georgia  '; ...
       'North Pole        '; ...
       'South Pole        '; ...
       'Timbuktu          '; ...
       'San Antonio, Texas'; ...
       'Savannah, Georgia ' ];
  lat_d =  [ 33, 90, -90, 16, 29, 32 ];
  lat_m =  [ 11,  0,   0, 49, 25,  5 ];
  long_d = [ 82,  0,   0,  3, 98, 81 ];
  long_m = [ 34,  0,   0,  0, 30,  6 ];
  radius = 3957.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'GEOMETRY_TEST068\n' );
  fprintf ( 1, '  POINTS_DIST_SPHERE_3D measures the distance between\n' );
  fprintf ( 1, '  two points on a sphere.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  All tests uses RADIUS = %f\n', radius );
  fprintf ( 1, '  which is the radius of the earth in miles.\n' );
  fprintf ( 1, '\n' );

  for i = 1 : ntest-1

    lat1 = dms_to_radians ( lat_d(i), lat_m(i), 0.0 );
    long1 = dms_to_radians ( long_d(i), long_m(i), 0.0 );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Distance from %s\n', name(i,:) );

    for j = i+1 : ntest

      lat2 = dms_to_radians ( lat_d(j), lat_m(j), 0.0 );
      long2 = dms_to_radians ( long_d(j), long_m(j), 0.0 );

      dist1 = sphere_distance1 ( lat1, long1, lat2, long2, radius );
      dist2 = sphere_distance2 ( lat1, long1, lat2, long2, radius );
      dist3 = sphere_distance3 ( lat1, long1, lat2, long2, radius );

      fprintf ( 1, '             to %s is %16.8f  %16.8f  %16.8f\n', ...
        name(j,:), dist1, dist2, dist3 );

    end

  end

  return
end


function [ u, it_num ] = monogrid_poisson_1d ( n, a, b, ua, ub, force, exact )

%*****************************************************************************80
%
%% MONOGRID_POISSON_1D solves a 1D PDE, using the Gauss-Seidel method.
%
%  Discussion:
%
%    This routine solves a 1D boundary value problem of the form
%
%      - U''(X) = F(X) for A < X < B,
%
%    with boundary conditions U(A) = UA, U(B) = UB.
%
%    The Gauss-Seidel method is used.
%
%    This routine is provided primarily for comparison with the
%    multigrid solver.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 July 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    William Hager,
%    Applied Numerical Linear Algebra,
%    Prentice-Hall, 1988,
%    ISBN13: 978-0130412942,
%    LC: QA184.H33.
%
%  Parameters:
%
%    Input, integer N, the number of intervals.
%
%    Input, real A, B, the left and right endpoints of the region.
%
%    Input, real UA, UB, the left and right boundary values.
%
%    Input, function value = FORCE ( x ), the name of the function
%    which evaluates the right hand side.
%
%    Input, function value = EXACT ( x ), the name of the function
%    which evaluates the exact solution.
%
%    Output, integer IT_NUM, the number of iterations.
%
%    Output, real U(N+1,1), the computed solution.
%

%
%  Initialization.
%
  tol = 0.0001;
%
%  Set the nodes.
%
  x = ( linspace ( a, b, n + 1 ) )';
%
%  Set the right hand side.
%
  r = zeros ( n + 1, 1 );

  r(1) = ua;
  r(2:n) = force ( x(2:n) ) / n / n;
  r(n+1) = ub;

  u = zeros ( n + 1, 1 );

  it_num = 0;
%
%  Gauss-Seidel iteration.
%
  while ( 1 )

    it_num = it_num + 1;

    [ u, d1 ] = gauss_seidel ( n + 1, r, u );

    if ( d1 <= tol )
      break
    end

  end

  return
end


function point = intersectLinePlane(line, plane, varargin)
%INTERSECTLINEPLANE Intersection point between a 3D line and a plane.
%
%   PT = intersectLinePlane(LINE, PLANE)
%   Returns the intersection point of the given line and the given plane.
%   LINE:  [x0 y0 z0 dx dy dz]
%   PLANE: [x0 y0 z0 dx1 dy1 dz1 dx2 dy2 dz2]
%   PT:    [xi yi zi]
%   If LINE and PLANE are parallel, return [NaN NaN NaN].
%   If LINE (or PLANE) is a matrix with 6 (or 9) columns and N rows, result
%   is an array of points with N rows and 3 columns.
%
%   PT = intersectLinePlane(LINE, PLANE, TOL)
%   Specifies the tolerance factor to test if a line is parallel to a
%   plane. Default is 1e-14.
%
%   Example
%     % define horizontal plane through origin
%     plane = [0 0 0   1 0 0   0 1 0];
%     % intersection with a vertical line
%     line = [2 3 4  0 0 1];
%     intersectLinePlane(line, plane)
%     ans =
%        2   3   0
%     % intersection with a line "parallel" to plane
%     line = [2 3 4  1 2 0];
%     intersectLinePlane(line, plane)
%     ans =
%       NaN  NaN  NaN
%
%   See also
%   lines3d, planes3d, points3d, clipLine3d
%

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

% extract tolerance if needed
tol = 1e-14;
if nargin > 2
    tol = varargin{1};
end

% unify sizes of data
nLines  = size(line, 1);
nPlanes = size(plane, 1);

% N planes and M lines not allowed
if nLines ~= nPlanes && min(nLines, nPlanes) > 1
    error('MatGeom:geom3d:intersectLinePlane', ...
        'Input must have same number of rows, or one must be 1');
end

% plane normal
n = crossProduct3d(plane(:,4:6), plane(:,7:9));

% difference between origins of plane and line
dp = bsxfun(@minus, plane(:, 1:3), line(:, 1:3));

% dot product of line direction with plane normal
denom = sum(bsxfun(@times, n, line(:,4:6)), 2);

% relative position of intersection point on line (can be inf in case of a
% line parallel to the plane)
t = sum(bsxfun(@times, n, dp),2) ./ denom;

% compute coord of intersection point
point = bsxfun(@plus, line(:,1:3),  bsxfun(@times, [t t t], line(:,4:6)));

% set indices of line and plane which are parallel to NaN
par = abs(denom) < tol;
point(par,:) = NaN;


function W = compute_mesh_weight(vertex,face,type,options)

% compute_mesh_weight - compute a weight matrix
%
%   W = compute_mesh_weight(vertex,face,type,options);
%
%   W is sparse weight matrix and W(i,j)=0 is vertex i and vertex j are not
%   connected in the mesh.
%
%   type is either
%       'combinatorial': W(i,j)=1 is vertex i is conntected to vertex j.
%       'distance': W(i,j) = 1/d_ij^2 where d_ij is distance between vertex
%           i and j.
%       'conformal': W(i,j) = cot(alpha_ij)+cot(beta_ij) where alpha_ij and
%           beta_ij are the adjacent angle to edge (i,j)
%
%   If options.normalize=1, the the rows of W are normalize to sum to 1.
%
%   Copyright (c) 2007 Gabriel Peyre

options.null = 0;
[vertex,face] = check_face_vertex(vertex,face);

nface = size(face,1);
n = max(max(face));

verb = getoptions(options, 'verb', n>5000);

if nargin<3
    type = 'conformal';
end

switch lower(type)
    case 'combinatorial'
        W = triangulation2adjacency(face);
    case 'distance'
        W = my_euclidean_distance(triangulation2adjacency(face),vertex);
        W(W>0) = 1./W(W>0);
        W = (W+W')/2;
    case 'conformal'
        % conformal laplacian
        W = sparse(n,n);
        ring = compute_vertex_face_ring(face);
        for i = 1:n
            if verb
                progressbar(i,n);
            end
            for b = ring{i}
                % b is a face adjacent to a
                bf = face(:,b);
                % compute complementary vertices
                if bf(1)==i
                    v = bf(2:3);
                elseif bf(2)==i
                    v = bf([1 3]);
                elseif bf(3)==i
                    v = bf(1:2);
                else
                    error('Problem in face ring.');
                end
                j = v(1); k = v(2);
                vi = vertex(:,i);
                vj = vertex(:,j);
                vk = vertex(:,k);
                % angles
                alpha = myangle(vk-vi,vk-vj);
                beta = myangle(vj-vi,vj-vk);
                % add weight
                W(i,j) = W(i,j) + cot( alpha );
                W(i,k) = W(i,k) + cot( beta );
            end
        end
    otherwise
        error('Unknown type.')
end

if isfield(options, 'normalize') && options.normalize==1
    W = diag(sum(W,2).^(-1)) * W;
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function beta = myangle(u,v);

du = sqrt( sum(u.^2) );
dv = sqrt( sum(v.^2) );
du = max(du,eps); dv = max(dv,eps);
beta = acos( sum(u.*v) / (du*dv) );

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function W = my_euclidean_distance(A,vertex)

if size(vertex,1)<size(vertex,2)
    vertex = vertex';
end

[i,j,s] = find(sparse(A));
d = sum( (vertex(i,:) - vertex(j,:)).^2, 2);
W = sparse(i,j,d);


function [pval m] = circ_otest(alpha, sz, w)
%
% [pval, m] = circ_otest(alpha,sz,w)
%   Computes Omnibus or Hodges-Ajne test for non-uniformity of circular data.
%   H0: the population is uniformly distributed around the circle
%   HA: the population is not distributed uniformly around the circle
%
%   Alternative to the Rayleigh and Rao's test. Works well for unimodal,
%   bimodal or multimodal data. If requirements of the Rayleigh test are
%   met, the latter is more powerful.
%
%   Input:
%     alpha	sample of angles in radians
%     [sz   step size for evaluating distribution, default 1 degree
%     [w		number of incidences in case of binned angle data]

%   Output:
%     pval  p-value
%     m     minimum number of samples falling in one half of the circle
%
% PHB 3/16/2009
%
% References:
%   Biostatistical Analysis, J. H. Zar
%   A bivariate sign test, J. L. Hodges et al., 1955
%   A simple test for uniformity of a circular distribution, B. Ajne, 1968
%
% Circular Statistics Toolbox for Matlab

% By Philipp Berens, 2009
% berens@tuebingen.mpg.de - www.kyb.mpg.de/~berens/circStat.html

if size(alpha,2) > size(alpha,1)
	alpha = alpha';
end

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

if nargin < 3
  w = ones(size(alpha));
else
  if length(alpha)~=length(w)
    error('Input length does not match.')
  end
  w =w(:);
end

alpha = mod(alpha,2*pi);
n = sum(w);
dg = 0:sz:pi;

m1 = zeros(size(dg));
m2 = zeros(size(dg));
for i=1:length(dg)
  m1(i) = sum((alpha > dg(i) & alpha < pi + dg(i)).*w);
  m2(i) = n - m1(i);
end
m = min(min([m1;m2]));

if n > 50
  % approximation by Ajne (1968)
  A = pi*sqrt(n) / 2 / (n-2*m);
  pval = sqrt(2*pi) / A * exp(-pi^2/8/A^2);
else
  % exact formula by Hodges (1955)
  pval = 2^(1-n) * (n-2*m) * nchoosek(n,m);
end


function y = gprctile(x,p)
%GPRCTILE Percentile(s) of a grouped sample.
%  In some scientific works, once the data have been gathered from a
%  population of interest, it is often difficult to get a sense of what
%  the data indicate when they are presented in an unorganized fashion.
%  Assembling the raw data into a meaningful form, such as a frequency
%  distribution, makes the data easier to understand and interpret. It is
%  in the context of frequency distributions that the importance of
%  conveying in a succinct way numerical information contained in the data
%  is encountered.
%  So, grouped data is data that has been organized into groups known as
%  classes.  The raw dataset can be organized by constructing a table
%  showing the frequency distribution of the variable (whose values are
%  given in the raw dataset). Such a frequency table is often referred to
%  as grouped data.
%  Here, we developed a m-code to calculate the percentile(s) of a grouped
%  data. One can input the returns or modified vectors n and xout
%  containing the frequency counts and the bin locations of the hist
%  m-function, in a column form matrix.
%
%  Percentile calculation uses the straight forward formula,
%
%                  P = L + I*(N*P/100 - C)/F
%
%  where:
%  L = lower limit of the interval containing the percentile
%  I = width of the interval containing the percentile
%  N = total number of data
%  P = interested percentile
%  C = cumulative frequency corresponding to the previous percentile class
%  F = number of cases in the interval containing the percentile
%
%  Syntax: function y = gprctile(x,p)
%
%  Inputs:
%       x - data matrix (Size of matrix must be n-by-2; absolut frequency=
%           column 1, class mark=column 2)
%       p - is a scalar or a vector of percent values
%  Outputs:
%       y  - percentile(s) of the values in x
%
%  Example: From the example given at
%  http://www.emathzone.com/tutorials/basic-statistics/frequency-distributi
%  on-of-discrete-data.html
%  We are interested to get the percentile values 15,30,60,80.
%
%  Data: 2,4,6,1,3,5,3,7,8,6,4,7,4,4,2,1,3,6,4,2,5,7,9,1,2,10,1,8,9,2,3,1,
%  2,3,4,4,4,6,6,5,5,4,5,8,5,4,3,3,2,5,0,5,9,9,8,10,0,4,10,10,1,1,2,2,1,8,
%  6,9,10
%
%  Using [A,B] = hist(x,11)
%
%  x = [B' A']; p = [15,30,60,80];
%
%                     ----------------
%                        MC       F
%                     ----------------
%                      0.4545     2
%                      1.3636     8
%                      2.2727     9
%                      3.1818     7
%                      4.0909    11
%                      5.0000     8
%                      5.9091     6
%                      6.8182     3
%                      7.7273     5
%                      8.6364     5
%                      9.5455     5
%                     ----------------
%
%  Calling on Matlab the function:
%          y = gprctile(x,p)
%
%  Answer is:
%
%  y = 1.8535    2.9481    5.0455    7.4909
%
%  Created by A. Trujillo-Ortiz, R. Hernandez-Walls and R. Preciado-Perez
%             Facultad de Ciencias Marinas
%             Universidad Autonoma de Baja California
%             Apdo. Postal 453
%             Ensenada, Baja California
%             Mexico.
%             atrujo@uabc.edu.mx
%
%  Copyright (C)  September 15, 2012.
%
%  To cite this file, this would be an appropriate format:
%  Trujillo-Ortiz, A., R. Hernandez-Walls and R. Preciado-Perez. (2012).
%     gprctile:Percentile(s) of a grouped sample. [WWW document].
%     URL http://www.mathworks.com/matlabcentral/fileexchange/
%     38228-gprctile
%
%  Reference:
%  Cann, A. J. (2003), Maths from Scratch for Biologists. John Willey &
%              Sons Ltd. Chichester:England.
%

c = size(x,2);

if c ~= 2
    error('stats:gprctile:BadData','X must have two colums.');
end

if ~isvector(p) || numel(p) == 0
    error('stats:gprctile:BadProbs', ...
          'P must be a scalar or a non-empty vector.');
elseif any(p < 0 | p > 100) || ~isreal(p)
    error('stats:gprctile:BadPercents', ...
          'P must take real values between 0 and 100');
end

mc = x(:,1); %class mark
f = x(:,2); %absolut frequency
a = mc(2) - mc(1); %class interval
fa = cumsum(f); %cumulative absolut frequency
n = fa(end); %sample size

y = [];
for i = 1:length(p)
    r(i) = n*p(i)/100; %interested ordened data (iod)
    cl(i) = min(find(fa > r(i))); %class where the iod are
    l(i) = mc(cl(i));
    L(i) = l(i) - 0.5*a; %lower class boundary
    A(i) =(a/f(cl(i)));
    if (cl(i) - 1) == 0;
        B(i) = r(i);
    else
        B(i) = (r(i) - fa(cl(i) - 1));
    end

    yy = L(i) + A(i)*B(i); %calculation by a linear interpolation
    y = [y yy];
end

return,


function [H,R] = myqr (A)
%MYQR QR factorization using Householder reflections
% uses function [v,beta,xnorm] = hmake1 (x)
% and function hx = happly (v, beta, x)
%
% Example
%   [H,R] = myqr (A)
% See also: testall

%   Copyright 2006-2007, Timothy A. Davis.
%   http://www.cise.ufl.edu/research/sparse

[m n] = size (A) ;

H = zeros (m,n) ;
R = zeros (m,n) ;

for k = 1:n

    % apply prior H's
    % fprintf ('\n-----------------init %d\n', k) ;
    x = A (:,k) ;
    for i = 1:k-1
        v = H(((i+1):m),i) ;
        v = [1 ; v] ;                                                       %#ok
        beta = H (i,i) ;
        % n1 = norm (x (i:m)) ;
        x (i:m) = happly (v, beta, x (i:m)) ;
        % n2 = norm (x (i:m)) ;
        % fprintf ('=============== i %d %g %g\n', i, n1, n2) ;
        % beta
        % v'
        % X = x'
        % pause
        % i
        % x
    end
    % k
    % x

    % make Hk
    % fprintf ('x(k:m) = ') ; x (k:m)
    [v,beta,xnorm] = hmake1 (x (k:m)) ;

    H (k,k) = beta ;
    H (k+1:m, k) = v (2:end) ;

    R (1:(k-1),k) = x (1:(k-1)) ;
    R (k,k) = xnorm ;
    % full (R)
    % pause
end

% s2 = svd (full (R)) ;
% [s1 s2 s1-s2]


function [col4row,row4col,gain]=linBottleneckAssign(C,solSel)
%%LINBOTTLENECKASSIGN Solve the linear bottleneck assignment problem for a
%          square cost matrix. The problem being solved can be formulated
%          as
%          gain=minimize_phi max_i C_{i,phi(i)} where phi is a permutation
%                                               vector.
%          It can also be formulated as:
%          gain=minimize_{x} max_{i,j} C_{i,j}*x_{i,j}
%          subject to
%          \sum_{j=1}^{n}x_{i,j}=1 for all i
%          \sum_{i=1}^{n}x_{i,j}=1 for all j
%          x_{i,j}=0 or 1.
%
%INPUTS: C An nXn cost matrix that does not contain any NaNs.
%   solSel Multiple optimal solutions typically exist to this problem. This
%          parameter specifies which solution to choose. Possible values
%          are:
%          0 (The default if omitted or an empty matrix is passed) Choose
%            a feasible solution without any particular property.
%          1 Choose the optimal solution that also minimizes
%            sum_i C_{i,phi(i)}.
%          2 Choose the optimal solution that also maximizes
%            sum_i C_{i,phi(i)}.
%
%OUTPUTS: col4row An nX1 vector where the entry in each element is an
%                 assignment of the element in that row to a column. This
%                 is equivalent to phi above.
%         row4col A nX1 vector where the entry in each element is an
%                 assignment of the element in that column to a row.
%            gain The value of the cost function of the linear bottleneck
%                 assignment problem at the optimal point.
%
%This function implements Algorithm 6.1 of Chapter 6.2 of [1]. This is an
%algorithm based on thresholding. The choice of which solution is obtained
%in the end depends on whether one uses maxCardBipartMatching in the final
%step, or whether one modifies the cost matrix in the final step according
%to G (forbidden assignments become either Inf or -Inf) and then uses
%assign2D to solve the problem.
%
%EXAMPLE:
%This is example 6.5 from Chapter 6.2 of [1].
% C=[8,2,3,3;
%    2,7,5,8;
%    0,9,8,4;
%    2,5,6,3];
% [col4row,row4col,gain]=linBottleneckAssign(C)
% %Verify the value of the cost function for the permutation.
% n=size(C,1);
% costVal=-Inf;
% for curRow=1:n
%     cij=C(curRow,col4row(curRow));
%     if(cij>costVal)
%         costVal=cij;
%     end
% end
% costVal
%One will see that gain=5 and costVal agrees with the gain. The cost value
%is five even though the col4row assignment is not identical to the in the
%book. Solution variations depend on variations to the algiruthm used for
%the perfect matching. Here, maxCardBipartMatching is used.
%
%REFERENCES:
%[1] R. Burkard, M. Dell'Amico, and S. Martello,Assignment Problems.
%    Philadelphia: Society for Industrial and Applied Mathematics, 2009.
%
%October 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

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

n=size(C,1);

c0=min(C(:));
c1=max(C(:));

if(c0==c1)
    col4row=(1:n).';
    row4col=(1:n).';
    gain=c0;
    return;
end

sel=C<c1&C>c0;
CSel=C(sel);
if(isempty(CSel))
    %This instance can occur, for example, if the matrix contains only two
    %values, such as if C is the identity matrix.
    cStar=c1;
else
    while(~isempty(CSel))
        cStar=medianHi(CSel(:));
        [c0,c1]=feasCheck(C,cStar,c0,c1);

        sel=C<c1&C>c0;
        CSel=C(sel);
    end
end

if(cStar~=c0)
    [~,c1]=feasCheck(C,c0,c0,c1);
end

G=(C<=c1);
switch(solSel)
    case 0
        [col4row,row4col]=maxCardBipartMatching(G);
    case 1
        CNew=Inf(n,n);
        CNew(G)=C(G);
        [col4row,row4col]=assign2D(CNew,false);
        if(isempty(col4row))%If the cost wouldn't have been finite.
            [col4row,row4col]=maxCardBipartMatching(G);
        end
    case 2
        CNew=-Inf(n,n);
        CNew(G)=C(G);
        [col4row,row4col]=assign2D(CNew,true);
        if(isempty(col4row))%If the cost wouldn't have been finite.
            [col4row,row4col]=maxCardBipartMatching(G);
        end
    otherwise
        error('Unknown solution selected.')
end
gain=c1;

end

function [c0,c1]=feasCheck(C,cStar,c0,c1)

G=(C<=cStar);
col4row=maxCardBipartMatching(G);

if(all(col4row~=0))
    %It is feasible.
    c1=cStar;
else
    %It is infeasible.
    c0=cStar;
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 = correlation_power ( n, rho, rho0, e )

%*****************************************************************************80
%
%% CORRELATION_POWER evaluates the power correlation function.
%
%  Discussion:
%
%    The power correlation is
%
%      C(rho) = ( 1 - |rho| )^e  if 0 <= |rho| <= 1
%             = 0                otherwise
%
%      The constraint on the exponent is 2 <= e.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 October 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of arguments.
%
%    Input, real RHO(N,1), the arguments.
%    0.0 <= RHO.
%
%    Input, real RHO0, the correlation length.
%    0.0 < RHO0.
%
%    Input, real E, the exponent.
%    E has a default value of 2;
%    2 <= E.
%
%    Output, real C(N,1), the correlations.
%
  if ( nargin < 4 )
    e = 2.0;
  end

  c = zeros ( n, 1 );

  rho1 = abs ( rho ( : ) ) / rho0;

  i = find ( rho1 <= 1 );

  c(i) = ( 1.0 - rho1(i) ) .^ e;

  return
end


% Black-Scholes implied vol
%
% sigma=impvol(C,S,K,r,t,T,q,tol)
%
% C: call price (scalar or vector)
% S: Stock price (scalar or vector)
% K: Strike price (scalar or vector)
% r: Interest rate (scalar or vector)
% t: Time now (scalar or vector)
% T: Maturity date (scalar or vector)
% [q]: Dividend yield (scalar or vector). Default=0;
% [tol]: Tolerance. Default=1e-6

function sigma=impvol(C,S,K,r,t,T,q,tol)

T=T-t;

if nargin<8
    tol=1e-6;
end

if nargin<7 || isempty(q)
    q=0;
end

F=S*exp((r-q).*T);
G=C.*exp(r.*T);

alpha=log(F./K)./sqrt(T);
beta=0.5*sqrt(T);

% Now we need to solve G=F Phi(d1)- K Phi(d2) where
% d1=alpha/sigma+beta and d2=alpha/sigma-beta

a=beta.*(F+K);
b=sqrt(2*pi)*(0.5*(F-K)-G);
c=alpha.*(F-K);

disc=max(0,b.^2-4*a.*c);

sigma0=(-b+sqrt(disc))./(2*a);

sigma=NewtonMethod(sigma0);

    function s1=NewtonMethod(s0)

        s1=s0;
        count=0;
        f=@(x) call(S,K,r,x,0,T,q)-C;
        fprime=@(x) call_vega(S,K,r,x,0,T,q);

        max_count=1e3;

        while max(abs(f(s1)))>tol && count<max_count
            count=count+1;

            s0=s1;
            s1=s0-f(s0)./fprime(s0);
        end

        if max(abs(f(s1)))>tol
            disp('Newton method did not converge')
        end
    end

end


function out = planesBisector(plane1, plane2)
% PLANESBISECTOR  Bisector plane between two other planes
%
%   BIS = planesBisector(PL1, PL2);
%   Returns the planes that contains the intersection line between PL1 and
%   PL2 and that bisect the dihedral angle of PL1 and PL2.
%   Note that computing the bisector of PL2 and PL1 (in that order) returns
%   the same plane but with opposite orientation.
%
%   Example
%     % Draw two planes together with their bisector
%     pl1 = createPlane([3 4 5], [1 2 3]);
%     pl2 = createPlane([3 4 5], [2 -3 4]);
%     % compute bisector
%     bis = planesBisector(pl1, pl2);
%     % setup display
%     figure; hold on; axis([0 10 0 10 0 10]);
%     set(gcf, 'renderer', 'opengl')
%     view(3);
%     % draw the planes
%     drawPlane3d(pl1, 'g');
%     drawPlane3d(pl2, 'g');
%     drawPlane3d(bis, 'b');
%
%   See also
%   planes3d, dihedralAngle, intersectPlanes
%
%   Author: Ben X. Kang
%   Dept. Orthopaedics & Traumatology
%   Li Ka Shing Faculty of Medicine
%   The University of Hong Kong
%   Pok Fu Lam, Hong Kong
%

% Let the two planes be defined by equations
%
%  a1*x + b1*y + c1*z + d1 = 0
%
% and
%
%  a2*x + b2*y + c2*z + d2 = 0
%
% in which vectors [a1,b1,c1] and [a2,b2,c2] are normalized to be of unit
% length (a^2+b^2+c^2 = 1). Then
%
%  (a1+a2)*x + (b1+b2)*y + (c1+c2)*z + (d1+d2) = 0
%
% is the equation of the desired plane which bisects the dihedral angle
% between the two planes.  These coefficients cannot be all zero because
% the two given planes are not parallel.
%
% Notice that there is a second solution to this problem
%
%  (a1-a2)*x + (b1-b2)*y + (c1-c2)*z + (d1-d2) = 0
%
% which also is a valid plane and orthogonal to the first solution. One of
% these planes bisects the acute dihedral angle, and the other the
% supplementary obtuse dihedral angle, between the two given planes.

P1 = plane1(1:3);			% a point on the plane
n1 = planeNormal(plane1);	% the normal of the plane
% d1 = -dot(n1, P1);		% for line equation

P2 = plane2(1:3);
n2 = planeNormal(plane2);
% d2 = -dot(n2, P2);

if ~isequal(P1(1:3), P2(1:3))
	L = intersectPlanes(plane1, plane2);	% intersection of the given two planes
	Pt = L(1:3);							% a point on the line intersection
% 	v2 = cross(n1-n2, L(4:6));				% another vector lie on the bisect plane
% 	out = [v1, v2]';
else
	Pt = P1(1:3);
end

% use column-wise vector
out = createPlane(Pt, n1 - n2);

%%  EOF  %%


function [Jacobian, Joint] = ARM_2DOF(L1, L2, theta1, theta2, draw, orgX, orgY)
%% Function Configuration
if (nargin == 5)
    orgX = 0;
    orgY = 0;
end

%% Modelling of the Manipulator
X(1)= orgX+ L1*cosd(theta1);
Y(1)= orgY+ L1*sind(theta1);
X(2)= X(1)+ L2*cosd(theta1 + theta2);
Y(2)= Y(1)+ L2*sind(theta1 + theta2);

% Storing the Joint Locations of the Manipulator
Joint = [orgX, orgY; X(1), Y(1); X(2), Y(2)];

% Storing the Jacobian matrix for the current Manipulator configuration
Jacobian = [-L1*sind(theta1) - L2*sind(theta1+theta2), -L2*sind(theta1+theta2);
    L1*cosd(theta1)+ L2*cosd(theta1+theta2), L2*cosd(theta1+theta2)];

% If it was mentioned in the parameter 'draw' then draw the manipulator.
if draw == true
    plot([orgX,X(1)],[orgY,Y(1)]);
    hold on
    plot([X(1),X(2)],[Y(1),Y(2)]);
    axis([-(L1 + L2), (L1 + L2), -(L1 + L2), (L1 + L2)]);
    hold off;
    title('2 DOF Planar Manipulator');
    legend('1st Link of Arm', '2nd Link of Arm');
    drawnow;
end

end


function [v,usediters] = projfunc( s, k1, k2, nn )

% Solves the following problem:
% Given a vector s, find the vector v having sum(abs(v))=k1
% and sum(v.^2)=k2 which is closest to s in the euclidian sense.
% If the binary flag nn is set, the vector v is additionally
% restricted to being non-negative (v>=0).
%
% Written 2.7.2004 by Patrik O. Hoyer
%

% Problem dimension
N = length(s);

% If non-negativity flag not set, record signs and take abs
if ~nn,
    isneg = s<0;
    s = abs(s);
end

% Start by projecting the point to the sum constraint hyperplane
v = s + (k1-sum(s))/N;

% Initialize zerocoeff (initially, no elements are assumed zero)
zerocoeff = [];

j = 0;
while 1,

    % This does the proposed projection operator
    midpoint = ones(N,1)*k1/(N-length(zerocoeff));
    midpoint(zerocoeff) = 0;
    w = v-midpoint;
    a = sum(w.^2);
    b = 2*w'*v;
    c = sum(v.^2)-k2;
    alphap = (-b+real(sqrt(b^2-4*a*c)))/(2*a);
    v = alphap*w + v;

    if all(v>=0),
	% We've found our solution
	usediters = j+1;
	break;
    end

    j = j+1;

    % Set negs to zero, subtract appropriate amount from rest
    zerocoeff = find(v<=0);
    v(zerocoeff) = 0;
    tempsum = sum(v);
    v = v + (k1-tempsum)/(N-length(zerocoeff));
    v(zerocoeff) = 0;

end

% If non-negativity flag not set, return signs to solution
if ~nn,
    v = (-2*isneg + 1).*v;
end

% Check for problems
if max(max(abs(imag(v))))>1e-10,
    error('Somehow got imaginary values!');
end


function inside = circle_sector_contains_point_2d ( r, center, theta1, theta2, p )

%*****************************************************************************80
%
%% CIRCLE_SECTOR_CONTAINS_POINT_2D : is a point inside a circular sector?
%
%  Discussion:
%
%    A circular sector is formed by a circular arc, and the two straight line
%    segments that join its ends to the center of the circle.
%
%    A circular sector is defined by
%
%      ( X - CENTER(1) )**2 + ( Y - CENTER(2) )**2 = R**2
%
%    and
%
%      Theta1 <= Theta <= Theta2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    08 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the radius of the circle.
%
%    Input, real CENTER(2), the center of the circle.
%
%    Input, real THETA1, THETA2, the angles defining the arc,
%    in radians.  Normally, THETA1 < THETA2.
%
%    Input, real P(2), the point to be checked.
%
%    Output, logical INSIDE, is TRUE if the point is inside or on the
%    circular sector, FALSE otherwise.
%
  inside = 0;
%
%  Is the point inside the (full) circle?
%
  if ( ( p(1) - center(1) ) * ( p(1) - center(1) ) ...
     + ( p(2) - center(2) ) * ( p(2) - center(2) ) <= r * r )
%
%  Is the point's angle within the arc's range?
%  Try to force the angles to lie between 0 and 2 * PI.
%
    theta = r8_atan ( p(2) - center(2), p(1) - center(1) );

    if ( r8_modp ( theta  - theta1,  2.0 * pi ) <= ...
         r8_modp ( theta2 - theta1,  2.0 * pi ) )

      inside = 1;

    end

  end

  return
end


function vs = sphere01_triangle_vertices_to_centroid ( v1, v2, v3 )

%*****************************************************************************80
%
%% SPHERE01_TRIANGLE_VERTICES_TO_CENTROID gets a spherical triangle centroid.
%
%  Discussion:
%
%    A unit sphere centered at 0 in 3D satisfies the equation:
%
%      X*X + Y*Y + Z*Z = 1
%
%    A spherical triangle is specified by three points on the sphere.
%
%    The (true) centroid of a spherical triangle is the point
%
%      VT = (XT,YT,ZT) = Integral ( X, Y, Z ) dArea / Integral 1 dArea
%
%    Note that the true centroid does NOT, in general, lie on the sphere.
%
%    The "flat" centroid VF is the centroid of the planar triangle defined by
%    the vertices of the spherical triangle.
%
%    The "spherical" centroid VS of a spherical triangle is computed by
%    the intersection of the geodesic bisectors of the triangle angles.
%    The spherical centroid lies on the sphere.
%
%    VF, VT and VS lie on a line through the center of the sphere.  We can
%    easily calculate VF by averaging the vertices, and from this determine
%    VS by normalizing.
%
%    Of course, we still will not have actually computed VT, which lies
%    somewhere between VF and VS!
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real V1(3), V2(3), V3(3), the vertices of the triangle.
%
%    Output, real VS(3), the coordinates of the "spherical
%    centroid" of the spherical triangle.
%
  vs(1:3) = ( v1(1:3) + v2(1:3) + v3(1:3) ) / 3.0;

  norm = sqrt ( sum ( vs(1:3).^2 ) );

  vs(1:3) = vs(1:3) / norm;

  return
end


function [ zfilt ] = gaussfilt( t,z,sigma )
%Apply a Gaussian filter to a time series
%   Inputs: t = independent variable, z = data at points t, and
%       sigma = standard deviation of Gaussian filter to be applied.
%   Outputs: zfilt = filtered data.
%
%   written by James Conder. Aug 22, 2013

n = length(z);  % number of data
zfilt = 0*z;    % initalize output vector

%%% get distances between points for proper weighting
w = 0*t;
w(2:end-1) = 0.5*(t(3:end)-t(1:end-2));
w(1) = t(2)-t(1);
w(end) = t(end)-t(end-1);

%%% check if sigma smaller than data spacing
iw = find(w > 2*sigma, 1);
if ~isempty(iw)
    disp('WARNING: sigma smaller than half node spacing')
    disp('May lead to unstable result')
    iw = w > 2.5*sigma;
    w(iw) = 2.5*sigma;
    % this correction leaves some residual for spacing between 2-3sigma.
    % otherwise ok.
    % In general, using a Gaussian filter with sigma less than spacing is
    % a bad idea anyway...
end

%%% loop over points
a = 1/(sqrt(2*pi)*sigma);
sigma2 = sigma*sigma;
for i = 1:n
    filter = a*exp(-0.5*((t - t(i)).^2)/(sigma2));
    zfilt(i) = sum(w.*z.*filter);
end

%%% clean-up edges - mirror data for correction
ss = 2.4*sigma;   % distance from edge that needs correcting

% left edge
tedge = min(t);
iedge = find(t < tedge + ss);
nedge = length(iedge);
for i = 1:nedge;
    dist = t(iedge(i)) - tedge;
    include = find( t > t(iedge(i)) + dist);
    filter = a*exp(-0.5*((t(include) - t(iedge(i))).^2)/(sigma2));
    zfilt(iedge(i)) = zfilt(iedge(i)) + sum(w(include).*filter.*z(include));
end

% right edge
tedge = max(t);
iedge = find(t > tedge - ss);
nedge = length(iedge);
for i = 1:nedge;
    dist = tedge - t(iedge(i));
    include = find( t < t(iedge(i)) - dist);
    filter = a*exp(-0.5*((t(include) - t(iedge(i))).^2)/(sigma2));
    zfilt(iedge(i)) = zfilt(iedge(i)) + sum(w(include).*filter.*z(include));
end

end


function h=plotgauss2d(mu, Sigma)
% PLOTGAUSS2D Plot a 2D Gaussian as an ellipse with optional cross hairs
% h=plotgauss2(mu, Sigma)
%

h = plotcov2(mu, Sigma);
return;

%%%%%%%%%%%%%%%%%%%%%%%%

% PLOTCOV2 - Plots a covariance ellipse with major and minor axes
%            for a bivariate Gaussian distribution.
%
% Usage:
%   h = plotcov2(mu, Sigma[, OPTIONS]);
%
% Inputs:
%   mu    - a 2 x 1 vector giving the mean of the distribution.
%   Sigma - a 2 x 2 symmetric positive semi-definite matrix giving
%           the covariance of the distribution (or the zero matrix).
%
% Options:
%   'conf'    - a scalar between 0 and 1 giving the confidence
%               interval (i.e., the fraction of probability mass to
%               be enclosed by the ellipse); default is 0.9.
%   'num-pts' - the number of points to be used to plot the
%               ellipse; default is 100.
%
% This function also accepts options for PLOT.
%
% Outputs:
%   h     - a vector of figure handles to the ellipse boundary and
%           its major and minor axes
%
% See also: PLOTCOV3

% Copyright (C) 2002 Mark A. Paskin

function h = plotcov2(mu, Sigma, varargin)

if size(Sigma) ~= [2 2], error('Sigma must be a 2 by 2 matrix'); end
if length(mu) ~= 2, error('mu must be a 2 by 1 vector'); end

[p, ...
 n, ...
 plot_opts] = process_options(varargin, 'conf', 0.9, ...
					'num-pts', 100);
h = [];
holding = ishold;
if (Sigma == zeros(2, 2))
  z = mu;
else
  % Compute the Mahalanobis radius of the ellipsoid that encloses
  % the desired probability mass.
  k = conf2mahal(p, 2);
  % The major and minor axes of the covariance ellipse are given by
  % the eigenvectors of the covariance matrix.  Their lengths (for
  % the ellipse with unit Mahalanobis radius) are given by the
  % square roots of the corresponding eigenvalues.
  if (issparse(Sigma))
    [V, D] = eigs(Sigma);
  else
    [V, D] = eig(Sigma);
  end
  % Compute the points on the surface of the ellipse.
  t = linspace(0, 2*pi, n);
  u = [cos(t); sin(t)];
  w = (k * V * sqrt(D)) * u;
  z = repmat(mu, [1 n]) + w;
  % Plot the major and minor axes.
  L = k * sqrt(diag(D));
  h = plot([mu(1); mu(1) + L(1) * V(1, 1)], ...
	   [mu(2); mu(2) + L(1) * V(2, 1)], plot_opts{:});
  hold on;
  h = [h; plot([mu(1); mu(1) + L(2) * V(1, 2)], ...
	       [mu(2); mu(2) + L(2) * V(2, 2)], plot_opts{:})];
end

h = [h; plot(z(1, :), z(2, :), plot_opts{:})];
if (~holding) hold off; end

%%%%%%%%%%%%

% CONF2MAHAL - Translates a confidence interval to a Mahalanobis
%              distance.  Consider a multivariate Gaussian
%              distribution of the form
%
%   p(x) = 1/sqrt((2 * pi)^d * det(C)) * exp((-1/2) * MD(x, m, inv(C)))
%
%              where MD(x, m, P) is the Mahalanobis distance from x
%              to m under P:
%
%                 MD(x, m, P) = (x - m) * P * (x - m)'
%
%              A particular Mahalanobis distance k identifies an
%              ellipsoid centered at the mean of the distribution.
%              The confidence interval associated with this ellipsoid
%              is the probability mass enclosed by it.  Similarly,
%              a particular confidence interval uniquely determines
%              an ellipsoid with a fixed Mahalanobis distance.
%
%              If X is an d dimensional Gaussian-distributed vector,
%              then the Mahalanobis distance of X is distributed
%              according to the Chi-squared distribution with d
%              degrees of freedom.  Thus, the Mahalanobis distance is
%              determined by evaluating the inverse cumulative
%              distribution function of the chi squared distribution
%              up to the confidence value.
%
% Usage:
%
%   m = conf2mahal(c, d);
%
% Inputs:
%
%   c    - the confidence interval
%   d    - the number of dimensions of the Gaussian distribution
%
% Outputs:
%
%   m    - the Mahalanobis radius of the ellipsoid enclosing the
%          fraction c of the distribution's probability mass
%
% See also: MAHAL2CONF

% Copyright (C) 2002 Mark A. Paskin

function m = conf2mahal(c, d)

m = chi2inv(c, d); % matlab stats toolbox


function [ p, seed ] = triangle_reference_sample ( n, seed )

%*****************************************************************************80
%
%% TRIANGLE_REFERENCE_SAMPLE returns random points in the reference triangle.
%
%  Diagram:
%
%       3
%    s  |\
%    i  | \
%    d  |  \
%    e  |   \  side 2
%       |    \
%    3  |     \
%       |      \
%       1-------2
%
%         side 1
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 December 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points to generate.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real P(2,N), random points in the triangle.
%
%    Output, integer SEED, a seed for the random number generator.
%
  dim_num = 2;

  for j = 1 : n

    [ r, seed ] = r8_uniform_01 ( seed );
%
%  Interpret R as a percentage of the triangle's area.
%
%  Imagine a line L, parallel to side 1, so that the area between
%  vertex 1 and line L is R percent of the full triangle's area.
%
%  The line L will intersect sides 2 and 3 at a fraction
%  ALPHA = SQRT ( R ) of the distance from vertex 1 to vertices 2 and 3.
%
    alpha = sqrt ( r );
%
%  Now choose, uniformly at random, a point on the line L.
%
    [ beta, seed ] = r8_uniform_01 ( seed );

    p(1,j) = ( 1.0 - beta ) * alpha;
    p(2,j) =         beta   * alpha;

  end

  return
end


function z = r8vec_convolution ( m, x, n, y )

%*****************************************************************************80
%
%% R8VEC_CONVOLUTION returns the convolution of two R8VEC's.
%
%  Discussion:
%
%    An R8VEC is a vector of R8's.
%
%    The I-th entry of the convolution can be formed by summing the products
%    that lie along the I-th diagonal of the following table:
%
%    Y3 : 3   4   5   6   7
%    Y2 : 2   3   4   5   6
%    Y1 : 1   2   3   4   5
%       +------------------
%        X1  X2  X3  X4  X5
%
%    which will result in:
%
%    Z = ( X1 * Y1,
%          X1 * Y2 + X2 * Y1,
%          X1 * Y3 + X2 * Y2 + X3 * Y1,
%                    X2 * Y3 + X3 * Y2 + X4 * Y1,
%                              X3 * Y3 + X4 * Y2 + X5 * Y1,
%                                        X4 * Y3 + X5 * Y2,
%                                                  X5 * Y3 )
%
%  Example:
%
%    Input:
%
%      X = (/ 1, 2, 3, 4 /)
%      Y = (/ -1, 5, 3 /)
%
%    Output:
%
%      Z = (/ -1, 3, 10, 17, 29, 12 /)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    05 May 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the dimension of X.
%
%    Input, real X(M), the first vector to be convolved.
%
%    Input, integer N, the dimension of Y.
%
%    Input, real Y(N), the second vector to be convolved.
%
%    Output, real Z(M+N-1), the convolution of X and Y.
%
  z(1:m+n-1,1) = 0.0;

  for j = 1 : n
    z(j:j+m-1,1) = z(j:j+m-1,1) + x(1:m,1) * y(j,1);
  end

  return
end


function y = fcube ( x )

%*****************************************************************************80
%
%% FCUBE sets the cubic data values.
%
%  Discussion:
%
%    Y(X) = ( ( X + 2 ) * X + 3 ) * X + 4
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real Y, the value of the function.
%
  y = ( ( (       1.0E+00 ) ...
                * x + 2.0E+00 ) ...
                * x + 3.0E+00 ) ...
                * x + 4.0E+00;

  return
end


function [ x, w ] = gen_laguerre_ss_compute ( n, alpha )

%*****************************************************************************80
%
%% GEN_LAGUERRE_SS_COMPUTE computes a generalized Gauss-Laguerre quadrature rule.
%
%  Discussion:
%
%    The integral:
%
%      Integral ( 0 <= X < +oo ) EXP ( - X ) * X^ALPHA * F(X) dX
%
%    The quadrature rule:
%
%      Sum ( 1 <= I <= N ) W(I) * F ( X(I) )
%
%    The integral:
%
%      Integral ( 0 <= X < +oo ) X^ALPHA * F(X) dX
%
%    The quadrature:
%
%      Sum ( 1 <= I <= N ) W(I) * EXP ( X(I) ) * F ( X(I) )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 June 2010
%
%  Author:
%
%    Original FORTRAN77 version by Arthur Stroud, Don Secrest.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Arthur Stroud, Don Secrest,
%    Gaussian Quadrature Formulas,
%    Prentice Hall, 1966,
%    LC: QA299.4G3S7.
%
%  Parameters:
%
%    Input, integer N, the order.
%    N must be at least 1.
%
%    Input, real ALPHA, the exponent of the X factor.
%    Set ALPHA = 0.0 for the simplest rule.
%    ALPHA must be nonnegative.
%
%    Output, real X(N), the abscissas.
%
%    Output, real W(N), the weights.
%
  x = zeros ( n, 1 );
  w = zeros ( n, 1 );
%
%  Set the recursion coefficients.
%
  for i = 1 : n
    b(i) = ( alpha + 2 * i - 1 );
  end

  for i = 1 : n
    c(i) = ( i - 1 ) * ( alpha + i - 1 );
  end

  cc = gamma ( alpha + 1.0 ) * prod ( c(2:n) );

  for i = 1 : n
%
%  Compute an estimate for the root.
%
    if ( i == 1 )

      xval = ( 1.0 + alpha ) * ( 3.0 + 0.92 * alpha ) ...
        / ( 1.0 + 2.4 * n + 1.8 * alpha );

    elseif ( i == 2 )

      xval = xval + ( 15.0 + 6.25 * alpha ) / ( 1.0 + 0.9 * alpha + 2.5 * n );

    else

      r1 = ( 1.0 + 2.55 * ( i - 2 ) ) / ( 1.9 * ( i - 2 ) );

      r2 = 1.26 * ( i - 2 ) * alpha / ( 1.0 + 3.5 * ( i - 2 ) );

      ratio = ( r1 + r2 ) / ( 1.0 + 0.3 * alpha );

      xval = xval + ratio * ( xval - x(i-2) );

    end
%
%  Use iteration to find the root.
%
    [ xval, dp2, p1 ] = gen_laguerre_ss_root ( xval, n, alpha, b, c );
%
%  Set the abscissa and weight.
%
    x(i) = xval;
    w(i) = ( cc / dp2 ) / p1;

  end

  return
end


function y = maxstar(x, w)
% maxstar   Log of a sum of exponentials.
%   For vectors, maxstar(x) is equivalent to log(sum(exp(x))).
%   For matrices, maxstar(x) is a row vector and maxstar operates on
%   each column of x. For N-D arrays, maxstar(x) operates along the
%   first non-singleton dimension.
%
%   maxstar(x,w) is the log of a weighted sum of exponentials,
%   equivalent to log(sum(w.*exp(x))). Vectors w and x must be
%   the same length. For matrix x, the weights w can be input as
%   a matrix the same size as x, or as a vector of the same length
%   as columns of x. Weights may be zero or negative, but the result
%   sum(w.*exp(x)) must be greater than zero.
%
%   Acts on first dimensions

if nargin<2
    w = [];
else
    if ~isvector(w)
        error('maxstar: w must be a vector')
    end
    if length(w) ~= size(x,1)
        error('maxstar: weight does not match x')
    end
end
%%
w = w(:);
szx = size(x);
if isempty(w)
    % no weight
    m = max(x);
    y = m + log(sum(exp(bsxfun(@minux,x,m))));
else
    % Move the weight into the exponent xw and find
    % m = max(xw) over terms with positive weights
    wpos = w>0;
    xw = bsxfun(@plus, x(wpos,:), log(w(wpos)));
    m = max(xw);
    exwp = exp( bsxfun(@minus, xw, m) );
    wneg = w<0;
    exwn = exp( x(wneg,:) + bsxfun(@minus,log(-w(wneg)), m) );
    y = m + log(sum(exwp,1) - sum(exwn,1));
end
y = reshape(y,[szx(2:end) 1]);


%% Data import
%Copyright (c) 2011, The MathWorks, Inc.

% Import tumor-weight profile for drugs A & B
ds = dataset('xlsfile', 'Data.xls') ;

% Convert drug type column to nominal
ds.Drug = nominal(ds.Drug)               ;

%% Curve fitting

% Initial estimates for [L0, L1, k1, k2_A and k2_B]
p0 = [0.11 , .149 , 1.836, 0.0154, 0.00732] ;

% Estimate parameters
fh   = @(p , t ) objFcn(p , t , ds.Drug) ;% Function handle
tic
pFit = lsqcurvefit(fh , p0 , ds.Time , ds.TumorWeight ) ;
toc
%% Display results & plot

disp([' Drug-independent parameters: '          , ...
        num2str(pFit(1)), ' (L0), '             , ...
        num2str(pFit(2)), ' (L1) and '          , ...
        num2str(pFit(3)), ' (k1) '              ]) ;

disp([' Drug-dependent parameters: ' , ...
        num2str(pFit(4)), ' (k2 - Drug A) and '              , ...
        num2str(pFit(5)), ' (k2 - Drug B)'   ]) ;

% Plot observations
figure; hold on  ;
idx_A = ds.Drug == 'A' ;
plot(ds.Time(idx_A) , ds.TumorWeight(idx_A) , 'ro')  ;
plot(ds.Time(~idx_A), ds.TumorWeight(~idx_A), 'bo')  ;

% Plot predictions
yPred = fh(pFit, ds.Time) ;
plot(ds.Time(idx_A)  , yPred(idx_A) , 'r:')  ;
plot(ds.Time(~idx_A) , yPred(~idx_A), 'b:')  ;

xlabel('Time (days)')
ylabel('Tumor Weight (milligram)')
title('Tumor growth profile')
legend({'Drug A', 'Drug B'})


function x = half_normal_cdf_inv ( cdf, a, b )

%*****************************************************************************80
%
%% HALF_NORMAL_CDF_INV inverts the Half Normal CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real CDF, the value of the CDF.
%    0.0 <= CDF <= 1.0.
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Output, real X, the corresponding argument.
%
  if ( cdf < 0.0 | 1.0 < cdf )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'HALF_NORMAL_CDF_INV - Fatal error!\n' );
    fprintf ( 1, '  CDF < 0 or 1 < CDF.\n' );
    error ( 'HALF_NORMAL_CDF_INV - Fatal error!' );
  end

  cdf2 = 0.5 * ( cdf + 1.0 );

  x = normal_cdf_inv ( cdf2, a, b );

  return
end


function [ xdp, ddp ] = dif_basis_derivk ( nd, xd, k )

%*****************************************************************************80
%
%% DIF_BASIS_DERIVK: Lagrange basis K-th derivative difference tables.
%
%  Discussion:
%
%    Given ND points XD, a Lagrange basis polynomial L(J)(X) is associated
%    with each point XD(J).
%
%    This function computes a table DDP(*,*) whose J-th column contains
%    the difference table for the K-th derivative of L(J)(X).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 June 2013
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carl deBoor,
%    A Practical Guide to Splines,
%    Springer, 2001,
%    ISBN: 0387953663,
%    LC: QA1.A647.v27.
%
%  Parameters:
%
%    Input, integer ND, the number of data points.
%
%    Input, real XD(ND), the X values upon which the
%    Lagrange basis polynomials are to be based.
%
%    Input, integer K, the index of the derivative.
%
%    Output, real XDP(ND-K), the X values upon with
%    the derivative difference table is based.  In fact, these are
%    all 0.
%
%    Output, real DDP(ND-K,ND), the divided difference
%    tables for all the Lagrange basis polynomials.  Column J of DDP
%    contains the table for basis polynomial associated with XD(J).
%
  ddp = zeros ( nd - k, nd );
%
%  Process the vectors one column at a time.
%
  for j = 1 : nd
%
%  Set the data.
%
    yd(1:nd,1) = 0.0;
    yd(j,1) = 1.0;
%
%  Compute the divided difference table.
%
    dd = data_to_dif ( nd, xd, yd );
%
%  Compute the divided difference table for the derivative.
%
    [ xdp, ddp(1:nd-k,j) ] = dif_derivk_table ( nd, xd, dd, k );

  end

  return
end


function [ iters, endpt ] = hooke ( nvars, startpt, rho, eps, itermax, f )

%*****************************************************************************80
%
%% HOOKE seeks a minimizer of a scalar function of several variables.
%
%  Discussion:
%
%    This routine find a point X where the nonlinear objective function
%    F(X) has a local minimum.  X is an N-vector and F(X) is a scalar.
%    The objective function F(X) is not required to be differentiable
%    or even continuous.  The program does not use or require derivatives
%    of the objective function.
%
%    The user supplies three things:
%    1) a subroutine that computes F(X),
%    2) an initial "starting guess" of the minimum point X,
%    3) values for the algorithm convergence parameters.
%
%    The program searches for a local minimum, beginning from the
%    starting guess, using the Direct Search algorithm of Hooke and
%    Jeeves.
%
%    This program is adapted from the Algol pseudocode found in the
%    paper by Kaupe, and includes improvements suggested by Bell and Pike,
%    and by Tomlin and Smith.
%
%    The algorithm works by taking "steps" from one estimate of
%    a minimum, to another (hopefully better) estimate.  Taking
%    big steps gets to the minimum more quickly, at the risk of
%    "stepping right over" an excellent point.  The stepsize is
%    controlled by a user supplied parameter called RHO.  At each
%    iteration, the stepsize is multiplied by RHO  (0 < RHO < 1),
%    so the stepsize is successively reduced.
%
%    Small values of rho correspond to big stepsize changes,
%    which make the algorithm run more quickly.  However, there
%    is a chance (especially with highly nonlinear functions)
%    that these big changes will accidentally overlook a
%    promising search vector, leading to nonconvergence.
%
%    Large values of RHO correspond to small stepsize changes,
%    which force the algorithm to carefully examine nearby points
%    instead of optimistically forging ahead.  This improves the
%    probability of convergence.
%
%    The stepsize is reduced until it is equal to (or smaller
%    than) EPS.  So the number of iterations performed by
%    Hooke-Jeeves is determined by RHO and EPS:
%
%      RHO^(number_of_iterations) = EPS
%
%    In general it is a good idea to set RHO to an aggressively
%    small value like 0.5 (hoping for fast convergence).  Then,
%    if the user suspects that the reported minimum is incorrect
%    (or perhaps not accurate enough), the program can be run
%    again with a larger value of RHO such as 0.85, using the
%    result of the first minimization as the starting guess to
%    begin the second minimization.
%
%    Normal use:
%    (1) Code your function F() in the C language;
%    (2) Install your starting guess;
%    (3) Run the program.
%
%    If there are doubts about the result, the computed minimizer
%    can be used as the starting point for a second minimization attempt.
%
%    To apply this method to data fitting, code your function F() to be
%    the sum of the squares of the errors (differences) between the
%    computed values and the measured values.  Then minimize F()
%    using Hooke-Jeeves.
%
%    For example, you have 20 datapoints (T(i), Y(i)) and you want to
%    find A, B and C so that:
%
%      A*t*t + B*exp(t) + C*tan(t)
%
%    fits the data as closely as possible.  Then the objective function
%    F() to be minimized is just
%
%      F(A,B,C) = sum ( 1 <= i <= 20 )
%        ( y(i) - A*t(i)*t(i) - B*exp(t(i)) - C*tan(t(i)) )^2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 2008
%
%  Author:
%
%    ALGOL original by Arthur Kaupe.
%    C version by Mark Johnson.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    M Bell, Malcolm Pike,
%    Remark on Algorithm 178: Direct Search,
%    Communications of the ACM,
%    Volume 9, Number 9, September 1966, page 684.
%
%    Robert Hooke, Terry Jeeves,
%    Direct Search Solution of Numerical and Statistical Problems,
%    Journal of the ACM,
%    Volume 8, Number 2, April 1961, pages 212-229.
%
%    Arthur Kaupe,
%    Algorithm 178:
%    Direct Search,
%    Communications of the ACM,
%    Volume 6, Number 6, June 1963, page 313.
%
%    FK Tomlin, LB Smith,
%    Remark on Algorithm 178: Direct Search,
%    Communications of the ACM,
%    Volume 12, Number 11, November 1969, page 637-638.
%
%  Parameters:
%
%    Input, integer NVARS, the number of spatial dimensions.
%
%    Input, real STARTPT(NVARS), the user-supplied
%    initial estimate for the minimizer.
%
%    Input, real RHO, a user-supplied convergence parameter
%    which should be set to a value between 0.0 and 1.0.  Larger values
%    of RHO give greater probability of convergence on highly nonlinear
%    functions, at a cost of more function evaluations.  Smaller
%    values of RHO reduce the number of evaluations and the program
%    running time, but increases the risk of nonconvergence.
%
%    Input, real EPS, the criterion for halting
%    the search for a minimum.  When the algorithm
%    begins to make less and less progress on each
%    iteration, it checks the halting criterion: if
%    the stepsize is below EPS, terminate the
%    iteration and return the current best estimate
%    of the minimum.  Larger values of EPS (such
%    as 1.0e-4) give quicker running time, but a
%    less accurate estimate of the minimum.  Smaller
%    values of EPS (such as 1.0e-7) give longer
%    running time, but a more accurate estimate of
%    the minimum.
%
%    Input, integer ITERMAX, a limit on the number of iterations.
%
%    Input, function handle F, the name of the function routine,
%    which should have the form:
%      function value = f ( x, n )
%
%    Output, integer ITERS, the number of iterations taken.
%
%    Output, real ENDPT(NVARS), the estimate for the
%    minimizer, as calculated by the program.
%
  verbose = 0;

  for i = 1 : nvars
    newx(i) = startpt(i);
  end

  for i = 1 : nvars
    xbefore(i) = startpt(i);
  end

  for i = 1 : nvars
    if ( startpt(i) == 0.0 )
      delta(i) = rho;
    else
      delta(i) = rho * abs ( startpt(i) );
    end
  end

  funevals = 0;
  steplength = rho;
  iters = 0;
  fbefore = f ( newx, nvars );
  funevals = funevals + 1;
  newf = fbefore;

  while ( iters < itermax & eps < steplength )

    iters = iters + 1;

    if ( verbose )

      fprintf ( 1, '\n' );
      fprintf ( 1, '  FUNEVALS = %d, F(X) = %e\n', funevals, fbefore );
      for i = 1 : nvars
        fprintf ( 1, '  %8d  %e\n', i, xbefore(i) );
      end

    end
%
%  Find best new point, one coordinate at a time.
%
    for i = 1 : nvars
      newx(i) = xbefore(i);
    end

    [ newf, newx, funevals ] = best_nearby ( delta, newx, fbefore, nvars, ...
    f, funevals );
%
%  If we made some improvements, pursue that direction.
%
    keep = 1;

    while ( newf < fbefore & keep == 1 )

      for i = 1 : nvars
%
%  Arrange the sign of DELTA.
%
        if ( newx(i) <= xbefore(i) )
          delta(i) = - abs ( delta(i) );
        else
          delta(i) = abs ( delta(i) );
        end
%
%  Now, move further in this direction.
%
        tmp = xbefore(i);
        xbefore(i) = newx(i);
        newx(i) = newx(i) + newx(i) - tmp;
      end

      fbefore = newf;
      [ newf, newx, funevals ] = best_nearby ( delta, newx, fbefore, nvars, ...
        f, funevals );
%
%  If the further (optimistic) move was bad...
%
      if ( fbefore <= newf )
        break;
      end
%
%  Make sure that the differences between the new and the old points
%  are due to actual displacements; beware of roundoff errors that
%  might cause NEWF < FBEFORE.
%
      keep = 0;

      for i = 1 : nvars
        if ( 0.5 * abs ( delta(i) ) < abs ( newx(i) - xbefore(i) ) )
          keep = 1;
          break
        end
      end

    end

    if ( eps <= steplength & fbefore <= newf )
      steplength = steplength * rho;
      for i = 1 : nvars
        delta(i) = delta(i) * rho;
      end
    end

  end

  for i = 1 : nvars
    endpt(i) = xbefore(i);
  end

  return
end


function varargout = modschaffer4(X)
% modified Schaffer function, #4
%
%   MODSCHAFFER4([x1, x2]) returns the value of the 4th Schaffer
%   function at the specified points. [x1] and [x2] may be vectors.
%   The search domain is
%
%               -100 < x_i < 100
%
%   The global minimum is
%
%               f(x1, x2) = f(0, 1.25313) = 0.292579.

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

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

    % otherwise, output function value
    else

        % keep values within the search interval
        X(X < -100) = inf;      X(X > 100) = inf;

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

        % output function value
        varargout{1} = 0.5  + (cos(sin(abs(x1.^2 - x2.^2))).^2 - 0.5) ./ (1+0.001*(x1.^2 + x2.^2)).^2;

    end

end


function value = j_double_product_integral ( i, j, a, b )

%*****************************************************************************80
%
%% J_DOUBLE_PRODUCT_INTEGRAL: integral of J(i,x)*J(j,x)*(1-x)^a*(1+x)^b.
%
%  Discussion:
%
%    VALUE = integral ( -1 <= x <= +1 ) J(i,x)*J(j,x)*(1-x)^a*(1+x)^b dx
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 March 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, J, the polynomial indices.
%
%    Input, real A, B, the parameters.
%    -1 < A, B.
%
%    Output, real VALUE, the value of the integral.
%
  if ( i ~= j )
    value = 0.0;
  else
    value = 2^( a + b + 1.0 ) / ( 2 * i + a + b + 1 ) ...
      * gamma ( i + a + 1 ) * gamma ( i + b + 1 ) ...
      / r8_factorial ( i ) / gamma ( i + a + b + 1 );
  end

  return
end


function [mappedX, mapping] = em_pca(X, no_dims, max_iter)
%EMPCA Run an EM-based implementation of (probabilistic) PCA
%
%   [mappedX, mapping] = em_pca(X, no_dims)
%
% Performs probabilistic PCA on dataset X in order to reduce its
% dimensionality to no_dims. The dimensionality reduction is performed by
% means of an EM algorithm. The resulting low-dimensional counterpart of X
% is returned in mappedX. Information on the applied mapping (allowing for,
% e.g., out-of-sample extension) is returned in mapping.
%
%

% This file is part of the Matlab Toolbox for Dimensionality Reduction.
% The toolbox can be obtained from http://homepage.tudelft.nl/19j49
% You are free to use, change, or redistribute this code in any way you
% want for non-commercial purposes. However, it is appreciated if you
% maintain the name of the original author.
%
% (C) Laurens van der Maaten, Delft University of Technology

    if ~exist('max_iter', 'var')
        max_iter = 200;
    end

    % Initialize some variables
    [n D] = size(X);                        % data dimensions
    Ez = zeros(no_dims, n);                 % expectation of latent vars
    Ezz = zeros(no_dims, no_dims, n);       % expectation of cov(z)
    Q = Inf;                                % log-likelihood
    mapping = struct;

    % Randomly initialize W and sigma
    W = rand(D, no_dims) * 2;               % factor loadings
    sigma2 = rand(1) * 2;                   % variance ^ 2
    % The covariance of the Gaussian is: C = W * W' + sigma2 * eye(D);

    % Make data zero-mean (possible because data mean is ML estimate for mu)
    mapping.mean = mean(X, 1);
    X = bsxfun(@minus, X, mapping.mean);

    % Compute data covariance and transpose data
    S = cov(X);
    X = X';

    % Perform EM iterations
    converged = 0;
    iter = 0;
    inW = W' * W;
    while ~converged && iter <= max_iter

        % Update iteration number
        iter = iter + 1;
        if rem(iter, 5) == 0
            fprintf('.');
        end

        % Perform E-step
        invM = inv(inW + sigma2 * eye(no_dims));
        for i=1:n
            Ez(:,i)    = invM * W' * X(:,i);
            Ezz(:,:,i) = sigma2 * invM + Ez(:,i) * Ez(:,i)';
        end

        % Perform M-step (maximize mapping W)
        Wp1 = zeros(D, no_dims);
        Wp2 = zeros(no_dims, no_dims);
        for i=1:n
            Wp1 = Wp1 + X(:,i) * Ez(:,i)';
            Wp2 = Wp2 + Ezz(:,:,i);
        end
        W = Wp1 / Wp2;
        inW = W' * W;

        % Perform M-step (maximize discarded variance sigma)
        normX = sum(X .^ 2, 1);
        sigma2 = 0;
        for i=1:n
            sigma2 = sigma2 + (normX(i) - 2 * Ez(:,i)' * W' * X(:,i) + trace(Ezz(:,:,i) * inW));
        end
        sigma2 = (1 / (n * D)) * sigma2;

        % Compute likelihood of new model
        oldQ = Q;
        if iter > 1
            invC = ((1 / sigma2) * eye(D)) - ((1 / sigma2) * W * invM * W');
            detC = det(sigma2 * eye(D)) * det(eye(no_dims) + W' * ((sigma2 .^ -1) * eye(D)) * W);
            Q = (-n / 2) * (D * log(2 * pi) + log(detC) + trace(invC * S));
        end

        % Stop condition to detect convergence
        if abs(oldQ - Q) < 1e-3
            converged = 1;
        end
    end

    % Compute mapped data
    disp(' ');
    mapping.M = (inW \ W')';
    mapping.sigma2 = sigma2;
    mappedX = X' * mapping.M;


function t = tvec_even3 ( nt )

%*****************************************************************************80
%
%% TVEC_EVEN3 computes an evenly spaced set of angles between 0 and 2*PI.
%
%  Discussion:
%
%    The angles begin with 0 and end with 2*PI.
%
%  Example:
%
%    NT = 4
%
%    T = ( 0, 2*PI/3, 4*PI/3 2*PI )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NT, the number of values to compute.
%
%    Output, real TVEC(NT), the evenly spaced angles, in radians.
%
  if ( nt == 1 )
    t(1) = pi;
  else
    t(1:nt) = ( 0:2:(2*nt-1) ) * pi / ( nt - 1 );
  end

  return
end


function [VIn, MIn] = partition_distance(Cx, Cy)
%PARTITION_DISTANCE     Distance or similarity between community partitions
%
%   This function quantifies information-theoretic distance (normalized
%   variation of information) or similarity (normalized mutual information)
%   between community partitions.
%
%   VIn        = partition_distance(Cx);
%   VIn        = partition_distance(Cx, Cy);
%   [VIn, MIn] = partition_distance(Cx, Cy);
%
%   Inputs:
%       Cx,
%           Community partition vector or matrix of n rows and p columns,
%           n is the number of network nodes, and p is the number of input
%           community partitions (in the case of vector input p=1).
%
%       Cy (optional argument),
%           Community partition vector or matrix of n rows and q columns. n
%           is the number of nodes (must be equal to the number of nodes in
%           Cq) and q is the number of input community partitions (may be
%           different to the number of nodes in Cq). This argument may be
%           omitted, in which case, the partition distance is computed
%           between all pairwise partitions of Cx.
%
%   Outputs:
%       VIn,
%           Normalized variation of information ([p, q] matrix)
%
%       MIn,
%           Normalized mutual information ([p, q] matrix)
%
%   Notes:
%       Mathematical definitions.
%
%           VIn = [H(X) + H(Y) - 2MI(X, Y)]/log(n)
%           MIn = 2MI(X, Y) / [H(X) + H(Y)]
%
%           where H is the entropy and MI is the mutual information
%
%
%   Reference: Meila M (2007) J Multivar Anal 98, 873-895.
%
%
%   2011-2017, Mika Rubinov, UNSW, Janelia HHMI

%   Modification History:
%   Mar 2011: Original
%   Jan 2017: Added computation between input matrices.

s = (nargin==1);
if s
    Cy = Cx;
    d = 10.^ceil(log10(double(1 + max( Cx(:)) )));
else
    d = 10.^ceil(log10(double(1 + max([Cx(:);Cy(:)]) )));
end

if ~isequal([Cx(:);Cy(:)], int64([Cx(:);Cy(:)])) || min([Cx(:);Cy(:)])<=0
    error('Input partitions must contain only positive integers.')
end

[n, p] = size(Cx);
HX = zeros(p, 1);
for i = 1:p
    Px = nonzeros(accumarray(Cx(:, i), 1)) / n;                     % P(x)
    HX(i) = - sum(Px .* log(Px));                                   % H(x)
end

if s
    q = p;
    HY = HX;
else
    [n_, q] = size(Cy);
    assert(n == n_);
    HY = zeros(q, 1);
    for j = 1:q
        Py = nonzeros(accumarray(Cy(:, j), 1)) / n;                 % P(y)
        HY(j) = - sum(Py .* log(Py));                               % H(y)
    end
end

VIn = zeros(p, q);
MIn = zeros(p, q);
for i = 1:p
    j_idx = (s * (i - 1) + 1):q;
    for j = j_idx
        Pxy = nonzeros(accumarray(d*Cx(:, i) + Cy(:, j), 1)) / n; 	% P(x,y)
        Hxy = -sum(Pxy .* log(Pxy));                                % H(x,y)
        VIn(i, j) = (2 * Hxy - HX(i) - HY(j)) / log(n);             % VIn
        MIn(i, j) = 2 * (HX(i) + HY(j) - Hxy) / (HX(i) + HY(j));    % MIn
    end
    if s
        VIn(j_idx, i) = VIn(i, j_idx);
        MIn(j_idx, i) = MIn(i, j_idx);
    end
end


function x = log_normal_cdf_inv ( cdf, a, b )

%*****************************************************************************80
%
%% LOG_NORMAL_CDF_INV inverts the Lognormal CDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 1999
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real CDF, the value of the CDF.
%    0.0 <= CDF <= 1.0.
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < B.
%
%    Input, real X, the corresponding argument.
%
  if ( cdf < 0.0 | 1.0 < cdf )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'LOG_NORMAL_CDF_INV - Fatal error!\n' );
    fprintf ( 1, '  CDF < 0 or 1 < CDF.\n' );
    error ( 'LOG_NORMAL_CDF_INV - Fatal error!' );
  end

  logx = normal_cdf_inv ( cdf, a, b );

  x = exp ( logx );

  return
end


function [ pn, dist, t ] = segment_point_near ( p1, p2, p )

%*****************************************************************************80
%
%% SEGMENT_POINT_NEAR finds the line segment point nearest a point.
%
%  Discussion:
%
%    A line segment is the finite portion of a line that lies between
%    two points.
%
%    The nearest point will satisfy the condition
%
%      PN = (1-T) * P1 + T * P2.
%
%    T will always be between 0 and 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(2,1), P2(2,1), the endpoints of the line segment.
%
%    Input, real P(2,1), the point whose nearest neighbor
%    on the line segment is to be determined.
%
%    Output, real PN(2,1), the point on the line segment which is
%    nearest the point (X,Y).
%
%    Output, real DIST, the distance from the point to the
%    nearest point on the line segment.
%
%    Output, real T, the relative position of the point (XN,YN)
%    to the points (X1,Y1) and (X2,Y2).
%

%
%  If the line segment is actually a point, then the answer is easy.
%
  if ( p1(1:2,1) == p2(1:2,1) )

    t = 0.0;

  else

    bot = sum ( ( p2(1:2,1) - p1(1:2,1) ).^2 );

    t = ( p(1:2,1) - p1(1:2,1) )' * ( p2(1:2,1) - p1(1:2,1) ) / bot;

    t = max ( t, 0.0 );
    t = min ( t, 1.0 );

  end

  pn(1:2,1) = p1(1:2,1) + t * ( p2(1:2,1) - p1(1:2,1) );

  dist = sqrt ( sum ( ( pn(1:2,1) - p(1:2,1) ).^2 ) );

  return
end


function [env] = env_secant(x_data, y_data, view, side)
% Function call: env_secant(x_data, y_data, view, side)
% Calculates the top envelope of data <y_data> over <x_data>.
% Method used: 'secant-method'
% env_secant() observates the max. slope of about <view> points,
% and joints them to the resulting envelope.
% An interpolation over original x-values is done finally.
% <side> ('top' or 'bottom') defines which side to evolve.
% Author: Andreas Martin, Volkswagen AG, Germany

side = strcmpi( {'top','bottom'}, side ) * [ 1 ; -1 ];

assert( view > 1, ...
       'Parameter <view> too small!' );
assert( ndims (x_data) == 2, ...
       'Parameter <x_data> has to be vector type!' );
assert( size (x_data, 1) == 1 || size (x_data, 2) == 1, ...
       'Parameter <x_data> has to be vector type (Nx1)!' );
assert( ndims (y_data) == 2, ...
       'Parameter <y_data> has to be vector type (Nx1)!' );
assert( size (y_data, 1) == 1 || size (y_data, 2) == 1, ...
       'Parameter <y_data> has to be vector type (Nx1)!' );
assert( length (x_data) == length (y_data), ...
       'Parameters <x_data> and <y_data> must have same length!' );
assert( side ~= 0, ...
       'Parameter <side> must be ''top'' or ''bottom''' );

y_data = y_data(:);
data_len = length( y_data );
x_new = [];
y_new = [];

i = 1;
while i < data_len;
    ii = i+1:min( i + view, data_len );
    [ m, idx ] = max( ( y_data(ii) - y_data(i) ) ./ (ii-i)' .* side );

    % Equidistant x_data assumed! Use next row instead, if not:
    %[ m, idx ] = max( ( y_data(ii) - y_data(i) ) ./ ( x_data(ii) - x_data(i) ) * side );

    % New max. slope: store new "observation point"
    i = i + idx;
    x_new = [ x_new x_data(i) ];
    y_new = [ y_new y_data(i) ];
end;

env = interp1( x_new, y_new, x_data, 'linear', 'extrap' );


function program_07 ( )

%*****************************************************************************80
%
%% PROGRAM_07: Monte Carlo integral estimate for arbitrary triangle.
%
%  Discussion:
%
%    The program
%    * reads a triangle T (defined by three points),
%    * reads a random number seed;
%    * reads integer exponents P and Q;
%    * reads N, the number of random values to generate;
%    * it then computes N random points in the triangle;
%    * evaluates X^P * Y^Q at each point, and averages
%      to estimate the integral over the triangle.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 February 2007
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'PROGRAM_07 - Monte Carlo estimate of\n' );
  fprintf ( 1, '  Integral x^p y^q\n' );
  fprintf ( 1, '  over an arbitrary triangle.\n' );
%
%  Get the triangle vertices.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Define a triangle T:\n' );

  t_v1 = input ( '  Enter [ T.v1.x, T.v1.y]: ' );
  t_v2 = input ( '  Enter [ T.v2.x, T.v2.y]: ' );
  t_v3 = input ( '  Enter [ T.v3.x, T.v3.y]: ' );
%
%  Get the random number seed.
%
  seed = input ( 'Enter a random number seed:  ' );
  rand ( 'state', seed );
%
%  Get the powers P and Q.
%
  p = input ( 'Enter the power P for X^P:  ' );
  q = input ( 'Enter the power Q for Y^Q:  ' );
%
%  Get the number of values to generate.
%
  n = input ( 'Enter the number of samples to generate:  ' );
%
%  Compute the area.
%
  t_area = 0.5 * ( t_v1(1) * ( t_v2(2) - t_v3(2) ) ...
                 + t_v2(1) * ( t_v3(2) - t_v1(2) ) ...
                 + t_v3(1) * ( t_v1(2) - t_v2(2) ) );
%
%  Generate sample points in the unit triangle,
%  map them to points in the given triangle,
%  evaluate the integrand, add to QUAD.
%
  quad = 0.0;

  for i = 1 : n

    r = rand;
    s = rand;

    xi1 =   1.0       - sqrt ( s );
    xi2 = ( 1.0 - r ) * sqrt ( s );
    xi3 =         r   * sqrt ( s );

    x = xi1 * t_v1(1) + xi2 * t_v2(1) + xi3 * t_v3(1);
    y = xi1 * t_v1(2) + xi2 * t_v2(2) + xi3 * t_v3(2);

    quad = quad + x^p * y^q;

  end
%
%  Normalize QUAD by the area and the number of points.
%
  quad = quad * t_area / n;
%
%  We didn't work out the exact integral, so all we have is
%  this estimate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Estimated integral = %12.6f\n', quad );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'PROGRAM_07\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  return
end


function y = logGauss(X, mu, sigma)
% Compute log pdf of a Gaussian distribution.
% Input:
%   X: d x n data matrix
%   mu: d x 1 mean vector of Gaussian
%   sigma: d x d covariance matrix of Gaussian
% Output:
%   y: 1 x n probability density in logrithm scale y=log p(x)
% Written by Mo Chen (sth4nth@gmail.com).
d = size(X,1);
X = X-mu;
[U,p]= chol(sigma);
if p ~= 0
    error('ERROR: sigma is not PD.');
end
Q = U'\X;
q = dot(Q,Q,1);  % quadratic term (M distance)
c = d*log(2*pi)+2*sum(log(diag(U)));   % normalization constant
y = -(c+q)/2;


%% Mean-Shift Algorithm
% by Sylvain Bernhardt
% July 2008
%% Description
% Computes the mask of a Parzen window
% and its gradient in respect of the x-axis
% and the y-axis.
% The different types of kernel are:
% {Uniform,Triangular,Epanechnikov,Gaussian}
%
% [k,gx,gy] = Parzen_window(H,W,R,type,graph)
% with:
% k - the mask
% gx,gy - its gradients
% (H,W) - size of the mask
% type - its type
% graph - plot the masks if graph=1

function [k,gx,gy] = Parzen_window(H,W,R,type,graph)
k = zeros(H,W);

%% ----Uniform----
if strcmp(type,'Uniform')==1
    for i=1:H
        for j=1:W
            if (((2*i)/H-1)/R)^2+(((2*j)/W-1)/R)^2 <= 1
                k(i,j) = 1;
            end
        end
    end
end

%% ----Triangular----
if strcmp(type,'Triangular')==1
    Max = max(H,W);
    for z=1:round(R*Max/2)-1
        h = zeros(H,W);
        for i=1:H
            for j=1:W
                if ((i-(H/2))/(R*H/2-z*H/Max))^2+...
                        ((j-(W/2))/(R*W/2-z*W/Max))^2 <= 1
                    h(i,j) = 2/(Max*R);
                end
            end
        end
        k = k+h;
    end
end

%% ----Epanechnikov
if strcmp(type,'Epanechnikov')==1
    for i=1:H
        for j=1:W
            k(i,j) = (1-(2*i/(R*H)-1/R)^2-...
                (2*j/(R*W)-1/R)^2);
            if k(i,j) < 0
                k(i,j) = 0;
            end
        end
    end
end

%% ----Gaussian----
if strcmp(type,'Gaussian')==1
    sigmaH = (R*H/2)/3;
    sigmaW = (R*W/2)/3;
    % sigma = x/3 as a gaussian is almost equal to 0
    % from 3*sigma.
    for i=1:H
        for j=1:W
            k(i,j) = exp(-.5*((i-.5*H)^2/sigmaH^2+...
                (j-.5*W)^2/sigmaW^2));
        end
    end
end

%% Gradient of kernel
[gx,gy] = gradient(-k);

%% Plotting the window
if graph==1
    figure (4)
    scrsz = get(0,'ScreenSize');
    set(4,'Position',[scrsz(3)/4 scrsz(4)/4 ...
        scrsz(3)/1.5 scrsz(4)/1.5])
    subplot(2,2,1)
    mesh(k);
    surf(k);
    shading interp
    subplot(2,2,2)
    mesh(gx);
    surf(gx);
    shading interp
    subplot(2,2,3)
    mesh(gy);
    surf(gy);
    shading interp
end


function c=dsti(f,L,dim)
%DSTI  Discrete Sine Transform type I
%   Usage:  c=dsti(f);
%           c=dsti(f,L);
%           c=dsti(f,[],dim);
%           c=dsti(f,L,dim);
%
%   `dsti(f)` computes the discrete sine transform of type I of the
%   input signal *f*. If *f* is multi-dimensional, the transformation is
%   applied along the first non-singleton dimension.
%
%   `dsti(f,L)` zero-pads or truncates *f* to length *L* before doing the
%   transformation.
%
%   `dsti(f,[],dim)` or `dsti(f,L,dim)` applies the transformation along
%   dimension *dim*.
%
%   The transform is real (output is real if input is real) and orthonormal.
%
%   This transform is its own inverse.
%
%   Let f be a signal of length *L* and let `c=dsti(f)`. Then
%
%   ..                         L-1
%     c(n+1) = sqrt(2/(L+1)) * sum sin(pi*(n+1)*(m+1)/(L+1))
%                              m=0
%   .. math:: c\left(n+1\right)=\sqrt{\frac{2}{L+1}}\sum_{m=0}^{L-1}f\left(m+1\right)\sin\left(\frac{\pi \left(n+1\right)\left(m+1\right)}{L+1}\right)
%
%   The implementation of this functions uses a simple algorithm that requires
%   an FFT of length $2N+2$, which might potentially be the product of a large
%   prime number. This may cause the function to sometimes execute slowly.
%   If guaranteed high speed is a concern, please consider using one of the
%   other DST transforms.
%
%   Examples:
%   ---------
%
%   The following figures show the first 4 basis functions of the DSTI of
%   length 20:::
%
%     % The dsti is its own adjoint.
%     F=dsti(eye(20));
%
%     for ii=1:4
%       subplot(4,1,ii);
%       stem(F(:,ii));
%     end;
%
%   See also:  dcti, dstiii, dstiv
%
%   References: rayi90 wi94

%   AUTHOR: Peter L. Søndergaard
%   TESTING: TEST_PUREFREQ
%   REFERENCE: REF_DSTI

complainif_argnonotinrange(nargin,1,3,mfilename);

if nargin<3
  dim=[];
end;

if nargin<2
  L=[];
end;

[f,L,Ls,W,dim,permutedsize,order]=assert_sigreshape_pre(f,L,dim,'DSTI');

if ~isempty(L)
  f=postpad(f,L);
end;

if L==1
  c=f;

else

  c = comp_dst(f,1);

end;

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