%% Distributed Marginal Value-at-Risk Simulation
% This example uses the Parallel Computing Toolbox(TM) to perform a Monte
% Carlo simulation of a number of stocks in a portfolio. At a given
% confidence level, we predict the value at risk (VaR) of the portfolio as
% well as the marginal value at risk (mVaR) of each of the stocks in the
% portfolio.  We also provide confidence intervals for our estimates.
%
%   Copyright 2007-2012 The MathWorks, Inc.
%   Adapted and simplified in 2013 by Michael Weidman, Quantitative Support
%   Services, Ltd.

%% 1. Open a pool of MATLAB workers and load input data

if matlabpool('size') == 0
    matlabpool open
end

load pctdemo_data_mvar

%% 2. Define Parameters

nSims           = 1e5;
relativeWeights = [1 1 2 2 1 3 2]/12;
time            = 50;%(10:1:50)';
confLevel       = 95;

nTimes          = length(time);
nAssets         = size(stock,2);

%% 3. Estimate asset moments

returns         = (stock(2:end,:) - stock(1:end-1,:)) ./ stock(1:end-1,:);
expReturns      = mean(returns);
expCovariances  =  cov(returns);

%% 4. Simulate asset prices

tic

simPrices   = zeros(nTimes, nAssets, nSims);
portPrices  = zeros(nTimes,       1, nSims);
price0      = stock(end,:);
portPrice0  = price0 * relativeWeights';

parfor iSim = 1:nSims
    simPrices( :,:,iSim) = simulatePrices(expReturns, expCovariances, ...
        price0, time);
    portPrices(:,:,iSim) = sum(bsxfun(@times, simPrices(:,:,iSim), ...
        relativeWeights), 2);
end

toc

%% 5. Calculate mVaR and VaR

simRelativeLosses = bsxfun(@rdivide, ...
    bsxfun(@minus, price0, simPrices), price0);
simRelativePortLosses = bsxfun(@minus, portPrice0, portPrices) ...
    ./ portPrice0;

mVaR = prctile(simRelativeLosses    , confLevel, 3);
VaR  = prctile(simRelativePortLosses, confLevel, 3);

%% 6. Plot the Results

plotMVAR(VaR, mVaR, time, names);


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

% N- point IDFTs of a 4-point sequence

X=[10 -2+2j -2 -2-2j];

% 4-point IDFT
ifft(X)

% 4-point IDFT
idft(X)

% 6-point IDFT
ifft(X,6)

% 6-point IDFT
X(6)=0
ifft(X)


function point_num = sphere_icos_point_num ( factor )

%*****************************************************************************80
%
%% SPHERE_ICOS_POINT_NUM sizes an icosahedral grid on a sphere.
%
%  Discussion:
%
%    With FACTOR = 1, the grid has 20 triangular faces, 30 edges, and 12 nodes.
%
%    With FACTOR = 2, each triangle of the icosahedron is subdivided into
%    2x2 subtriangles, resulting in 80 faces, 120 edges, and
%    42 = 12 + 20 * 3 * (1)/2 + 20 * 0 ) nodes.
%
%    With FACTOR = 3, each triangle of the icosahedron is subdivided into
%    3x3 subtriangles, resulting in 180 faces, 270 edges, and
%    92 ( = 12 + 20 * 3 * (2)/2 + 20 * 1 ) nodes.
%
%    In general, each triangle is subdivided into FACTOR*FACTOR subtriangles,
%    resulting in 20 * FACTOR * FACTOR faces, 30 * FACTOR * FACTOR edges, and
%      12
%    + 20 * 3          * (FACTOR-1) / 2
%    + 20 * (FACTOR-2) * (FACTOR-1) / 2 nodes.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 July 2007
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer FACTOR, the subdivision factor, which must
%    be at least 1.
%
%    Output, integer POINT_NUM, the number of nodes.
%
  point_num =   12                                   ...
              + 10 * 3              * ( factor - 1 ) ...
              + 10 * ( factor - 2 ) * ( factor - 1 );

  return
end


function xfat = r8vec_expand_linear ( n, x, fat )

%*****************************************************************************80
%
%% R8VEC_EXPAND_LINEAR linearly interpolates new data into a vector.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 October 2001
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of input data values.
%
%    Input, real X(N), the original data.
%
%    Input, integer FAT, the number of data values to interpolate
%    between each pair of original data values.
%
%    Output, real XFAT((N-1)*(FAT+1)+1), the "fattened" data.
%
  k = 0;

  for i = 1 : n-1

    k = k + 1;
    xfat(k) = x(i);

    for j = 1 : fat
      k = k + 1;
      xfat(k) = ( ( fat - j + 1 ) * x(i)     ...
                + (       j     ) * x(i+1) ) ...
                / ( fat     + 1 );
    end

  end

  k = k + 1;
  xfat(k) = x(n);

  return
end


function t = tvec_even_bracket2 ( nt, theta1, theta2 )

%*****************************************************************************80
%
%% TVEC_EVEN_BRACKET2 computes an evenly spaced set of angles between THETA1 and THETA2.
%
%  Example:
%
%    NT = 5
%    THETA1 = 30
%    THETA2 = 90
%
%    T = ( 40, 50, 60, 70, 80 )
%
%  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.
%
%    Input, real THETA1, THETA2, the limiting angles.
%
%    Output, real TVEC(NT), the evenly spaced angles.
%
  for i = 1 : nt
    t(i) = ( ( nt + 1 - i ) * theta1   ...
           + (          i ) * theta2 ) ...
           / ( nt + 1     );
  end

  return
end


function [ code, itree, more ] = tree_parent_next ( nnode, more )

%*****************************************************************************80
%
%% TREE_PARENT_NEXT generates, one at a time, all labeled trees.
%
%  Discussion:
%
%    The routine also returns the corresponding Pruefer codes.
%
%    There are N^(N-2) labeled trees on N nodes (Cayley's formula).
%
%    The number of trees in which node I has degree D(I) is the
%    multinomial coefficient: ( N-2; D(1)-1, D(2)-1, ..., D(N)-1 ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 June 2013
%
%  Parameters:
%
%    Input, integer NNODE, the number of nodes to be used in
%    the trees.
%
%    Output, integer CODE(NNODE).  The first NNODE-2 entries
%    of CODE contain the Pruefer code for the given labeled tree.
%
%    Output, integer ITREE(NNODE).  The first NNODE-1 entries
%    of ITREE describe the edges that go between the nodes.  Each pair
%    (I, ITREE(I)) represents an edge.  Thus if ITREE(5) = 3,
%    there is an edge from node 3 to node 5.
%
%    Input/output, logical MORE.  On the first call only, the
%    user is required to set MORE = .FALSE.  Then call the routine, and
%    it will return information about the first tree
%    as well as setting MORE to the value .TRUE.
%    Keep calling to get another tree until MORE is .FALSE.
%    on return, at which point there are no more trees.
%
  persistent iarray;

  if ( ~ more )
    iarray = [];
  end

  [ iarray, more ] = vec_next ( nnode-2, nnode, iarray, more );

  code(1:nnode-2) = iarray(1:nnode-2) + 1;

  itree = pruefer_to_tree_2 ( nnode, code );

  return
end


function cubePoissonP2
%% CUBEPOISSONP2 solves Poisson equation in a cube using quadratic element.
%
% Copyright (C) 2008 Long Chen. See COPYRIGHT.txt for details.

close all;
%% Parameters
maxIt = 3;
N = zeros(maxIt,1);
h = zeros(maxIt,1);

%% Generate an initial mesh
[node,elem] = cubemesh([-1,1,-1,1,-1,1],0.5);

%% Get the data of the pde
pde = sincosdata3;
% pde = polydata3;

%% Set up boundary condition
bdFlag = setboundary3(node,elem,'Dirichlet');
% bdFlag = setboundary3(node,elem,'Neumann');

%% Finite Element Method
errL2 = zeros(maxIt,1);
errH1 = zeros(maxIt,1);
erruIuh = zeros(maxIt,1);
for k=1:maxIt
    % refine grid
    [node,elem,bdFlag] = uniformrefine3(node,elem,bdFlag);
    % solve the equation
    [soln,eqn] = Poisson3P2(node,elem,bdFlag,pde);
    uh = soln.u;
    N(k) = length(uh);
    h(k) = 1./(size(node,1)^(1/3)-1);
    errH1(k) = getH1error3(node,elem,pde.Du,uh);
    errL2(k) = getL2error3(node,elem,pde.exactu,uh);
    uI = pde.exactu([node; (node(eqn.edge(:,1),:)+node(eqn.edge(:,2),:))/2]);
    erruIuh(k) = sqrt((uh-uI)'*eqn.Lap*(uh-uI));
    %error(k) = norm(u(1:N(k))-uI(1:N(k)));
end

%% Plot convergence rates
figure;
showrateh3(h,errH1,2,'-*', '|| Du - Du_h ||', ...
           h,errL2,2,'k-+', '|| u - u_h ||', ...
           h,erruIuh,2,'m-+','|| D u_I - D u_h ||');

fprintf('\n');
disp('Table: Error')
colname = {'#Dof','h','|| u-u_h ||','|| Du-Du_h ||','|| Du_I-Du_h ||'};
disptable(colname,N,[],h,'%0.3e',errL2,'%0.5e',errH1,'%0.5e',erruIuh,'%0.5e');


function [all_theta] = oneVsAll(X, y, num_labels, lambda)
    %% ONEVSALL trains multiple logistic regression classifiers and returns all
    %the classifiers in a matrix all_theta, where the i-th row of all_theta
    %corresponds to the classifier for label i
    %   [all_theta] = ONEVSALL(X, y, num_labels, lambda) trains num_labels
    %   logisitc regression classifiers and returns each of these classifiers
    %   in a matrix all_theta, where the i-th row of all_theta corresponds
    %   to the classifier for label i

    % Some useful variables
    n = size(X, 1);
    d = size(X, 2);

    % You need to return the following variables correctly
    all_theta = zeros(num_labels, d + 1);

    % Add ones to the X data matrix
    X = [ones(n, 1) X];

    % ====================== YOUR CODE HERE ======================
    % Instructions: You should complete the following code to train num_labels
    %               logistic regression classifiers with regularization
    %               parameter lambda.
    %
    % Hint: theta(:) will return a column vector.
    %
    % Hint: You can use y == c to obtain a vector of 1's and 0's that tell use
    %       whether the ground truth is true/false for this class.
    %
    % Note: For this assignment, we recommend using fmincg to optimize the cost
    %       function. It is okay to use a for-loop (for c = 1:num_labels) to
    %       loop over the different classes.
    %
    %       fmincg works similarly to fminunc, but is more efficient when we
    %       are dealing with large number of parameters.
    %
    % Example Code for fmincg:
    %
    %     % Set Initial theta
    %     initial_theta = zeros(n + 1, 1);
    %
    %     % Set options for fminunc
    %     options = optimset('GradObj', 'on', 'MaxIter', 50);
    %
    %     % Run fmincg to obtain the optimal theta
    %     % This function will return theta and the cost
    %     [theta] = ...
    %         fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), ...
    %                 initial_theta, options);
    %

    % for optimization of theta
    options = optimset('GradObj', 'on', 'MaxIter', 50);

    % for each class label
    for k = 1 : num_labels

        % initialize theta, and minimize value for cost function
        init_theta = zeros(d + 1, 1);
        theta = fmincg(@(t)(lrCostFunction(t, X, (y == k), lambda)), ...
            init_theta, options);
        all_theta(k, :) = theta';
    end
end


% MAHAL2CONF - Translates a Mahalanobis distance into a confidence
%              interval.  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.
%
%              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 confidence interval is
%              determined by integrating the chi squared distribution
%              up to the Mahalanobis distance of the measurement.
%
% Usage:
%
%   c = mahal2conf(m, d);
%
% Inputs:
%
%   m    - the Mahalanobis radius of the ellipsoid
%   d    - the number of dimensions of the Gaussian distribution
%
% Outputs:
%
%   c    - the confidence interval, i.e., the fraction of
%          probability mass enclosed by the ellipsoid with the
%          supplied Mahalanobis distance
%
% See also: CONF2MAHAL

% Copyright (C) 2002 Mark A. Paskin
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful, but
% WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
% General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
% USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function c = mahal2conf(m, d)

c = chi2cdf(m, d);


function [varargout] = cubic_cubic_integrated_distance( ...
    x, ...
    y, ...
    g_C, ...
    h_C, ...
    P, ...
    g_D, ...
    h_D, ...
    Q)
  %
  % [E] = cubic_cubic_integrated_distance( x, y, g_C, h_C, P, g_D, h_D, Q)
  % [H,F,c] = cubic_cubic_integrated_distance( x, y, g_C, h_C, P, g_D, h_D)
  %
  % E = ½ ∫ₓʸ ‖ C( g_C u + h_C ) - D( g_D u + h_D ) ‖² du
  %
  % where C's control points are in rows of P and D's control points are in rows
  % of Q.
  %
  % E = 0.5*trace(Q.'*H*Q) + trace(Q.'*F) + c;
  %
  % That is,
  %   Q★ = argmin_Q E(Q)
  %   Q★ = H⁻¹ F
  %
  % Where
  %
  % C(T) = (1-T)³ Pᵢ⁰ + 3(1-T)²T Pᵢ¹ + 3(1-T)T² Pᵢ² + T³ Pᵢ³
  % D(T) = (1-T)³ Qᵢ⁰ + 3(1-T)²T Qᵢ¹ + 3(1-T)T² Qᵢ² + T³ Qᵢ³
  %
  % Inputs:
  %   x  starting value of integral 0≤x<1
  %   y  ending value of integral x<y≤1
  %   g_C  scalar multiplicative factor in parametric values of fixed curve
  %   h_C  scalar additive factor in parametric values of fixed curve
  %   P  4 by dim list of fixed curve control points
  %   g_D  scalar multiplicative factor in parametric values of fixed curve
  %   h_D  scalar additive factor in parametric values of fixed curve
  %   Q  4 by dim list of unknown curve control points (optional)
  % Outputs
  %   E  integrated energy
  %   H  4 by 4 quadratic form of energy as function of Q
  %   F  4 by dim linear term of energy as function of Q
  %   c  scalar constant of energy as function of Q
  %
  if isfloat(x) && isfloat(y)
    assert(x>=0);
    assert(x<1);
    assert(y>=x);
    assert(y<=1);
  end
  dim = size(P,2);

  % https://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_quadrature
  % n is number of points
  % 2n-1 order polynomial is integrated exactly
  % ↓
  % n = 4

  % https://people.sc.fsu.edu/~jburkardt/datasets/quadrature_rules/quadrature_rules.html
  % n=4 Gauss-Legendre quadrature on [-1,1]
  w = [
    0.347854845137453857373063949222
    0.652145154862546142626936050778
    0.652145154862546142626936050778
    0.347854845137453857373063949222
    ];
  a = [
   -0.861136311594052575223946488893
   -0.339981043584856264802665759103
    0.339981043584856264802665759103
    0.861136311594052575223946488893
  ];
  % Move to [x,y] range.
  u = (0.5*a + 0.5)*(y-x)+x;
  % Adjust weights.
  w = ((y-x)/(1- -1))*w;

  % Evaluate C at quadrature points
  C = cubic_eval( P, g_C*u + h_C);

  % Map quadrature points to D's direct paramter space
  T = g_D * u + h_D;

  if nargout<=1
    % Compute energy directly. This is faster. Better be the same as below.
    %
    % It's ever so slightly different (between 1e-16 and 1e-20)
    E = 0.5*sum(w.*(C - cubic_eval( Q, T)).^2,'all');
    varargout{1} = E;
    return;
  end

  % Stack bezier basis matrices for each evaluation point
  M = [(1-T).^3 3*T.*(1-T).^2 3*T.^2.*(1-T) T.^3];

  W = diag(w);

  H = M.'*W*M;
  assert(all(size(H) == [4 4]));
  F = -M.'*W*C;
  assert(size(F,1) == 4);
  assert(size(F,2) == dim);

  c = 0.5*trace(C.'*W*C);

  if isempty(Q)
    warning("Cant compute energy on empty Q");
    E = [];
  else
    % Actually compute energy
    E = 0.5*trace(Q.'*H*Q) + trace(Q.'*F) + c;
  end

  varargout{1} = H;
  varargout{2} = F;
  varargout{3} = c;
  varargout{4} = E;
end


function A = sllinreg(X, Y, varargin)
%SLLINREG Performs Multivariate Linear Regression and Ridge Regression
%
% $ Syntax $
%   - A = sllinreg(X, Y, ...)
%
% $ Arguments $
%   - X:        The matrix of x samples
%   - Y:        The matrix of y samples
%   - A:        The solved transform matrix
%
% $ Description $
%   - A = sllinreg(X, Y, varargin) solves the linear regression problem to
%     get the linear transforms A: (y = Ax + e). The solution is given by
%     the following optimization problem:
%       A = argmin_{A} sum_i ||y_i - A x_i||^2 + sum_k lambda_k ||a_k||^2
%     Here, Y is a dy x n matrix with the i-th column giving y_i;
%           X is a dx x n matrix with the i-th column giving x_i
%           A is a dy x dx transform matrix
%           a_k is the k-row vector of A, which corresponds to the k-th
%                  component of y
%           lambda_k is the regularization weight in ridge regression
%     According to mathematical analysis, the solution is given as
%       A = (Y * X^T) * (X * X^T + diag(lambda))^{-1}
%     You can specify the following properties to control the regression:
%     \*
%     \t    Table  Linear Regression Properties
%     \h        name       &             description
%              'lambdas'   &  The regularization coefficients in ridge
%                             linear regression. If all components share
%                             the same value, then lambdas can be a scalar.
%                             If different values are for different
%                             dimensions, then lambdas can be a dy x 1
%                             column vector. (default = 0)
%              'weights'   &  The sample weights, can be either [] or
%                             an 1 x n row vector.
%              'invparams' &  The parameters for invoking slinvcov to
%                             compute inverse matrix, in the form of
%                             {method, ...}. default = [], means directly
%                             using inv to do inverse.
%     \*
%
% $ Remarks $
%   - To solve the linear problem like y = Ax + b, you have two ways:
%     (1) centralize x and y respectively, and invoke sllinreg, then set
%         b = my - A * mx
%     (2) invoke sllinrega, which is specially designed for such an
%         augmented problem.
%
% $ History $
%   - Created by Dahua Lin, on Sep 15, 2006
%

%% parse and verify input arguments

if nargin < 2
    raise_lackinput('sllinreg', 2);
end

if ~isnumeric(X) || ~isnumeric(Y) || ndims(X) ~= 2 || ndims(Y) ~= 2
    error('sltoolbox:invalidarg', ...
        'The X and Y should be both 2D numeric matrices');
end

[dx, n] = size(X);
[dy, ny] = size(Y);
if n ~= ny
    error('sltoolbox:sizmismatch', ...
        'X and Y contain different numbers of samples');
end

opts.lambdas = 0;
opts.rv = 1e-3;
opts.weights = [];
opts.invparams = [];
opts = slparseprops(opts, varargin{:});

lambdas = opts.lambdas;
if ~isscalar(lambdas) && ~isequal(size(lambdas), [dy, 1])
    error('lambdas should be either a scalar or a dy x 1 column vector');
end

w = opts.weights;
if ~isempty(w)
    if ~isequal(size(w), [1, n])
        error('The sample weights should be a 1 x n row vector');
    end
end

%% main

if isempty(w)
    Xt = X';
else
    Xt = slmulvec(X, w, 2)';
end

M2 = X * Xt;
if ~isequal(lambdas, 0)
    inds = (1:dx)' * (dx+1) - dx;
    M2(inds) = M2(inds) + lambdas;
end

if isempty(opts.invparams)
    invM2 = inv(M2);
else
    invM2 = slinvcov(M2, opts.invparams{:});
end
clear M2;

M1 = Y * Xt;

A = M1 * invM2;


function out = distfcm(center, data)
%DISTFCM Distance measure in fuzzy c-mean clustering.
%	OUT = DISTFCM(CENTER, DATA) calculates the Euclidean distance
%	between each row in CENTER and each row in DATA, and returns a
%	distance matrix OUT of size M by N, where M and N are row
%	dimensions of CENTER and DATA, respectively, and OUT(I, J) is
%	the distance between CENTER(I,:) and DATA(J,:).
%
%       See also FCMDEMO, INITFCM, IRISFCM, STEPFCM, and FCM.

%	Roger Jang, 11-22-94, 6-27-95.
%       Copyright 1994-2016 The MathWorks, Inc.

out = zeros(size(center, 1), size(data, 1));

% fill the output matrix

if size(center, 2) > 1
    for k = 1:size(center, 1)
	out(k, :) = sqrt(sum(((data-ones(size(data, 1), 1)*center(k, :)).^2), 2));
    end
else	% 1-D data
    for k = 1:size(center, 1)
	out(k, :) = abs(center(k)-data)';
    end
end


function [y, sigma, p] = linRegPred(model, X, t)
% Compute linear regression model reponse y = w'*X+w0 and likelihood
% Input:
%   model: trained model structure
%   X: d x n testing data
%   t (optional): 1 x n testing response
% Output:
%   y: 1 x n prediction
%   sigma: variance
%   p: 1 x n likelihood of t
% Written by Mo Chen (sth4nth@gmail.com).
w = model.w;
w0 = model.w0;
y = w'*X+w0;
%% probability prediction
if nargout > 1
    beta = model.beta;
    if isfield(model,'U')
        U = model.U;        % 3.54
        Xo = bsxfun(@minus,X,model.xbar);
        XU = U'\Xo;
        sigma = sqrt((1+dot(XU,XU,1))/beta);   % 3.59
    else
        sigma = sqrt(1/beta)*ones(1,size(X,2));
    end
end

if nargin == 3 && nargout == 3
    p = exp(-0.5*(((t-y)./sigma).^2+log(2*pi))-log(sigma));
end


function x = make_sin_out(T,Sdim,parm)
% Sinusoidal signal

if isfield(parm,'Tstart'),
	Tstart = parm.Tstart;
else
	Tstart = rand(1);
end

% period
Tmin = parm.Tmin;
Tmax = parm.Tmax;

if Sdim==1,
	Tperiod = Tmax;
elseif isfield(parm,'Tperiod')
	Tperiod = parm.Tperiod;
else
	Tstp = (Tmax - Tmin)/(Sdim-1);
	Tperiod = (0:(Sdim-1))*Tstp + Tmin;
	Tperiod = circshift(Tperiod, fix(Sdim/2));
%	Tperiod = ((Sdim-1):-1:0)*Tstp + Tmin;
%	Tperiod = Tmax*rand(1,Sdim) + Tmin;
end

% frequency
omega  = 2*pi./Tperiod(:);

% Sinusoidal signal
t = (1:T) + Tmax*Tstart;
%t = repadd( omega * t, - (2*pi) * rand(Sdim,1) );
x = sin( omega * t );


% Implement a simple version of "Geodesics in Heat" by Crane et al. 2013

clc; clear all; close all;
[V,F] = readOBJ('../data/spot.obj');
[V,F,S] = loop(V,F,2); % upsample the mesh to see the speed difference
use_prefactorization = true; % set it to "true" or "false" to see speed difference

% precompute matrices
A = massmatrix(V,F);
Lc = cotmatrix(V,F);
t = avgedge(V,F)^2;
LHS = A - t*Lc;
G = grad(V,F); % #F*dim by #V
D = div(V,F); % #V by #F*dim

% prefactorization
preLHS = decomposition(LHS);
preLc = decomposition(Lc);

%% change heat source
heatSrcIdx = 1;

tic;

% step 1
delta = zeros(size(V,1),1);
delta(heatSrcIdx) = 1;
if use_prefactorization
    u = preLHS \ delta;
else
    u = LHS \ delta;
end

% step 2
gradu = G*u;
gradu = reshape(gradu, size(F,1), 3);
gradu_normalized = gradu ./ normrow(gradu);
X = -gradu_normalized;

% step 3
divX = D * reshape(X, size(F,1)*3, 1);
if use_prefactorization
    phi = preLc \ divX;
else
    phi = Lc \ divX;
end
phi = phi - phi(heatSrcIdx);

toc;

%% visualization
tsurf(F,V, 'CData', phi);
axis equal;
CM = cbrewer('Reds', 500);
CM = CM(size(CM,1):-1:1,:);
colormap(CM);
colorbar
shading interp
drawnow


function [ fea, out ] = ex_diffusion1( varargin )
%EX_DIFFUSION1 2D Diffusion equation example on a unit square.
%
%   [ FEA, OUT ] = EX_DIFFUSION1( VARARGIN ) Diffusion equation on a unit
%   square with exact solutions. Accepts the following property/value pairs.
%
%       Input       Value/{Default}        Description
%       -----------------------------------------------------------------------------------
%       isol        scalar {1}             Exact solution
%                           1                x*y
%                           2                x^2-y^2
%                           3                2*y/((1+x)^2+y^2)
%                           4                2*y/((1+x)^2+y^2)
%                           5                (sinh(pi*x)*sin(pi*y)+sinh(pi*y)*
%                                            sin(pi*x))/sinh(pi)
%       cd          scalar {0.1}           Diffusion coefficient
%       igrid       scalar 1/{0}           Cell type (0=quadrilaterals, 1=triangles)
%       hmax        scalar {1/40}          Max grid cell size
%       sfun        string {sflag1}        Shape function
%       iphys       scalar 0/{1}           Use physics mode to define problem    (=1)
%                                          or directly define fea.eqn/bdr fields (=0)
%       iplot       scalar 0/{1}           Plot solution (=1)
%                                                                                .
%       Output      Value/(Size)           Description
%       -----------------------------------------------------------------------------------
%       fea         struct                 Problem definition struct
%       out         struct                 Output struct

% Copyright 2013-2022 Precise Simulation, Ltd.

cOptDef = { ...
  'isol',     1; ...
  'cd',       0.1; ...
  'igrid',    0; ...
  'hmax',     1/40; ...
  'sfun',     'sflag1'; ...
  'iphys',    1; ...
  'iplot',    1; ...
  'fid',      1 };
[got,opt] = parseopt(cOptDef,varargin{:});
fid       = opt.fid;
switch opt.isol
  case 1
    refsol = 'x*y';
  case 2
    refsol = 'x^2-y^2';
  case 3
    refsol = '2*y/((1+x)^2+y^2)';
  case 4
    refsol = 'exp(pi*x)*sin(pi*y)';   % pi can be substituted for any constant.
  case 5
    refsol = '(sinh(pi*x)*sin(pi*y)+sinh(pi*y)*sin(pi*x))/sinh(pi)';
end

% Geometry definition.
gobj = gobj_rectangle();
fea.geom.objects = { gobj };

% Grid generation.
switch opt.igrid
  case -1
    fea.grid = rectgrid(round(1/opt.hmax));
    fea.grid = quad2tri(fea.grid);
  case 0
    fea.grid = rectgrid(round(1/opt.hmax));
  case 1
    fea.grid = gridgen(fea,'hmax',opt.hmax,'fid',fid);
end
n_bdr = max(fea.grid.b(3,:));           % Number of boundaries.

% Problem definition.
fea.sdim  = { 'x' 'y' };                % Coordinate names.
if ( opt.iphys==1 )

  fea = addphys(fea,@convectiondiffusion);   % Add convection and diffusion physics mode.
  fea.phys.cd.sfun = { opt.sfun };           % Set shape function.
  fea.phys.cd.eqn.coef{2,4}   = { opt.cd };  % Set diffusion coefficient.
  fea.phys.cd.bdr.sel         = [1 1 1 1];
  fea.phys.cd.bdr.coef{1,end} = repmat({refsol},1,n_bdr);   % Set Dirichlet boundary coefficient to reference solution.
  fea = parsephys(fea);                 % Check and parse physics modes.

else

  fea.dvar  = { 'c' };                  % Dependent variable name.
  fea.sfun  = { opt.sfun  };            % Shape function.

  % Define equation system.
  fea.eqn.a.form = { [2 3;2 3] };       % First row indicates test function space   (2=x-derivative + 3=y-derivative),
                                        % second row indicates trial function space (2=x-derivative + 3=y-derivative).
  fea.eqn.a.coef = { opt.cd };          % Diffusion coefficient used in assembling stiffness matrix.

  fea.eqn.f.form = { 1 };               % Test function space to evaluate in right hand side (1=function values).
  fea.eqn.f.coef = { 0 };               % Coefficient used in right hand side.

  % Define boundary conditions.
  fea.bdr.d     = cell(1,n_bdr);
 [fea.bdr.d{:}] = deal(refsol);         % Assign reference solution to all boundaries (Dirichlet).

  fea.bdr.n     = cell(1,n_bdr);        % No Neumann boundaries ('fea.bdr.n' empty).

end

% Parse and solve problem.
fea       = parseprob(fea);             % Check and parse problem struct.
fea.sol.u = solvestat(fea,'fid',fid);   % Call to stationary solver.

% Postprocessing.
s_err = ['abs(',refsol,'-c)'];
if ( opt.iplot>0 )
  figure
  subplot(2,1,1)
  postplot(fea,'surfexpr','c')
  title('Solution c')
  subplot(2,1,2)
  postplot(fea,'surfexpr',s_err,'evalstyle','exact')
  title('Error')
end

% Error checking.
if ( size(fea.grid.c,1)==4 )
  xi = [0;0];
else
  xi = [1/3;1/3;1/3];
end
err = evalexpr0(s_err,xi,1,1:size(fea.grid.c,2),[],fea);
ref = evalexpr0('c',xi,1,1:size(fea.grid.c,2),[],fea);
err = sqrt(sum(err.^2)/sum(ref.^2));

if( ~isempty(fid) )
  fprintf(fid,'\nL2 Error: %f\n',err)
  fprintf(fid,'\n\n')
end

out.err  = err;
out.pass = out.err<0.01;
if ( nargout==0 )
  clear fea out
end


function [ t, wts ] = sgqf ( nt, aj, bj, zemu )

%*****************************************************************************80
%
%% SGQF computes knots and weights of a Gauss Quadrature formula.
%
%  Discussion:
%
%    This routine computes all the knots and weights of a Gauss quadrature
%    formula with simple knots from the Jacobi matrix and the zero-th
%    moment of the weight function, using the Golub-Welsch technique.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 2010
%
%  Author:
%
%    Original FORTRAN77 version by Sylvan Elhay, Jaroslav Kautsky.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Sylvan Elhay, Jaroslav Kautsky,
%    Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
%    Interpolatory Quadrature,
%    ACM Transactions on Mathematical Software,
%    Volume 13, Number 4, December 1987, pages 399-415.
%
%  Parameters:
%
%    Input, integer NT, the number of knots.
%
%    Input, real AJ(NT), the diagonal of the Jacobi matrix.
%
%    Input, real BJ(NT), the subdiagonal of the Jacobi
%    matrix, in entries 1 through NT-1.  On output, BJ has been overwritten.
%
%    Input, real ZEMU, the zero-th moment of the weight function.
%
%    Output, real T(NT), the knots.
%
%    Output, real WTS(NT), the weights.
%

%
%  Exit if the zero-th moment is not positive.
%
  if ( zemu <= 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SGQF - Fatal error!\n' );
    fprintf ( 1, '  ZEMU <= 0.\n' );
    error ( 'SGQF - Fatal error!' );
  end
%
%  Set up vectors for IMTQLX.
%
  wts = zeros ( nt, 1 );

  wts(1) = sqrt ( zemu );
  wts(2:nt) = 0.0;
%
%  Diagonalize the Jacobi matrix.
%
  [ t, wts ] = imtqlx ( nt, aj, bj, wts );

  wts(1:nt) = wts(1:nt).^2;

  return
end


function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION Compute cost and gradient for regularized linear
%regression with multiple variables
%   [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda) computes the
%   cost of using theta as the parameter for linear regression to fit the
%   data points in X and y. Returns the cost in J and the gradient in grad

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

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));
J = 1/(2*m)*sum((X*theta-y).^2)+lambda/(2*m)*(sum(theta.^2)-theta(1).^2);

grad = 1/m*X'*(X*theta-y)+lambda/m*theta;
grad(1) = grad(1) -lambda/m*theta(1);
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost and gradient of regularized linear
%               regression for a particular choice of theta.
%
%               You should set J to the cost and grad to the gradient.
%

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

grad = grad(:);

end


function value = u_integral ( e )

%*****************************************************************************80
%
%% U_INTEGRAL: integral ( -1 <= x <= +1 ) x^e sqrt ( 1 - x^2 ) dx.
%
%  Discussion:
%
%     E    U_INTEGRAL
%    --    --------------
%     0         pi /    2
%     2         pi /    8
%     4         pi /   16
%     6     5 * pi /  128
%     8     7 * pi /  256
%    10    21 * pi / 1024
%    12    33 * pi / 2048
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 April 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer E, the exponent of X.
%    0 <= E.
%
%    Output, real VALUE, the value of the integral.
%
  if ( mod ( e, 2 ) == 1 )

    value = 0.0;

  else

    arg1 = 0.5 * ( 1 + e );
    arg2 = 2.0 + 0.5 * e;
    value = 0.5 * sqrt ( pi ) * gamma ( arg1 ) / gamma ( arg2 );

  end

  return
end


function v=scatterquad2(x,y,z)
% SCATTERQUAD2 - calculates the volume under a surface defined by scattered points
%
% Usage:
%   v = scatterquad2(x,y,z)
%
% Inputs:
%   X,Y,Z are vectors of equal size specifying the coordinates of the points
%   defining the surface.  Z can also be a scalar or a function handle accepting
%   two inputs.
%
% Outputs:
%   V is the volume under the surface defined by linear interpolation of Z on
%   the Delaunay triangulation of the points (X(i),Y(i)), assuming that z=0
%   outside the convex hull of the points (X(i),Y(i)).
%
% Method:
%   The linear interpolation is a linear combination of basis functions of the
%   form z=t if (x,y) is in triangle T such that
%     (x,y)=r*(u1,v1)+s*(u2,v2)+t*(u3,v3)  where r+s+t=1 (all non-negative) and
%   (u,v) are the vertices of T, or z=0 otherwise.  The integral of z is
%   (1/3)*Area(T) where the area of T is determined by the cross product of two
%   edge vectors.
%
% Examples:
%   load seamount
%   scatterquad2(x,y,z-min(z)) % returns 190.7996
%   inR = (x>=211.1 & x<=211.4 & y>=-48.35 & y<=-48);
%   scatterquad2(x,y,(z-min(z)).*inR) % returns 142.3083
%   scatterquad2(x,y,1) % returns 0.2696
%
% For functions that can be evaluated at arbitrary points, use DBLQUAD or
% QUAD2D.  For regular grids, use TRAPZ twice.

if nargin<3
  error('scatterquad2:nargin','Expect 3 input arguments');
elseif ~isnumeric(x) || ~isnumeric(y)
  error('scatterquad2:xytype','Inputs X and Y must be numeric');
elseif ~isequal(numel(x),numel(y))
  error('scatterquad2:xysize','Inputs X and Y must have same number of elements');
elseif numel(x)<3
  error('scatterquad2:xsize','Inputs X and Y must have at least 3 elements');
elseif ~isnumeric(z)
  if isa(z,'function_handle')
    try
      z=z(x,y);
      if ~isnumeric(z)
        error('scatterquad2:zftype','Input Z failed to return a numeric array');
      end;
    catch ME
      error('scatterquad2:zfeval','Input Z failed to evaluate at (X,Y)');
    end;
  else
    error('scatterquad2:ztype','Input Z must be numeric or a function handle');
  end;
end;

if ~isequal(numel(z),numel(x))
  if numel(z)==1
    z=repmat(z,numel(x),1);
  else
    error('scatterquad2:zsize','Input Z must be scalar or the same size as X and Y');
  end;
end;

DT=DelaunayTri(x,y);
i=DT(:,1);
j=DT(:,2);
k=DT(:,3);
A=abs((x(j)-x(i)).*(y(k)-y(i))-(y(j)-y(i)).*(x(k)-x(i)))/2; % area of triangles
v=sum((z(i)+z(j)+z(k)).*A)/3;

end % main function scatterquad2(...)


function [ p, Fstat, df1, df2 ] = ftest(n,np1,np2,chi1,chi2)
% [ p ] = ftest(n,np1,np2,chi1,chi2)
% function to test whether addition of model parameters to
%     fit data is warranted by level of misfit improvement
%
% Inputs
% n = # of data
% np1, np2 = number of free parameters for each fit.
% chi1 & chi2 = sum of squares of misfits for two models.
%     must be positive values
%     normalization of chis by n not required
%     (normalization divides out in Fstatistic)
%
% Outputs
% p = probability (between 0 - 1) that improvement to fit from
%     addition of parameters is due to chance. I.e.,
%     0 means certainty that extra parameters are warranted
%     1 means improvement undoubtedly attributable to chance
% If desired, will also return F-statistic (Fstat) and
%     degrees of freedom (df1, df2) for f-distribution
%
% Written by James Conder, Southern Illinois University, Oct. 2010
% Citation:
%     Anderson, K.B. & Conder, J.A., Discussion of Multicyclic Hubbert
% Modeling as a Method for Forecasting Future Petroleum Production,
% Energy & Fuels, dx.doi.org/10.1021/ef1012648, 2011
%
% Update June, 2011
%   Check added for df1=1 (giving -Inf). Use MatrixLabs approximation
%   for f when df1=1. Accuracy ok, but some small differences against
%   fcdf
%
% Update May 31, 2012
%   Allow Fstat, df1, & df2 as outputs.
%   Use fcdf from matlab statistics toolbox if available (fast)
%   Some cosmetic clean up
%
% Comments & questions should be directed to conder@siu.edu
%----------------------

%%% check ordering. np2 should be > np1 and chi2 should be < chi1
% i.e., second model should have more parameters and better fit
if np2 == np1
    disp('number of model parameters are the same in both cases!')
    p = 1;
    return
elseif np2 < np1        % np1 should be less than np2. If not, just swap.
    nptemp = np1; np1 = np2; np2 = nptemp;
    chitemp = chi1; chi1 = chi2; chi2 = chitemp;
end

if chi2 >= chi1
    disp('misfit higher for model with more parameters!')
    p = 1;
    return
end

%%% number of degrees of freedom for f-distribution
df1 = np2 - np1;		% number of degrees of freedom
df2 = n - np2 - 1;

%%% F-statistic
Fstat = df2*(chi1 - chi2)/(df1*chi2);

%%% find p by determination of cumulative f-distribution at Fstat
% first check if fcdf from matlab statistics toolbox is present (fast).
% if not, numerically integrate f-distribution.
% cdff is equivalent to result from fcdf in Matlab statistics package.

if exist('fcdf.m','file') == 2       % check for availability of fcdf from statistics toolbox
    p = 1 - fcdf(Fstat,df1,df2);
else
    if df1 ~= 1         % numerically integrate f-distribution
        ifpt = 1000001; % large number of slices for accurate numerical integration
        dx = Fstat/(ifpt-1);
        x = 0:dx:1.2*Fstat;

        fnumgam = gammaln((df1+df2)/2);		% gamma func factors can be very large, use ln
        fdengam = gammaln(df1/2) + gammaln(df2/2);
        fgam = exp(fnumgam - fdengam);

        fnum = fgam*((df1/df2)^(df1/2)).*(x.^(0.5*df1 -1));
        fden = ((1 + df1*x/df2).^(0.5*(df1+df2)));
        f = fnum./fden;	% f distribution for df1, df2
        %fF = f(ifpt);		% f at Fstat

        cdff = cumsum(f)*dx;	% numerical integration of f distribution
        p = 1 - cdff(ifpt);
    else    % when df1=1 use F-dist approximation from MatrixLabs to avoid -Inf
        if Fstat <= 0.5    % Compute using inverse for small F-values
            s = df2;
            t = df1;
            z = 1/Fstat;
        else
            s = df1;
            t = df2;
            z = Fstat;
        end
        j = 2/(9*s);
        k = 2/(9*t);

        % Use approximation formulas
        y = abs((1 - k)*z^(1/3) - 1 + j)/sqrt(k*z^(2/3) + j);
        if t < 4
            y = y*(1 + 0.08*y^4/t^3);
        end

        a1 = 0.196854;
        a2 = 0.115194;
        a3 = 0.000344;
        a4 = 0.019527;
        p = 0.5/(1 + y*(a1 + y*(a2 + y*(a3 + y*a4))))^4;

        % Adjust if inverse was computed
        if Fstat <= 0.5
            p = 1 - p;
        end
     end
end

end


function K = besselk_correlation ( s, t )

%*****************************************************************************80
%
%% BESSELK_CORRELATION evaluates the Bessel K correlation function.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 June 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real S(*), T(*), pairs of argument values.
%
%    Output, real K(*), the correlation function values
%
  K = ones ( size ( s ) );

  i = find ( s ~= t );
  K(i) = abs ( s(i) - t(i) ) .* besselk ( 1, abs ( s(i) - t(i) ) );

  return
end


function [outputs] = ml_clustering(X,options,varargin)
%ML_CLUSTERING Applies clustering technique to the data
%
%   input -----------------------------------------------------------------
%
%       o X : (N x D), a data set with N samples each being of dimension D.
%
%       o options : structure
%
%               options.method_name  = 'kmeans' : this options should be given
%
%  output ----------------------------------------------------------------
%
%

%% Default options

outputs = [];
K       = 1;  % default number of clusters is assumed to be 1.
kernel  = 'gauss';
kpar    = 1;

%% Check input

if ~isfield(options,'method_name'),  error('field of method_name of structure options was not defined!'); end
if isfield(options,'K'),             K = options.K;end
if isfield(options,'kernel')         [kernel, kpar] = sanitise_kernel_input(options);end

switch options.method_name

    case 'kmeans'

        if isempty(varargin)
            [idx, centroids]    = kmeans(X, K);
        else
            [idx, centroids]    = kmeans(X, K,varargin{:});
        end

        pnames                  =  {   'distance'  'start' 'replicates' 'emptyaction' 'onlinephase' 'options' 'maxiter' 'display'};
        dflts                   =  {'sqeuclidean' 'plus'          []  'singleton'         'on'        []        []        []};
        distance                =  internal.stats.parseArgs(pnames, dflts, varargin{:});
        distNames               = {'sqeuclidean','cityblock','cosine','correlation','hamming'};
        distance                =  internal.stats.getParamVal(distance,distNames,'''Distance''');

        outputs.distance        = distance;
        outputs.K               = K;
        outputs.method_name     = 'kmeans';
        outputs.labels          = idx;
        outputs.centroids       = centroids;

    case 'kernel-kmeans'

        % Old implementation, not working properly
%        Kn                       = gram(X, X, kernel,kpar(1),kpar(2));
%        [idx,centroids,eigens]   = kernelkmeans(Kn, K);
%        outputs.K               = K;
%        outputs.method_name     = 'kernel-kmeans';
%        outputs.labels          = idx;
%        outputs.centroids       = centroids;
%        outputs.eigens          = eigens;
%        outputs.kernel          = kernel;
%        outputs.kpar            = kpar;

       % New implementation, working! But no decision boundaries or
       % isolines .. not yet at least
       [M, ~] = size(X);
       init = ceil(K*rand(1,M));
       % Using new implementation
       if strcmp(kernel,'gauss')
            % Gaussian Kernel
            [y,model,mse] = knKmeans(X',init,@knGauss, kpar(1));
       elseif strcmp(kernel,'poly')
            % Gaussian Kernel
            [y,model,mse] = knKmeans(X',init,@knPoly, kpar(2), kpar(1));
       end
       outputs.K               = K;
       outputs.eigens          = model.eigens;
       outputs.lambda          = diag(model.lambda);
       outputs.centroids       = model.centroids;
       outputs.method_name     = 'kernel-kmeans';
       outputs.mse             = mse;
       outputs.labels          = y;
       outputs.kernel          = kernel;
       outputs.kpar            = kpar;

end


function [A,B,h,k,phi]=polyEllipsForm2ScalRotTrans(coeffs)
%%POLYELLIPSFORM2SCALROTTRANS Given a 2D ellipse represented as a quadratic
%   polynomial such that f(x,y)=0 is points on the ellipse, this function
%   obtains the parameterization for a parameteric representation of the
%   points in terms of scale factors (A, and B), a rotation angle (phi) and
%   translation coordinates (h, and k). Thus, if t is a parameteric
%   parameter that runs from 0 to 2*pi, x and y coordinates of points on
%   the ellipse are given by
%   x=A*cos(phi)*cos(t)-B*sin(phi)*sin(t)+h;
%   y=A*sin(phi)*cos(t)+B*cos(phi)*sin(t)+k;
%
%INPUTS: coeffs A 3X3 matrix of the coefficients for the bivariate
%               quadratic polynomial. These are arranged such
%               that coeffs(a1,a2) corresponds to the coefficient
%               of an x1^(a1-1)*x2^(a2-1) term. This is the format used in
%               polyValMultiDim.
%
%OUTPUTS: A, B The scalar positive scale factors.
%         h, k The scalar offsets in the x and y coordinates.
%          phi The scalar rotation angle in radians.
%
%The relations here come from inverting Equation 5 in [1]. Using the
%notation of [1], we note that we can write BB=(1/A2-1/B2)*sin(2*phi)
%and also AA-CC==(1/A^2-1/B^2)*cos(2*phi), so we use an inverse transgent to
%find phi. After that, the other terms are found by substituting and
%solving each of the equations. In the final equation for FF, we repalce
%the 1 with a c that we solve for. That is a scale factor (since one can
%multiply coeffs by any constant without changing the result). Given the
%scale factor, we then replace A with A/sqrt(c) and B with B/sqrt(c) to
%undo the scaling.
%
%EXAMPLE:
%To show that this produces correct results, we plot an ellipse using the
%drawEllipse function, which uses a different parameterization. We then
%convert that parameterization into polynomial coefficients using
%quadEllipsForm2Poly. Those coefficients are then transformed into the
%parameters for the scaled, rotated, and translated parametric form of
%this function. Being in parametric form, we plot the ellipse over the
%other one. One can see that they are the same.
% A=inv([4, -1.5;
%       -1.5,1]);
% x0=[2;3]*10;
% c=2.5;
% %Plot the original ellipse
% figure(1)
% clf
% drawEllipse(x0,A,c,'-k','linewidth',4)
% hold on
% %Convert the ellipse into polynomial form.
% coeffs=quadEllipsForm2Poly(A,x0,c)/1000;
% %Convert the polynomial form into the scaled, rotated, translated form.
% [A,B,h,k,phi]=polyEllipsForm2ScalRotTrans(coeffs);
% %This is a parameteric form, so plot the points on the ellipse:
% numPoints=500;
% t=linspace(0,2*pi,numPoints);
% x=A*cos(phi)*cos(t)-B*sin(phi)*sin(t)+h;
% y=A*sin(phi)*cos(t)+B*cos(phi)*sin(t)+k;
% plot(x,y,'-y','linewidth',1)
% legend('Original Ellipse','Parametric Ellipse')
% xlabel('x')
% ylabel('y')
%
%REFERENCES:
%[1] G. B. Hughes and M. Chraibi, "Calculating ellipse overlap areas,"
%    Computing and Visualization in Science, vol. 15, no. 5, pp. 291-301,
%    Oct. 2012.
%
%January 2023 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

AA=coeffs(3,1);
BB=coeffs(2,2);
CC=coeffs(1,3);
DD=coeffs(2,1);
EE=coeffs(1,2);
FF=coeffs(1,1);

phi=atan2(BB,AA-CC)/2;
sinPhi=sin(phi);
cosPhi=cos(phi);
%Using a double angle identity:
cos2Phi=cosPhi^2-sinPhi^2;

A2=2*cos2Phi/(AA-CC+(AA+CC)*cos2Phi);
B2=2*cos2Phi/(CC-AA+(AA+CC)*cos2Phi);

h=(1/2)*(-A2*DD+(B2-A2)*cosPhi*EE*sinPhi+(A2-B2)*DD*sinPhi^2);
k=(1/2)*(-B2*EE+(B2-A2)*cosPhi*DD*sinPhi-(A2-B2)*EE*sinPhi^2);

c=(h*cosPhi+k*sinPhi)^2/A2+(h*sinPhi-k*cosPhi)^2/B2-FF;

%Adjust the scaling of everything.
A2=A2*c;
B2=B2*c;

A=sqrt(A2);
B=sqrt(B2);

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 y = amexpo1s(N,t0,T);
%AMEXPO1S Generate one-sided exponential amplitude modulation.
%	Y = AMEXPO1S(N,T0,T) generates a one-sided exponential
%	amplitude modulation centered on a time T0, and with a
%	spread proportional to T.
%	This modulation is scaled such that Y(T0)=1.
%
%	N  : number of points.
%	T0 : arrival time of the exponential	(default : N/2).
%	T  : time spreading			(default : 2*sqrt(N)).
%	Y  : signal.
%
%	Examples:
%	 z=amexpo1s(160);plot(z);
%	 z=amexpo1s(160,20,40);plot(z);
%
%	See also AMEXPO2S, AMGAUSS, AMRECT, AMTRIANG.

% 	F. Auger, July 1995.
%	Copyright (c) 1996 by CNRS (France).
%
%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2 of the License, or
%  (at your option) any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; if not, write to the Free Software
%  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

if (nargin == 0),
 error ( 'The number of parameters must be at least 1.' );
elseif (nargin == 1),
 t0=N/2; T=2*sqrt(N);
elseif (nargin ==2),
 T=2*sqrt(N);
end;

if (N<=0),
 error('N must be greater or equal to 1.');
else
 tmt0=(1:N)'-t0;
 y = exp(-sqrt(pi)*tmt0/T).*(tmt0>=0.0);
end;


function p=t2p(t,n,df,units)
% t2p - get p-value from t-statistical values
% p=t2p(t,n,df,units);
%  t     = t-statistical values
%  n     = number of comparisons for Bonferroni correction [1]
%  df    = degrees of freedom [Inf]
%  units = 'p', 'log10p' [p]

% 08/2005 SOD: created it.

% input checks and defaults
if ~exist('t','var') || isempty(t),   error('Need t');   end
if ~exist('n','var') || isempty(n),   n = 1;             end
if ~exist('df','var') || isempty(df), df = Inf;          end
if ~exist('units','var') || isempty(units), units = 'p'; end

% preserve the sign of t in p values
tsign = sign(t);
tsign(tsign==0)=1;
t = abs(t);

% Find the upper tail probs of the two-tailed t-distribution:
if df==Inf,
  p=0.5*erfc(t/sqrt(2));
else
  p=0.5*betainc(df./(df+t.^2),df/2,0.5);
end;

% Bonferroni
p=(n+1).*p;
p(p>1)=1; % otherwise log10p is funny

% convert
switch units
 case 'log10p',
  p(p==0) = 10^-50; % remove 0
  p       = -log10(abs(p)) .* tsign;
 case 'p',
  % preserve the sign of t in p values
  p = p.*tsign;
 otherwise,
  disp(sprintf('Unknown unit: %s',units));
end;

return;


% the following program calculates the
% Colebrool-White friction factors at various
% roughess heights for Reynolds numbers
% between 5000 and 500000
% ---------------------------------------------------------------
%  The MATLAB function was created by Tibor Balint, December 1998
% TBoreal Research Corporation, Toronto, Ont. Canada
% (tibor@netcom.ca) and also, University of Warwick, UK
% ---------------------------------------------------------------

clear
Re=linspace(5000,500000,200); % set the Reynolds numbers
Dh=0.008;  % set the hydraulic diameter in meters

rough=0.00000075;  % set the 1st EQUIVALENT ROUGHNESS HEIGHT in m

for i=1:200
   miller(i)=0.25/(log10(rough/(3.7*0.009)+5.74/Re(i)^0.9))^2;
   fcw(i)=ffcw(Re(i), Dh, rough);
end

rough=0.000001;  % EQUIVALENT ROUGHNESS HEIGHT
for i=1:200
%   miller1(i)=0.25/(log10(rough/(3.7*0.009)+5.74/Re(i)^0.9))^2;
   fcw1(i)=ffcw(Re(i), Dh, rough);
end

rough=0.00000125;  % EQUIVALENT ROUGHNESS HEIGHT
for i=1:200
%   miller2(i)=0.25/(log10(rough/(3.7*0.009)+5.74/Re(i)^0.9))^2;
   fcw2(i)=ffcw(Re(i), Dh, rough);
end

rough=0.0000015;  % EQUIVALENT ROUGHNESS HEIGHT
for i=1:200
%   miller3(i)=0.25/(log10(rough/(3.7*0.009)+5.74/Re(i)^0.9))^2;
   fcw3(i)=ffcw(Re(i), Dh, rough);
end

rough=0.00000175;  % EQUIVALENT ROUGHNESS HEIGHT
for i=1:200
%   miller4(i)=0.25/(log10(rough/(3.7*0.009)+5.74/Re(i)^0.9))^2;
   fcw4(i)=ffcw(Re(i), Dh, rough);
end

%plot the figures
figure(1)
orient landscape;
subplot(2,1,1);
plot(Re,fcw,'b',Re,miller,'r--')
legend('f_{cw}','f_{miller}');
grid on;
axis tight;
xlabel('Reynolds number');
ylabel('Friction factor');
title ('Hydraulic Diameter (D_h=8 mm), Eq. Roughness Height (\epsilon = 0.75 \mum)');

subplot(2,1,2);
plot(Re,fcw,'b',Re,fcw1,'r',Re,fcw2,'g',Re,fcw3,'m',Re,fcw4,'k')
legend('\epsilon=0.75 \mum','\epsilon=1.00 \mum','\epsilon=1.25 \mum','\epsilon=1.50 \mum','\epsilon=1.75 \mum');
grid on;
axis tight;
xlabel('Reynolds number');
ylabel('Friction factor');
title ('Colebrook-White Friction Factor (f_{cw})');


function [ price ] = Analytical_Price_Equity_Swap_Cap_ConstRate(r, M, dt, contract_param, sigma )
% Price the equity swap and cap/floor under constant interest rate assumptino

contract_type = contract_param.contract_type; % 1 = swap, 2 = cap/floor
K = contract_param.K;
c = contract_param.c;
T = dt*M;

gamma = (1 + r*dt + c);
mult = (1 - exp(-r*T))/(exp(r*dt) - 1);

if contract_type == 1  % Swap
    price = K*(exp(r*dt) - gamma)*mult;

elseif contract_type == 2  % cap/floor

    C = contract_param.C; % cap
    F = contract_param.F; % floor

    mu = (r - sigma*sigma/2)*dt;
    sigdt = sigma*sqrt(dt);
    a = (log(max(0, F + gamma)) - mu)/sigdt;
    b = (log(C + gamma) - mu)/sigdt;
    t1 = normcdf(b - sigdt) - normcdf(a - sigdt);
    t2 = normcdf(b) - normcdf(a);
    H = F*normcdf(a) + exp(r*dt)*t1 - gamma*t2 + C*(1-normcdf(b));
    price = K*H*mult;
else
    price = -123456789;
end

end


function y = tanhminus1(x)
%TANHMINUS1 Hyperbolic tangent minus one.
%
%   TANHMINUS1(X) is TANH(X)-1 calculated in a way that is numerically better
%   when X is large and positive.
%
%   This example illustrates the difference
%
%      x = 17.5:0.01:20.5;
%      plot(x, tanh(x)-1, 'y-', x, tanhminus1(x), 'r-');

%   Author:      Peter J. Acklam
%   Time-stamp:  2003-10-13 15:04:13 +0200
%   E-mail:      pjacklam@online.no
%   URL:         http://home.online.no/~pjacklam

   % check number of input arguments
   error(nargchk(1, 1, nargin));

   y = -2 ./ (1 + exp(2 * x));


function mean = normal_ms_mean ( mu, sigma )

%*****************************************************************************80
%
%% NORMAL_MS_MEAN returns the mean of the Normal PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real MU, SIGMA, the parameters of the PDF.
%    0.0 < SIGMA.
%
%    Output, real MEAN, the mean of the PDF.
%
  mean = mu;

  return
end


function mean = pareto_mean ( a, b )

%*****************************************************************************80
%
%% PARETO_MEAN returns the mean of the Pareto PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 September 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the parameters of the PDF.
%    0.0 < A,
%    0.0 < B.
%
%    Output, real MEAN, the mean of the PDF.
%
  if ( b <= 1.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PARETO_MEAN - Fatal error!\n' );
    fprintf ( 1, '  For B <= 1, the mean does not exist.\n' );
    mean = 0.0;
    return
  end

  mean = b * a / ( b - 1.0 );

  return
end


function x = r8vec_cheby1space ( n, a, b )

%*****************************************************************************80
%
%% R8VEC_CHEBY1SPACE creates a vector of Type 1 Chebyshev spaced values in [A,B].
%
%  Discussion:
%
%    An R8VEC is a vector of R8's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 August 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, real A, B, the first and last entries.
%
%    Output, real X(N,1), a vector of Chebyshev spaced data.
%
  x = zeros ( n, 1 );

  if ( n == 1 )

    x(1) = ( a + b ) / 2.0;

  else

    for i = 1 : n

      theta = ( 2 * ( n - i ) + 1 ) * pi / ( 2 * n );

      c = cos ( theta );

      if ( mod ( n, 2 ) == 1 )
        if ( 2 * i - 1 == n )
          c = 0.0;
        end
      end

      x(i) = ( ( 1.0 - c ) * a  ...
             + ( 1.0 + c ) * b ) ...
             /   2.0;

    end

  end

  return
end


function f = ecc2flat(e)
%ECC2FLAT   Convert the eccentricity of an ellipsoid to its flattening
%
%  F = ECC2FLAT(E) returns the flattening given the eccentricity.
%
%   See also FLAT2ECC.

  e2 = e.^2;
  f = e2 ./ (1 + sqrt(1 - e2));
end


%MDS_STRESS - Sammon stress between dissimilarity matrices
%
% 	E = MDS_STRESS(Q,DS,D)
%
% INPUT
% 	Q					Indicator of the Sammon stress; Q = -2,-1,0,1,2
% 	DS				Original distance matrix
% 	D 				Approximated distance matrix
%
% OUTPUT
% 	E 				Sammon stress
%
% DESCRIPTION
% Computes the Sammon stress between the original distance matrix Ds
% and the approximated distance matrix D, expressed as follows:
%
%  E = 1/(sum_{i<j} DS_{ij}^(q+2)) sum_{i<j} (DS_{ij} - D_{ij})^2 * DS_{ij}^q
%

%
% Copyright: Elzbieta Pekalska, Robert P.W. Duin, ela@ph.tn.tudelft.nl, 2000-2003
% Faculty of Applied Sciences, Delft University of Technology
%

function [e,alpha] = mds_stress (q,Ds,D,isratio)

	if nargin < 4
		isratio = 0;
	end

	[m,k]   = size(Ds);
	if any(size(D) ~= size(Ds)),
		error ('The sizes of matrices do not match.');
	end
	mk = m*k;

	D  = +D;
	Ds = +Ds;

	% I is  the index of non-zero (> eps) values to be included
	% for the computation of the stress

	I = 1:mk;
	nanindex = find(isnan(Ds(:)) | isnan(D(:)));
	if ~isempty(nanindex),
		I(nanindex) = [];
	end
	O = [];
	if m == k & (length(intersect(find(D(:) < eps), 1:m+1:(mk))) == m),
		O  = 1:m+1:mk;
		Ds(O) = 1;
		D (O) = 1;
    mm = m - 1;
	else
		mm = k;
	end

  if isratio,
    II = setdiff(I,O);
    alpha = sum((Ds(II).^q).*D(II).^2)/sum((Ds(II).^(q+1)).*D(II));
    Ds = alpha*Ds;
	else
		alpha = 1;
	end

	c = sum(Ds(I).^(q+2)) - length(O);
	if q ~= 0,
		e = sum(Ds(I).^q .* ((Ds(I)-D(I)).^2))/c;
	else
		e = sum(((Ds(I)-D(I)).^2))/c;
	end
return;


function v = polynomialCurveDerivative(t, varargin)
%POLYNOMIALCURVEDERIVATIVE Compute derivative vector of a polynomial curve
%
%   VECT = polynomialCurveLength(T, XCOEF, YCOEF);
%   XCOEF and YCOEF are row vectors of coefficients, in the form:
%       [a0 a1 a2 ... an]
%   VECT is a 1x2 array containing direction of derivative of polynomial
%   curve, computed for position T. If T is a vector, VECT has as many rows
%   as the length of T.
%
%   VECT = polynomialCurveLength(T, COEFS);
%   COEFS is either a 2xN matrix (one row for the coefficients of each
%   coordinate), or a cell array.
%
%   Example
%   polynomialCurveDerivative
%
%   See also
%   polynomialCurves2d, polynomialCurveNormal, polynomialCurvePoint,
%   polynomialCurveCurvature
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2007-02-23
% Copyright 2007 INRA - BIA PV Nantes - MIAJ Jouy-en-Josas.

%% Extract input parameters

% polynomial coefficients for each coordinate
var = varargin{1};
if iscell(var)
    xCoef = var{1};
    yCoef = var{2};
elseif size(var, 1)==1
    xCoef = varargin{1};
    yCoef = varargin{2};
else
    xCoef = var(1,:);
    yCoef = var(2,:);
end

%% compute derivative

% compute derivative of the polynomial
dx = polynomialDerivate(xCoef);
dy = polynomialDerivate(yCoef);

% convert to polyval convention
dx = dx(end:-1:1);
dy = dy(end:-1:1);

% numerical integration of the Jacobian of parametrized curve
v = [polyval(dx, t) polyval(dy, t)];


%% Machine Learning Online Class - Exercise 2: Logistic Regression
%
%  Instructions
%  ------------
%
%  This file contains code that helps you get started on the second part
%  of the exercise which covers regularization with logistic regression.
%
%  You will need to complete the following functions in this exericse:
%
%     sigmoid.m
%     costFunction.m
%     predict.m
%     costFunctionReg.m
%
%  For this exercise, you will not need to change any code in this file,
%  or any other files other than those mentioned above.
%

%% Initialization
clear ; close all; clc

%% Load Data
%  The first two columns contains the X values and the third column
%  contains the label (y).

data = load('ex2data2.txt');
X = data(:, [1, 2]); y = data(:, 3);

plotData(X, y);

% Put some labels
hold on;

% Labels and Legend
xlabel('Microchip Test 1')
ylabel('Microchip Test 2')

% Specified in plot order
legend('y = 1', 'y = 0')
hold off;

%% =========== Part 1: Regularized Logistic Regression ============
%  In this part, you are given a dataset with data points that are not
%  linearly separable. However, you would still like to use logistic
%  regression to classify the data points.
%
%  To do so, you introduce more features to use -- in particular, you add
%  polynomial features to our data matrix (similar to polynomial
%  regression).
%

% Add Polynomial Features

% Note that mapFeature also adds a column of ones for us, so the intercept
% term is handled
X = mapFeature(X(:,1), X(:,2));

% Initialize fitting parameters
initial_theta = zeros(size(X, 2), 1);

% Set regularization parameter lambda to 1
lambda = 1;

% Compute and display initial cost and gradient for regularized logistic
% regression
[cost, grad] = costFunctionReg(initial_theta, X, y, lambda);

fprintf('Cost at initial theta (zeros): %f\n', cost);

fprintf('\nProgram paused. Press enter to continue.\n');
pause;

%% ============= Part 2: Regularization and Accuracies =============
%  Optional Exercise:
%  In this part, you will get to try different values of lambda and
%  see how regularization affects the decision coundart
%
%  Try the following values of lambda (0, 1, 10, 100).
%
%  How does the decision boundary change when you vary lambda? How does
%  the training set accuracy vary?
%

% Initialize fitting parameters
initial_theta = zeros(size(X, 2), 1);

% Set regularization parameter lambda to 1 (you should vary this)
lambda = 0;

% Set Options
options = optimset('GradObj', 'on', 'MaxIter', 400);

% Optimize
[theta, J, exit_flag] = ...
	fminunc(@(t)(costFunctionReg(t, X, y, lambda)), initial_theta, options);

% Plot Boundary
plotDecisionBoundary(theta, X, y);
hold on;
title(sprintf('lambda = %g', lambda))

% Labels and Legend
xlabel('Microchip Test 1')
ylabel('Microchip Test 2')

legend('y = 1', 'y = 0', 'Decision boundary')
hold off;

% Compute accuracy on our training set
p = predict(theta, X);

fprintf('Train Accuracy: %f\n', mean(double(p == y)) * 100);


function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION Compute cost and gradient for regularized linear
%regression with multiple variables
%   [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda) computes the
%   cost of using theta as the parameter for linear regression to fit the
%   data points in X and y. Returns the cost in J and the gradient in grad

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

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost and gradient of regularized linear
%               regression for a particular choice of theta.
%
%               You should set J to the cost and grad to the gradient.
%

h_theta = X*theta;
J = (1/(2*m))*sum((h_theta - y).^2) + (lambda/(2*m))*(theta(2:end)'*theta(2:end));
grad = (1/m)*((h_theta - y)'*X)'
grad = grad + (lambda/m)*[0;theta(2:end,:)]

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

grad = grad(:);

end


%
% lellipe(phi, k, errtol)
%
% Inputs:
%
%   phi     Input angle vector size 1xN.
%   k       Input parameter vector size 1 or 1xN.
%   errtol  Error tolerance for Carlson's algorithms.
%
% Matlab function to compute Legendre's (incomplete) elliptic integral
% E(phi, k).  Uses a vectorized implementation of Carlson's Duplication Algorithms
% for symmetric elliptic integrals as found in "Computing Elliptic
% Integrals by Duplication," by B. C. Carlson, Numer. Math. 33, 1-16 (1979)
% and also found in ACM TOMS Algorithm 577.  Section 4 in the paper cited
% here describes how to convert between the symmetric elliptic integrals
% and Legendre's elliptic integrals.
%
% Returns NaN's for any argument values outside input range.
%

function f = lellipe(phi, k, errtol)

% Argument checking for vectorization:
lphi = length(phi);
lk = length(k);
errflag = logical(0);
if (lphi ~= lk)
    if (lphi==1)
        phivec = phi * ones(1,lk);
        kvec = k;
    elseif (lk==1)
        kvec = k * ones(1,lphi);
        phivec = phi;
    else
        disp('Incompatible input vector dimensions in lellipf!');
        errflag = logical(1);
    end
else
    phivec = phi;
    kvec = k;
end

if (~errflag)
    snphi = sin(phivec);
    csphi = cos(phivec);
    snphi2 = snphi.^2;
    csphi2 = csphi.^2;
    k2 = kvec.^2;
    y = 1.0 - k2.*snphi2;
    onesvec = ones(1,length(phivec));
    f = snphi .* rf(csphi2,  y, onesvec, errtol) - ...
        k2 .* snphi .* snphi2 .* rd(csphi2, y, onesvec, errtol)/3.0;
else
    f = NaN;
end


% NAME:
% test_RANSAC_line_02.m
%
% DESC:
% test to estimate the parameters of a line using real data

close all
clear
% clc

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
load LineData

% set RANSAC options
options.epsilon = 1e-6;
options.P_inlier = 0.99;
options.sigma = 1;
options.est_fun = @estimate_line;
options.man_fun = @error_line;
options.mode = 'MSAC';
options.Ps = [];
options.notify_iters = [];
options.min_iters = 100;
options.fix_seed = false;
options.reestimate = true;
options.stabilize = false;

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% RANSAC
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% run RANSAC
[results, options] = RANSAC(X, options);

%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Results Visualization
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure;
hold on
ind = results.CS;
plot(X(1, ind), X(2, ind), '.g')
plot(X(1, ~ind), X(2, ~ind), '.r')
xlabel('x')
ylabel('y')
title('RANSAC results for 2D line estimation')
legend('Inliers', 'Outliers')
axis equal tight


function [xm xcov] = UT(Xi, W)
%
%
[n, kmax] = size(Xi);

xm = 0;
for k=1:kmax
  xm = xm + W(k)*Xi(:, k);
end

xcov = zeros(n, n);
for k=1:kmax
  xcov = xcov + W(k)*(Xi(:, k) - xm)*(Xi(:, k) - xm)';
end
xcov = xcov;


function [AF, u, v, w] = arrayFactor(xPos, yPos, zPos, elementWeights, f, c, thetaScanAngles, phiScanAngles, thetaSteerAngle, phiSteerAngle)
%arrayFactor - Calculate array factor of 1D, 2D or 3D array
%
%This matlab function calculates the array factor of a 1D, 2D or 3D array based
%on the position of the elements/sensors and the weight associated with
%each sensor. If no angle is given as input, the scanning angle is theta
%from -90 to 90, and phi from 0 to 360 degrees with 1 degree resolution
%
%[AF, u, v, w] = arrayFactor(xPos, yPos, zPos, elementWeights, f, c, thetaScanAngles, phiScanAngles, thetaSteerAngle, phiSteerAngle)
%
%IN
%xPos            - 1xP vector of x-positions
%yPos            - 1xP vector of y-positions
%zPos            - 1xP vector of z-positions
%elementWeights  - 1xP vector of element weights
%f               - Wave frequency
%c               - Speed of sound
%thetaScanAngles - 1xM vector or MxN matrix of theta scanning angles in degrees (optional)
%phiScanAngles   - 1XN vector or MxN matrix of phi scanning angles in degrees (optional)
%thetaSteerAngle - Theta steering angle in degrees (optional)
%phiSteerAngle   - Phi steering angle in degrees (optional)
%
%OUT
%AF              - Calculated array factor
%u               - MxN matrix of u coordinates in UV space [sin(theta)*cos(phi)]
%v               - MxN matrix of v coordinates in UV space [sin(theta)*sin(phi)]
%w               - MxN matrix of w coordinates in UV space [cos(theta)]
%
%
%Created by J?rgen Grythe
%Last updated 2017-02-27

if ~isvector(xPos)
    error('X-positions of array elements must be a 1xP vector where P is number of elements')
end

if ~isvector(yPos)
    error('Y-positions of array elements must be a 1xP vector where P is number of elements')
end

if ~isvector(elementWeights)
    error('Weighting of array elements must be a 1xP vector where P is number of elements')
end

if ~isscalar(f)
    error('The input frequency must be a single value')
end

%theta is the elevation and is the normal incidence angle from -90 to 90
if ~exist('thetaScanAngles', 'var')
    thetaScanAngles = -pi/2:pi/180:pi/2;
else
    thetaScanAngles = thetaScanAngles*pi/180;
end

%phi is the azimuth, and is the angle in the XY-plane from 0 to 360
if ~exist('phiScanAngles', 'var')
    phiScanAngles = 0:pi/180:2*pi;
else
    phiScanAngles = phiScanAngles*pi/180;
end

%theta, phi steering angles
if ~exist('thetaSteerAngle', 'var')
    thetaSteerAngle = 0;
else
    thetaSteerAngle = thetaSteerAngle*pi/180;
end

if ~exist('phiSteerAngle', 'var')
    phiSteerAngle = 0;
else
    phiSteerAngle = phiSteerAngle*pi/180;
end

%Wavenumber
k = 2*pi*f/c;

%Number of elements/sensors in the array
P = length(xPos);

%Calculating wave vector in spherical coordinates
if isvector(thetaScanAngles)

    %Size of vectors containing theta and phi angles
    M = length(thetaScanAngles);
    N = length(phiScanAngles);

    %Calculate UV coordinates
    u = sin(thetaScanAngles)'*cos(phiScanAngles);
    v = sin(thetaScanAngles)'*sin(phiScanAngles);
    w = repmat(cos(thetaScanAngles)', 1, N);

    % Apply steering
    us = u - sin(thetaSteerAngle)*cos(phiSteerAngle);
    vs = v - sin(thetaSteerAngle)*sin(phiSteerAngle);
    ws = w - cos(thetaSteerAngle);
else

    %Size of matrix containing theta and phi angles
    [M, N] = size(thetaScanAngles);

    %Calculate UV coordinates
    u = sin(thetaScanAngles).*cos(phiScanAngles);
    v = sin(thetaScanAngles).*sin(phiScanAngles);
    w = cos(thetaScanAngles);

    % Apply steering
    us = u - sin(thetaSteerAngle).*cos(phiSteerAngle);
    vs = v - sin(thetaSteerAngle).*sin(phiSteerAngle);
    ws = w - cos(thetaSteerAngle);
end

%Calculate array factor
uu = bsxfun(@times, us, reshape(xPos, 1, 1, P));
vv = bsxfun(@times, vs, reshape(yPos, 1, 1, P));
ww = bsxfun(@times, ws, reshape(zPos, 1, 1, P));

g = repmat(reshape(elementWeights, 1, 1, P), M, N);

AF = sum(g.*exp(1j*k*(uu + vv + ww)), 3);

%Normalising
AF = abs(AF)./max(max(abs(AF)));

%
%                 N
%AF(theta, phi) = sum [ g_n * exp{jk(u*x_n + v*y_n + w*z_n)} ]
%                n=1
%
%u =
%|sin(theta_0)*cos(phi_0) sin(theta_0)*cos(phi_1) .. sin(theta_0)*cos(phi_N)|
%|sin(theta_1)*cos(phi_0) sin(theta_1)*cos(phi_1) .. sin(theta_1)*cos(phi_N)|
%|    .                           .                         .               |
%|sin(theta_M)*cos(phi_0) sin(theta_M)*cos(phi_1) .. sin(theta_M)*cos(phi_N)|

%v =
%|sin(theta_0)*sin(phi_0) sin(theta_0)*sin(phi_1) .. sin(theta_0)*sin(phi_N)|
%|sin(theta_1)*sin(phi_0) sin(theta_1)*sin(phi_1) .. sin(theta_1)*sin(phi_N)|
%|    .                           .                         .               |
%|sin(theta_M)*sin(phi_0) sin(theta_M)*sin(phi_1) .. sin(theta_M)*sin(phi_N)|

%w =
%|cos(theta_0) cos(theta_0) .. cos(theta_0)|
%|cos(theta_1) cos(theta_1) .. cos(theta_1)|
%|    .            .                .      |
%|cos(theta_N) cos(theta_N) .. cos(theta_N)|

%uu =
%   --------
%  /       /|
% / xPos  / |
%---------  | M (length theta)
%|       |  |
%|   u   |  /
%|       | / P (# elements)
%---------/
%   N (length phi)

%g =
%   --------
%  / g_P   /|
% /       / |
%---------  | M
%|g1   g1|  |
%|   g1  |  /
%|g1   g1| / P (# elements)
%---------/
%   N


function x=choosenk(n,k)
%CHOOSENK All choices of K elements taken from 1:N [X]=(N,K)
% The output X is a matrix of size (N!/(K!*(N-K)!),K) where each row
% contains a choice of K elements taken from 1:N without duplications.
% The rows of X are in lexically sorted order.
%
% To choose from the elements of an arbitrary vector V use
% V(CHOOSENK(LENGTH(V),K)).

% CHOOSENK(N,K) is the same as the MATLAB5 function NCHOOSEK(1:N,K) but is
% much faster for large N and most values of K.

%   Copyright (c) 1998 Mike Brookes,  mike.brookes@ic.ac.uk
%      Version: $Id: choosenk.m,v 1.4 2007/05/04 07:01:38 dmb Exp $
%
%   VOICEBOX is a MATLAB toolbox for speech processing.
%   Home page: http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   This program is free software; you can redistribute it and/or modify
%   it under the terms of the GNU General Public License as published by
%   the Free Software Foundation; either version 2 of the License, or
%   (at your option) any later version.
%
%   This program is distributed in the hope that it will be useful,
%   but WITHOUT ANY WARRANTY; without even the implied warranty of
%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%   GNU General Public License for more details.
%
%   You can obtain a copy of the GNU General Public License from
%   http://www.gnu.org/copyleft/gpl.html or by writing to
%   Free Software Foundation, Inc.,675 Mass Ave, Cambridge, MA 02139, USA.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

kk=min(k,n-k);
if kk<2
   if kk<1
      if k==n
         x=1:n;
      else
         x=[];
      end
   else
      if k==1
         x=(1:n)';
      else
         x=1:n;
         x=reshape(x(ones(n-1,1),:),n,n-1);
      end
   end
else
   n1=n+1;
   m=prod(n1-kk:n)/prod(1:kk);
   x=zeros(m,k);
   f=n1-k;
   x(1:f,k)=(k:n)';
   for a=k-1:-1:1
      d=f;
      h=f;
      x(1:f,a)=a;
      for b=a+1:a+n-k
         d=d*(n1+a-b-k)/(n1-b);
         e=f+1;
         f=e+d-1;
         x(e:f,a)=b;
         x(e:f,a+1:k)=x(h-d+1:h,a+1:k);
      end
   end
end


function  [Itt,para]=color_transfer(Ic,It,ind)

[m1,n1,c]=size(Ic);
X=reshape(Ic,[m1*n1,c]);

[m2,n2,c]=size(It);
Y=reshape(It,[m2*n2,c]);

if nargin <3
   ind=[1:(m2*n2)]';
end

mu_x=mean(X);

S_x=(X-repmat(mu_x,[m1*n1,1]))'*(X-repmat(mu_x,[m1*n1,1]))/(m1*n1);
[Ux,Dx,~]=svd(S_x);
mu_y=mean(Y(ind,:));
S_y=(Y(ind,:)-repmat(mu_y,[size(ind,1),1]))'*(Y(ind,:)-repmat(mu_y,[size(ind,1),1]))/(size(ind,1));
[Uy,Dy,~]=svd(S_y);

A=Ux*diag(diag(Dx).^(0.5))*Ux'*Uy*diag(diag(Dy).^(-0.5))*Uy';
b=mu_x'-A*mu_y';

Z=A*Y'+repmat(b,[1,m2*n2]);
Z=Z';
para.A=A;
para.b=b;
%mu_z=mean(Z);
%S_z=(Z-repmat(mu_z,[m2*n2,1]))'*(Z-repmat(mu_z,[m2*n2,1]))/(m2*n2);
Itt=reshape(Z,[m2,n2,c]);
end


function [c,delta,cash] = BlackScholesCall(spot,K,r,vol,T)
% Black-Scholes price of a European call
% Inputs:
%   spot = spot price of underlying
%   K = strike of the call optioon
%   r = risk free rate as a fraction
%   vol = volatility of the underlying as a fraction
%   T = time to maturity in years
% Outputs:
%   c = price of European call(s)
%   delta = delta of the call(s)
%   cash = cash held in a replicating portfolio
%
d1 = (log(spot./K) + (r + vol.*vol/2).*T)./(vol.*sqrt(T));
d2 = d1 - vol.*sqrt(T);
delta = normcdf(d1);
cash =  -K.*exp(-r.*T).*normcdf(d2);
c = spot.*delta + cash;


function [y,g] = objfun(x)
y = 2*x(1)^2+2*x(2)^2-2*x(1)*x(2)-4*x(1)-6*x(2);
g = [4*x(1)-2*x(2)-4;4*x(2)-2*x(1)-6];


function g = sigmoidGradient(z)
%SIGMOIDGRADIENT returns the gradient of the sigmoid function
%evaluated at z
%   g = SIGMOIDGRADIENT(z) computes the gradient of the sigmoid function
%   evaluated at z. This should work regardless if z is a matrix or a
%   vector. In particular, if z is a vector or matrix, you should return
%   the gradient for each element.

g = zeros(size(z));
g = sigmoid(z) .* (1 - sigmoid(z));
% ====================== YOUR CODE HERE ======================
% Instructions: Compute the gradient of the sigmoid function evaluated at
%               each value of z (z can be a matrix, vector or scalar).

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

end


function M = nfchoa_order(nls,conf)
%NFCHOA_ORDER maximum order of spatial band-limited NFC-HOA
%
%   Usage: M = nfchoa_order(nls,conf)
%
%   Input parameters:
%       nls     - number of secondary sources
%
%   Output parameters:
%       M       - spherical harmonics order
%       conf    - configuration struct (see SFS_config)
%
%   NFCHOA_ORDER(nls,conf) returns the maximum order of spherical harmonics for
%   the given number of secondary sources in order to avoid spectral repetitions
%   (spatial aliasing) of the dirving signals. The order is
%
%        / nls/2 - 1,   even nls
%   M = <
%        \ (nls-1)/2    odd nls
%
%   for a circular array and
%         _____
%   M = \|nls/2
%
%   for a spherical array.
%
%   See also: driving_function_imp_nfchoa, driving_function_mono_nfchoa
%
%   References:
%       Ahrens (2012) - "Analytic Methods of Sound Field Synthesis", Springer,
%       ISBN 978-3-642-25743-8

%*****************************************************************************
% The MIT License (MIT)                                                      *
%                                                                            *
% Copyright (c) 2010-2019 SFS Toolbox Developers                             *
%                                                                            *
% Permission is hereby granted,  free of charge,  to any person  obtaining a *
% copy of this software and associated documentation files (the "Software"), *
% to deal in the Software without  restriction, including without limitation *
% the rights  to use, copy, modify, merge,  publish, distribute, sublicense, *
% and/or  sell copies of  the Software,  and to permit  persons to whom  the *
% Software is furnished to do so, subject to the following conditions:       *
%                                                                            *
% The above copyright notice and this permission notice shall be included in *
% all copies or substantial portions of the Software.                        *
%                                                                            *
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
% IMPLIED, INCLUDING BUT  NOT LIMITED TO THE  WARRANTIES OF MERCHANTABILITY, *
% FITNESS  FOR A PARTICULAR  PURPOSE AND  NONINFRINGEMENT. IN NO EVENT SHALL *
% THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
% LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT  OR OTHERWISE, ARISING *
% FROM,  OUT OF  OR IN  CONNECTION  WITH THE  SOFTWARE OR  THE USE  OR OTHER *
% DEALINGS IN THE SOFTWARE.                                                  *
%                                                                            *
% The SFS Toolbox  allows to simulate and  investigate sound field synthesis *
% methods like wave field synthesis or higher order ambisonics.              *
%                                                                            *
% https://sfs.readthedocs.io                            sfstoolbox@gmail.com *
%*****************************************************************************

%% ===== Checking input parameters =======================================
nargmin = 2;
nargmax = 2;
narginchk(nargmin,nargmax);
isargpositivescalar(nls);
isargstruct(conf);

%% ===== Configuration ===================================================
if conf.nfchoa.order
    M = conf.nfchoa.order;
    return;
end
dimension = conf.dimension;

%% ===== Computation =====================================================
% Get maximum order of spherical harmonics to avoid spatial aliasing
if strcmp('2D',dimension) || strcmp('2.5D',dimension)
    % Ahrens (2012), p. 132
    if isodd(nls)
        M = (nls-1)/2;
    else
        M = nls/2 - 1;
    end
elseif strcmp('3D',dimension)
    % Ahrens (2012), p. 125
    M = floor(sqrt(nls/2));
end


%  Generating a Givens' (2x2) matrix T such that
%            T*v = [d; 0]
%
%   Input:  v -- a vector of dimension 2
%
%  Output:  T -- Givens' matrix
%           d -- the 2-norm of v
%
%  syntax  >> [T,d] = GivensMatrix(v)


function uI = faceinterpolate3(u,node,elem,quadOrder)
%% FACEINTERPOLATE3 interpolate to face elements RT0.
%
% uI = faceinterpolate3(u,node,face) interpolates a given function u
% into the lowest order RT0. The coefficient is given by the face integral
% int_f u*n ds.
%
% uI = faceinterpolate3(u,node,elem) when |face| is not given, the function
% will generate the face by |[elem2face,face] = dof3face(elem)| and the
% ascend order is used |elem = sortelem3(elem)|.
%
% uI = faceinterpolate3(u,node,face,6) the last input is the quadrature
% order; see quadpts.
%
% Example
%
%   [node,elem] = cubemesh([-1,1,-1,1,-1,1],1);
%   maxIt = 3;
%   pde = mixBCdata3;
%   err = zeros(maxIt,1);
%   h = zeros(maxIt,1);
%   for i = 1:maxIt
%      [node,elem] = uniformrefine3(node,elem);
%      [elem2face,face] = dof3face(elem);
%      uI = faceinterpolate3(pde.Du,node,face);
%      err(i) = getL2error3RT0(node,elem,pde.Du,uI);
%      h(i) = 2^(-i);
%   end
%   figure;
%   showrateh(h,err,2,'-+','|| u - u_I ||');
%
% See also edgeinterpolate, edgeinterpolate1, edgeinterpolate2
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

% if ~exist('elemType','var'), elemType = 'RT0'; end

%% Construct Data Structure
if size(elem,2) == 3 % the input elem is face
    face = elem;
else
    elem = sortelem3(elem);
    [~,face] = dof3face(elem);
end

%% normal vector of each face
NF = size(face,1);
v12 = node(face(:,2),:) - node(face(:,1),:);
v13 = node(face(:,3),:) - node(face(:,1),:);
nVec = mycross(v12,v13); % |nVec| = 2*area;

%% assemble the right hand side
if ~exist('quadOrder','var'), quadOrder = 3; end
[lambda,weight] = quadpts(quadOrder);
nQuad = size(lambda,1);
uI = zeros(NF,1);
for p = 1:nQuad
    pxyz = lambda(p,1)*node(face(:,1),:) ...
		 + lambda(p,2)*node(face(:,2),:) ...
		 + lambda(p,3)*node(face(:,3),:);
    flux = u(pxyz);
    uI = uI + weight(p)*dot(flux,nVec,2)/2;
end
% if strcmp(elemType,'BDM1')
% end


%% Harmonic Representation of Rotational Functions
%

%%
% Similarly as periodic functions may be represented as weighted sums of
% sines and cosines a rotational function $f\colon \mathcal{SO}(3)\to\mathbb C$
% can be written as a series of the form
%
% $$ f({\bf R}) = \sum_{n=0}^N \sum_{k,l = -n}^n \hat f_n^{k,l} \, \mathrm{D}_n^{k,l}({\bf R}) $$
%
% with respect to Fourier coefficients $\hat f_n^{k,l}$ and the so called
% <WignerFunctions.html Wigner-D functions> $D_n^{k,l}$.
%
% There exists various normalizations for the <WignerFunctions.html Wigner-D functions>.
% In MTEX they are $L_2$ normalized, which means
%
% $$\| D_n^{k,l} \|_2 = 1$$
%
% for all $n,k,l$. For more information take a look on
% <WignerFunctions.html Wigner-D functions> and
% <SO3FunOperations.html#6 Integration of SO3Fun's>.
%
%%
%
% We construct an arbitrary ODF which generally is an SO3Fun:
mtexdata dubna
odf = calcODF(pf,'resolution',5*degree,'zero_Range')
%%
% Now we may transform an arbitrary SO3Fun into its Fourier representation
% using the command <SO3FunHarmonic.SO3FunHarmonic.html SO3FunHarmonic>

f = SO3FunHarmonic(odf,'bandwidth',32)

%% Fourier Coefficients
%
% Within the class |@SO3FunHarmonic| rotational functions are represented by
% their complex valued Fourier coefficients which are stored in the field
% |fun.fhat|.
% They are stored in a linear order, which means |f.fhat(1)| is the
% zero order Fourier coefficient, |f.fhat(2:10)| are the first order
% Fourier coefficients that form a 3x3 matrix and so on.
% Accordingly, we can extract the second order Fourier coefficients by

reshape(f.fhat(11:35),5,5)

%%
% As an additional example lets define a harmonic function by its Fourier
% coefficients $\hat f_0^{0,0} = 0.5$ and
% $\hat f_1 = \begin{array}{rrr}
% 1 & 4 & 7 \\
% 2 & 5 & 8 \\
% 3 & 6 & 9 \\
% \end{array}$

f2 = SO3FunHarmonic([0.5,1:9]')

plot(f2)
%%
% The Fourier coefficients $\hat f_n^{k,l}$ allow us a complete
% characterization of the rotational function. They are of particular
% importance for the calculation of mean macroscopic properties e.g.
% the second order Fourier coefficients characterize thermal expansion,
% optical refraction index, and electrical conductivity whereas the
% fourth order Fourier coefficients characterize the elastic properties
% of the specimen.
%
% Moreover, the decay of the Fourier coefficients is directly related to
% the smoothness of the SO3Fun. The decay of the Fourier coefficients might
% also hint for the presents of a ghost effect. See
% <PoleFigure2ODFGhostCorrection.html Ghost Correction>.

%%
% The decay of the Fourier coefficients is shown in the plot
close all;
plotSpektra(f)

%% ODFs given by Fourier coefficients
%
% In order to define an ODF by it *Fourier coefficients* ${\bf \hat{f}}$,
% they has to be given as a literally ordered, complex valued
% vector of the form
%
% $$ {\bf \hat{f}} = [\hat{f}_0^{0,0},\hat{f}_1^{-1,-1},\ldots,\hat{f}_1^{1,1},\hat{f}_2^{-2,-2},\ldots,\hat{f}_N^{N,N}] $$
%
% where $n=0,\ldots,N$ denotes the order of the Fourier coefficients.

cs   = crystalSymmetry('1');    % crystal symmetry
fhat = [1;reshape(eye(3),[],1);reshape(eye(5),[],1)]; % Fourier coefficients
odf = SO3FunHarmonic(fhat,cs)

plot(odf,'sections',6,'silent','sigma')

%%

plotPDF(odf,[Miller(1,0,0,cs),Miller(1,1,0,cs)],'antipodal')

%% TODO: Add some non ODF example for an SO3Fun
%
%


function mbasis = basis_matrix_hermite ( )

%*****************************************************************************80
%
%% BASIS_MATRIX_HERMITE sets up the Hermite spline basis matrix.
%
%  Discussion:
%
%    This basis matrix assumes that the data points are stored as
%    ( P1, P2, P1', P2' ), with P1 and P1' being the data value and
%    the derivative dP/dT at T = 0, while P2 and P2' apply at T = 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Foley, van Dam, Feiner, Hughes,
%    Computer Graphics: Principles and Practice,
%    page 484.
%
%  Parameters:
%
%    Output, real MBASIS(4,4), the basis matrix.
%
  mbasis(1,1) =  2.0;
  mbasis(1,2) = -2.0;
  mbasis(1,3) =  1.0;
  mbasis(1,4) =  1.0;

  mbasis(2,1) = -3.0;
  mbasis(2,2) =  3.0;
  mbasis(2,3) = -2.0;
  mbasis(2,4) = -1.0;

  mbasis(3,1) =  0.0;
  mbasis(3,2) =  0.0;
  mbasis(3,3) =  1.0;
  mbasis(3,4) =  0.0;

  mbasis(4,1) =  1.0;
  mbasis(4,2) =  0.0;
  mbasis(4,3) =  0.0;
  mbasis(4,4) =  0.0;

  return
end


function x = L4Pinv(cf,y)
%L4PINV The inverse of the 4 parameters logistic equation.
% The Four Parameters Logistic Regression or 4PL nonlinear regression model
% is commonly used for curve-fitting analysis in bioassays or immunoassays
% such as ELISAs or dose-response curves.
%
% Syntax: x=L4Pinv(cf,y)
%
% Inputs:
%           cf is the object containing the 4 parameters of logistic
%           equation computed by L4P function. Alternatively, it can be a
%           1x4 array.
%
%           y is the array of the response that you want to iterpolate.
%
% Outputs:
%           x is the vector of interpolated data.
%
% Example:
%
% xs=[0 4.5 10.6 19.7 40 84 210]; ys=[0.0089 0.0419 0.0873 0.2599 0.7074 1.528 2.7739];
%
% Calling on MatLab the function: [cf G]=L4P(x,y);
%
% you will find the 5 parameters of this curve.
%
% Calling on MatLab the function L4Pinv(cf,1.782315);
%
%           Answer is:
% ans =
%
%  99.9982
%
% Alternatively, you can do:
%
% P=[0.0010 1.5153 108.0035 3.7841]; L4Pinv(P,1.782315);
%
% with the same result.
%
%           Created by Giuseppe Cardillo
%           giuseppe.cardillo-edta@poste.it
%
% See also L4P, L5P, L5Pinv, L3P, L3Pinv
%
% To cite this file, this would be an appropriate format:
% Cardillo G. (2012) Four parameters logistic regression - There and back again
%

%--------------------Input errors handling section-------------------------
if nargin < 2
    error('Almost two inputs are required')
end
if isobject(cf)
    p=coeffvalues(cf);
else
    p=cf;
    if ~isvector(p) || length(p)~=4 || ~all(isfinite(p))
        error('cf must be a fit object or a 1x4 vector of real and finite numbers')
    end
end

%-------------------------Interpolate--------------------------------------
x=NaN(size(y)); ok=isfinite(y);
x(ok)=p(3).*(((p(1)-p(4))./(y(ok)-p(4)))-1).^(1/p(2));


%% check Clebsch Gordan Tensor

%% the reference

% some arbitrary rotation
g = rotation.byEuler(-72*degree,88*degree,134*degree);

% the rotation matrix
R = matrix(g);

% we want to express the product of two of those rotation matrice

RR_ref = R(:) * R(:).'

%% Express R by D

D1 = WignerD(g,'order',1);
D = D1(:) * D1(:).';

EinsteinSum(U,[1 -1],D1,[-1 -2],conj(U),[2 -2])

%% expansion into Wigner functions of lower order

% zero order component
D0 = WignerD(g,'order',0);
CG0 = ClebschGordanTensor(0);
C0 = D0*EinsteinSum(CG0,[1 3],CG0,[2 4])

% first order component
D1 = WignerD(g,'order',1);
CG1 = ClebschGordanTensor(1);
C1 = EinsteinSum(CG1,[1 3 -1],D1,[-1 -2],CG1,[2 4 -2])

% second order component
D2 = WignerD(g,'order',2);
CG2 = ClebschGordanTensor(2);
C2 = EinsteinSum(CG2,[1 3 -1],D2,[-1 -2],CG2,[2 4 -2])

C = EinsteinSum(C0 + C1 + C2,[-1 -2 -3 -4],U,[1 -1],conj(U),[2 -2],U,[3 -3],conj(U),[4 -4]);
real(reshape(matrix(C),[9 9]))

assert(norm(D - reshape(matrix(C0 + C1 + C2),[9,9]))<=1e-10,'Clebsch Gordan check failed')

%%

% zero order component
D0 = WignerD(g,'order',0);
CG0 = EinsteinSum(ClebschGordanTensor(0),[-1 -2],U,[1 -1],U,[2 -2]);
CG0c = EinsteinSum(ClebschGordanTensor(0),[-1 -2],conj(U),[1 -1],conj(U),[2 -2]);
C0 = D0*EinsteinSum(CG0,[1 3],CG0c,[2 4])

% first order component
D1 = WignerD(g,'order',1);
CG1 = EinsteinSum(ClebschGordanTensor(1),[-1 -2 3],U,[1 -1],U,[2 -2]);
CG1c = EinsteinSum(ClebschGordanTensor(1),[-1 -2 3],conj(U),[1 -1],conj(U),[2 -2]);
C1 = EinsteinSum(CG1,[1 3 -1],D1,[-1 -2],CG1c,[2 4 -2])

% second order component
D2 = WignerD(g,'order',2);
CG2 = EinsteinSum(ClebschGordanTensor(2),[-1 -2 3],U,[1 -1],U,[2 -2]);
CG2c = EinsteinSum(ClebschGordanTensor(2),[-1 -2 3],conj(U),[1 -1],conj(U),[2 -2]);
C2 = EinsteinSum(CG2,[1 3 -1],D2,[-1 -2],CG2c,[2 4 -2])

C = C0 + C1 + C2;
TT_ref ./ real(reshape(matrix(C),[9 9]))

assert(norm(TT_ref - reshape(matrix(C),[9,9]))<=1e-10,'Clebsch Gordan check failed')


rng(1); % For reproducibility
r = sqrt(rand(100,1)); % Radius
t = 2*pi*rand(100,1);  % Angle
data1 = [r.*cos(t), r.*sin(t)]; % Points

r2 = sqrt(3*rand(100,1)+1); % Radius
t2 = 2*pi*rand(100,1);      % Angle
data2 = [r2.*cos(t2), r2.*sin(t2)]; % points

figure;
plot(data1(:,1),data1(:,2),'r.','MarkerSize',15)
hold on
plot(data2(:,1),data2(:,2),'b.','MarkerSize',15)
ezpolar(@(x)1);ezpolar(@(x)2);
axis equal
hold off

data3 = [data1;data2];
theclass = ones(200,1);
theclass(1:100) = -1;

%Train the SVM Classifier
cl = fitcsvm(data3,theclass,'KernelFunction','rbf',...
    'BoxConstraint',Inf,'ClassNames',[-1,1]);

% Predict scores over the grid
d = 0.02;
[x1Grid,x2Grid] = meshgrid(min(data3(:,1)):d:max(data3(:,1)),...
    min(data3(:,2)):d:max(data3(:,2)));
xGrid = [x1Grid(:),x2Grid(:)];
[~,scores] = predict(cl,xGrid);

% Plot the data and the decision boundary
figure;
h(1:2) = gscatter(data3(:,1),data3(:,2),theclass,'rb','.');
hold on
ezpolar(@(x)1);
h(3) = plot(data3(cl.IsSupportVector,1),data3(cl.IsSupportVector,2),'ko');
contour(x1Grid,x2Grid,reshape(scores(:,2),size(x1Grid)),[0 0],'k');
legend(h,{'-1','+1','Support Vectors'});
axis equal
hold off

cl2 = fitcsvm(data3,theclass,'KernelFunction','rbf');
[~,scores2] = predict(cl2,xGrid);

figure;
h(1:2) = gscatter(data3(:,1),data3(:,2),theclass,'rb','.');
hold on
ezpolar(@(x)1);
h(3) = plot(data3(cl2.IsSupportVector,1),data3(cl2.IsSupportVector,2),'ko');
contour(x1Grid,x2Grid,reshape(scores2(:,2),size(x1Grid)),[0 0],'k');
legend(h,{'-1','+1','Support Vectors'});
axis equal
hold off


function b = r85_vxm ( n, a, x )

%*****************************************************************************80
%
%% R85_VXM multiplies a vector by a R85 matrix.
%
%  Discussion:
%
%    The R85 storage format represents a pentadiagonal matrix as a 5
%    by N array, in which each row corresponds to a diagonal, and
%    column locations are preserved.  Thus, the original matrix is
%    "collapsed" vertically into the array.
%
%  Example:
%
%    Here is how a R85 matrix of order 6 would be stored:
%
%       *   *  A13 A24 A35 A46
%       *  A12 A23 A34 A45 A56
%      A11 A22 A33 A44 A55 A66
%      A21 A32 A43 A54 A65  *
%      A31 A42 A53 A64  *   *
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the linear system.
%
%    Input, real A(5,N), the R85 matrix.
%
%    Input, real X(N), the vector to be multiplied by A'.
%
%    Output, real B(N), the product A' * x.
%
  b(1:n)   =            a(3,1:n)   * x(1:n);
  b(2:n)   = b(2:n)   + a(4,1:n-1) * x(1:n-1);
  b(3:n)   = b(3:n)   + a(5,1:n-2) * x(1:n-2);
  b(1:n-1) = b(1:n-1) + a(2,2:n)   * x(2:n);
  b(1:n-2) = b(1:n-2) + a(1,3:n)   * x(3:n);

  return
end


function [ x, w ] = ccfi_1 ( n, ell )

%*****************************************************************************80
%
%% CCFI_1 returns a Boyd quadrature rule for the Laguerre integral.
%
%  Discussion:
%
%    The Laguerre integral I(f) is:
%      I(f) = integral ( 0 <= x < +oo ) f(x) dx
%    and the quadrature rule which approximates I(f) is
%      Q(f) = sum ( 1 <= i <= n ) w(i) * f(x(i))
%
%    The parameter ELL controls the mapping between [-1,+1] and [0,+oo),
%    and can be initially chosen to be 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 May 2014
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    John Boyd,
%    Exponentially convergent Fourier-Chebyshev quadrature schemes on
%    bounded and infinite intervals,
%    Journal of Scientific Computing,
%    Volume 2, Number 2, 1987, pages 99-109.
%
%  Parameters:
%
%    Input, integer N, the number of points to use in the rule.
%
%    Input, real ELL, the mapping parameter.
%
%    Output, real X(N), W(N), the points and weights for the quadrature rule.
%
  t = ( pi * ( 1 : n ) / ( n + 1 ) )';
  x = ell * ( cot ( 0.5 * t ) ) .^ 2;

  w = zeros ( n, 1 );
  for i = 1 : n
    for j = 1 : n
      w(i) = w(i) + sin ( j * t(i) ) * ( 1.0 - cos ( j * pi ) ) / j;
    end
  end
  w = w * 2.0 * ell .* sin ( t ) ./ ( 1.0 - cos ( t ) ) .^ 2 * 2.0 / ( n + 1 );

  return
end


function a = hilbert_inverse ( n )

%*****************************************************************************80
%
%% HILBERT_INVERSE returns the inverse of the Hilbert matrix.
%
%  Formula:
%
%    A(I,J) =  (-1)**(I+J) * (N+I-1)! * (N+J-1)! /
%           [ (I+J-1) * ((I-1)!*(J-1)!)**2 * (N-I)! * (N-J)! ]
%
%  Example:
%
%    N = 5
%
%       25    -300     1050    -1400     630
%     -300    4800   -18900    26880  -12600
%     1050  -18900    79380  -117600   56700
%    -1400   26880  -117600   179200  -88200
%      630  -12600    56700   -88200   44100
%
%  Properties:
%
%    A is symmetric.
%
%    Because A is symmetric, it is normal, so diagonalizable.
%
%    A is almost impossible to compute accurately by general routines
%    that compute the inverse.
%
%    A is integral.
%
%    The sum of the entries of A is N**2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 March 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the inverse Hilbert matrix.
%

%
%  Set the (1,1) entry.
%
  a(1,1) = n * n;
%
%  Define Row 1, Column J by recursion on Row 1 Column J-1
%
  i = 1;
  for j = 2 : n
    a(i,j) = -a(i,j-1) * ( ( n + j - 1 ) * ( i + j - 2 ) * ...
      ( n + 1 - j ) ) /( ( i + j - 1 ) * ( j - 1 ) * ( j - 1 ) );
  end
%
%  Define Row I by recursion on row I-1
%
  for i = 2 : n
    for j = 1 : n

      a(i,j) = -a(i-1,j) * ( ( n + i - 1 ) * ( i + j - 2 ) * ( n + 1 - i ) ) ...
        / ( (i+j-1) * ( i - 1 ) * ( i - 1 ) );

    end
  end

  return
end


%
% Convert a polynomial coefficient matrix to a polynomial string
%
% Syntax:  >> p = CoefMat2PolynString(F,var)
%          >> p = CoefMat2PolynString(F,var,digits)
%
% Input:      F --- (matrix) Coefficient matrix of a polynomial
%           var --- (cell)   variable names in order
%        digits --- (integer) optional, number of digits, default = 15
%
% Output:     p --- (string) polynomial as a string
%
% Example:  >> F = [2 0; 1 3; 6, 8]
%              F =
%                2     0
%                1     3
%                6     8
%           >> CoefMat2PolynString(F,{'x','y'})
%              ans =
%                  6*x^2*y + 8*y^3


function cpv_test01 ( )

%*****************************************************************************80
%
%% CPV_TEST01 seeks the CPV of Integral ( -1 <= t <= 1 ) exp(t) / t dt
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 March 2015
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CPV_TEST01:\n' );
  fprintf ( 1, '  CPV of Integral ( -1 <= t <= 1 ) exp(t) / t dt\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '   N           Estimate             Error\n' );
  fprintf ( 1, '\n' );
  exact = 2.11450175075;
  a = -1.0;
  b = +1.0;
  for n = 2 : 2 : 8
    value = cpv ( @f01, a, b, n );
    fprintf ( 1, '  %2d  %24.16g  %14.6g\n', n, value, abs ( value - exact ) );
  end

  return
end
function value = f01 ( t )

%*****************************************************************************80
%
%% F01 evaluates the integrand of Integral ( -1 <= t <= 1 ) exp(t) / t dt
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 March 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real T, the argument.
%
%    Output, real VALUE, the value of the integrand.
%
  value = exp ( t );

  return
end


function C = augment(A, alpha)
%AUGMENT  Augmented system matrix.
%         AUGMENT(A, ALPHA) is the square matrix
%         [ALPHA*EYE(m) A; A' ZEROS(n)] of dimension m+n, where A is m-by-n.
%         It is the symmetric and indefinite coefficient matrix of the
%         augmented system associated with a least squares problem
%         minimize NORM(A*x-b).  ALPHA defaults to 1.
%         Special case: if A is a scalar, n say, then AUGMENT(A) is the
%                       same as AUGMENT(RANDN(p,q)) where n = p+q and
%                       p = ROUND(n/2), that is, a random augmented matrix
%                       of dimension n is produced.
%         The eigenvalues of AUGMENT(A,ALPHA) are given in terms of the
%         singular values s(i) of A (where m>n) by
%           ALPHA/2 +/- SQRT( s(i)^2*ALPHA^2 + 1/4 ),  i=1:n  (2n eigenvalues),
%           ALPHA,  (m-n eigenvalues).
%         If m < n then the first expression provides 2m eigenvalues and the
%         remaining n-m eigenvalues are zero.
%
%         See also SPAUGMENT.

%         References:
%         G. H. Golub and C. F. Van Loan, Matrix Computations, third
%            Edition, Johns Hopkins University Press, Baltimore, Maryland,
%            1996; sec. 5.6.4.
%         N. J. Higham, Accuracy and Stability of Numerical Algorithms,
%            Second edition, Society for Industrial and Applied Mathematics,
%            Philadelphia, PA, 2002; sec. 20.5.

[m, n] = size(A);
if nargin < 2, alpha = 1; end

if max(m,n) == 1
   n = A;
   p = round(n/2);
   q = n - p;
   A = randn(p,q);
   m = p; n = q;
end

C = [alpha*eye(m) A; A' zeros(n)];