function [ x, seed ] = sphere_unit_sample_3d_2 ( seed )

%*****************************************************************************80
%
%% SPHERE_UNIT_SAMPLE_3D_2 is a BAD method for sampling the unit sphere in 3D.
%
%  Discussion:
%
%    The unit sphere in 3D satisfies:
%
%      X * X + Y * Y + Z * Z = 1
%
%    Points on the unit sphere have coordinates ( PHI, THETA ) where
%    PHI varies from 0 to PI, and THETA from 0 to 2 PI, so that:
%
%    x = cos ( theta ) * sin ( phi )
%    y = sin ( theta ) * sin ( phi )
%    z =                 cos ( phi )
%
%    This routine implements a sampling of the sphere that simply
%    picks PHI and THETA uniformly at random from their ranges.
%    This is a uniform sampling on the cylinder, but it is NOT
%    a uniform sampling on the sphere.  I implement it here just
%    so I can run some tests against the code in SPHERE_UNIT_SAMPLE_3D.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real X(3), the sample point.
%
%    Output, integer SEED, a seed for the random number generator.
%
  dim_num = 3;

  [ phi, seed ] = r8_uniform_01 ( seed );
  phi = pi * phi;

  [ theta, seed ] = r8_uniform_01 ( seed );
  theta = 2.0 * pi * theta;

  x(1) = cos ( theta ) * sin ( phi );
  x(2) = sin ( theta ) * sin ( phi );
  x(3) = cos ( phi );

  return
end


function Ic = adjacency2incidence(A)

% adjacency2incidence - convert an adjacency matrix to an incidence matrix
%
%   Ic = adjacency2incidence(A);
%
%   A(i,j) = 1 iff (i,j) is an edge of the graph.
%   For each edge number k of the graph linking (i,j)
%       Ic(i,k)=1 and Ic(j,k)=-1
%
%   Ic is a sparse matrix.
%   Ic is also known as the graph gradient.
%
%   Copyright (c) 2006 Gabriel Peyre

%% compute list of edges
[i,j,s] = find(sparse(A));
I = find(i<=j);
i = i(I);
j = j(I);
% number of edges
n = length(i);
% number of vertices
nverts = size(A,1);

%% build sparse matrix
s = [ones(n,1); -ones(n,1)];
is = [(1:n)'; (1:n)'];
js = [i(:); j(:)];
Ic = sparse(is,js,s,n,nverts);
Ic = Ic';

% fix self-linking problem (0)
a = find(i==j);
if not(isempty(a))
    for t=a'
        Ic(i(t),t) = 1;
    end
end


%% Example 4.5: Solution of the Ornstein–Uhlenbeck process
%
% Copyright:
%   2018 - Simo Särkkä and Arno Solin
%
% License:
%   This software is provided under the MIT License. See the accompanying
%   LICENSE file for details.

%% Simulate trajectories from the OU process

  if exist('rng') % Octave doesn't have rng
      rng(10,'twister')
  else
      randn('state',1)
  end

  lambda = 0.5;
  q = 1;
  dt = 0.01;
  T = (0:dt:1);
  x0 = 4;
  M = exp(-lambda*T)*x0;
  P = q/(2*lambda)*(1 - exp(-2*lambda*T));

  XX = zeros(50,length(T));
  for n=1:size(XX,1)
    x = x0;
    for k=1:length(T)
      XX(n,k) = x;
      x = x - lambda * x * dt + sqrt(dt)*randn;
    end
  end

  figure(1); clf; hold on

    % Shade the 95% quantiles
    fill([T fliplr(T)],[M+1.96*sqrt(P) fliplr(M-1.96*sqrt(P))],1, ...
      'FaceColor',[.9 .9 .9],'EdgeColor',[.9 .9 .9])

    % Plot realizations
    h1 = plot(T,XX,'-','Color',[.5 .5 .5],'LineWidth',0.5);

    % Plot mean and quantiles
    h2 = plot(T,M,'k-','LineWidth',1);
    h34 = plot(T,M+1.96*sqrt(P),'--k', ...
               T,M-1.96*sqrt(P),'--k','LineWidth',0.7);

    %set(h(1:3),'Linewidth',2)

    legend([h2(1) h34(1) h1(1)],'Mean','95\% quantiles','Realizations')
    xlabel('Time, $t$'); ylabel('$x(t)$')

    ylim([0 5])
    box on
    set(gca,'Layer','Top')


close all; clear all; clc;
rng('default');
resize_images = true;

target.psnr = 35;
% target mean square error
target.mse = 255^2 * 10^(-target.psnr/10);
image_width = 42;
image_height = 48;
num_pixels = image_width * image_height;
% target sum of squared errors
target.sse = num_pixels * target.mse;
% target residual norm
target.rnorm = sqrt(target.sse);
fprintf('Target PSNR: %.2f dB\n', target.psnr);
fprintf('Target Mean Square Error: %.2f\n', target.mse);
fprintf('Target Root Mean Square Error: %.2f\n', sqrt(target.mse));
fprintf('Target Residual Norm: %.2f\n', target.rnorm);

N =  num_pixels;
redundancy_factor = 8;
D = redundancy_factor * N;

A = spx.dict.simple.gaussian_mtx(N, D);
dc_atom = (1/sqrt(N)) * ones(N, 1);
% throw away one original atom and replace with DC.
A = [dc_atom A(:, 1:D-1)];
dictionary = spx.dict.MatrixOperator(A);

yf = spx.data.image.YaleFaces();
yf.load();
fprintf('\n Resizing images:\n');
tstart = tic;
yf.resize_all(42, 48);
images = yf.ImageData;
[~, S] = size(images);
%images = yf.get_subject_images_resized(1, 42, 48);
elapsed = toc(tstart);
fprintf('Time taken: %.2f seconds \n', elapsed);
representations = zeros(D, S);
elapsed_times = zeros(1, S);
support_sizes = zeros(1, S);
res_norms = zeros(1, S);
psnrs = zeros(1, S);
fprintf('Total images: %d\n', S);
for s=1:S
    Y = images(:, s);
    solver = spx.pursuit.single.OrthogonalMatchingPursuit(dictionary);
    solver.MaxResNorm = target.rnorm;
    solver.Verbose = true;
    fprintf('sparsifying image: %d\n', s);
    tstart = tic;
    result = solver.solve_qr(Y);
    elapsed = toc(tstart);
    fprintf('Time taken: %.2f seconds \n', elapsed);
    fprintf('Support size: %d\n', result.iterations);
    support_sizes(s) = result.iterations;
    elapsed_times(s) = elapsed;
    representations(:, s) = result.z;
    res_norms(s) = result.rnorm;
    sse = result.rnorm^2;
    mse =  sse / num_pixels;
    psnr = 10 * log10(255^2 / mse);
    psnrs(s) = psnr;
    fprintf('PSNR : %.3f dB\n', psnr);
    if mod(s, 100) == 0
        % We wish to save intermediate data too
        save('omp_representations', 'representations');
        save('omp_stats', 'elapsed_times', 'support_sizes', 'res_norms', 'psnrs', 's');
    end
end
% final saving of all data.
save('bin/omp_dictionary', 'dictionary', 'N', 'D');
save('bin/omp_images', 'images');
save('bin/omp_representations', 'representations');
save('bin/omp_stats', 'elapsed_times', 'support_sizes', 'res_norms', 'psnrs', 'S');


function [x, funVal, ValueL]=LeastC(A, y, z, opts)
%
%%
% Function LeastC
%      Least Squares Loss with the L1 ball constraint (also known as Lasso)
%
%% Problem
%
%  min  1/2 || A x - y||^2 + 1/2 rsL2 * ||x||_2^2
%  s.t. ||x||_1 <= z
%
%  By default, rsL2=0.
%  When rsL2 is nonzero, this correspons the well-know elastic net.
%
%% Input parameters:
%
%  A-         Matrix of size m x n
%                A can be a dense matrix
%                         a sparse matrix
%                         or a DCT matrix
%  y -        Response vector (of size mx1)
%  z -        Radius of the L1 ball (z >0)
%  opts-      Optional inputs (default value: opts=[])
%
%% Output parameters:
%  x-         Solution
%  funVal-    Function value during iterations
%
%% Copyright (C) 2009-2010 Jun Liu, and Jieping Ye
%
% You are suggested to first read the Manual.
%
% For any problem, please contact with Jun Liu via j.liu@asu.edu
%
% Last modified on February 18, 2010.
%
%% Related papers
%
% [1]  Jun Liu and Jieping Ye, Efficient Euclidean Projections
%      in Linear Time, ICML 2009.
%
% [2]  Jun Liu and Jieping Ye, Sparse Learning with Efficient Euclidean
%      Projections onto the L1 Ball, Technical Report ASU, 2008.
%
%% Related functions
%
%  sll_opts, initFactor, pathSolutionLeast,
%  LeastR, nnLeastR, nnLeastC,
%  eplb
%
%%

%% Verify and initialize the parameters
%%

% Verify the number of input parameters
if (nargin <3)
    error('\n Inputs: A, y and z should be specified!\n');
elseif (nargin==3)
    opts=[];
end

% Get the size of the matrix A
[m,n]=size(A);

% Verify the length of y
if (length(y) ~=m)
    error('\n Check the length of y!\n');
end

% Verify the value of z
if (z<=0)
    error('\n z should be positive!\n');
end

% run sll_opts to set default values (flags)
opts=sll_opts(opts);

%% Detailed initialization
%% Normalization

% Please refer to sll_opts for the definitions of mu, nu and nFlag
%
% If .nFlag =1, the input matrix A is normalized to
%                     A= ( A- repmat(mu, m,1) ) * diag(nu)^{-1}
%
% If .nFlag =2, the input matrix A is normalized to
%                     A= diag(nu)^{-1} * ( A- repmat(mu, m,1) )
%
% Such normalization is done implicitly
%     This implicit normalization is suggested for the sparse matrix
%                                    but not for the dense matrix
%

if (opts.nFlag~=0)
    if (isfield(opts,'mu'))
        mu=opts.mu;
        if(size(mu,2)~=n)
            error('\n Check the input .mu');
        end
    else
        mu=mean(A,1);
    end

    if (opts.nFlag==1)
        if (isfield(opts,'nu'))
            nu=opts.nu;
            if(size(nu,1)~=n)
                error('\n Check the input .nu!');
            end
        else
            nu=(sum(A.^2,1)/m).^(0.5); nu=nu';
        end
    else % .nFlag=2
        if (isfield(opts,'nu'))
            nu=opts.nu;
            if(size(nu,1)~=m)
                error('\n Check the input .nu!');
            end
        else
            nu=(sum(A.^2,2)/n).^(0.5);
        end
    end

    ind_zero=find(abs(nu)<= 1e-10);    nu(ind_zero)=1;
    % If some values in nu is typically small, it might be that,
    % the entries in a given row or column in A are all close to zero.
    % For numerical stability, we set the corresponding value to 1.
end

if (~issparse(A)) && (opts.nFlag~=0)
    fprintf('\n -----------------------------------------------------');
    fprintf('\n The data is not sparse or not stored in sparse format');
    fprintf('\n The code still works.');
    fprintf('\n But we suggest you to normalize the data directly,');
    fprintf('\n for achieving better efficiency.');
    fprintf('\n -----------------------------------------------------');
end

%% Starting point initialization

% compute AT y
if (opts.nFlag==0)
    ATy=A'*y;
elseif (opts.nFlag==1)
    ATy=A'*y - sum(y) * mu';  ATy=ATy./nu;
else
    invNu=y./nu;              ATy=A'*invNu-sum(invNu)*mu';
end

% L2 norm regularization
if isfield(opts,'rsL2')
    rsL2=opts.rsL2;
    if (rsL2<0)
        error('\n opts.rsL2 should be nonnegative!');
    end
else
    rsL2=0;
end

% initialize a starting point
if opts.init==2
    x=zeros(n,1);
else
    if isfield(opts,'x0')
        x=opts.x0;
        if (length(x)~=n)
            error('\n Check the input .x0');
        end
    else
        x=ATy;  % if .x0 is not specified, we use ratio*ATy,
        % where ratio is a positive value
    end
end

% compute A x
if (opts.nFlag==0)
    Ax=A* x;
elseif (opts.nFlag==1)
    invNu=x./nu; mu_invNu=mu * invNu;
    Ax=A*invNu -repmat(mu_invNu, m, 1);
else
    Ax=A*x-repmat(mu*x, m, 1);     Ax=Ax./nu;
end

if (opts.init==0) % If .init=0, we set x=ratio*x by "initFactor"
    % Please refer to the function initFactor for detail

    x_norm=sum(abs(x)); % L1 norm of x
    x_2norm=x'*x;       % squared two norm of x
    if x_norm>=1e-6
        ratio=initFactor(x_norm, Ax, y, z,'LeastC', rsL2, x_2norm);
        x=ratio*x;    Ax=ratio*Ax;
    end
end

%% The main program

bFlag=0; % this flag tests whether the gradient step only changes a little

%% The Armijo Goldstein line search schemes
if (opts.lFlag==0)

    L=1 + rsL2;
    % We assume that the maximum eigenvalue of A'A is over 1

    % assign xp with x, and Axp with Ax.
    % xxp=x - xp
    xp=x; Axp=Ax; xxp=zeros(n,1);

    % alphap and alpha are used for computing the weight in forming search point
    alphap=0; alpha=1;

    % lambda0 is a guess of the root in the Euclidean projection
    lambda0=0;

    for iterStep=1:opts.maxIter
        % --------------------------- step 1 ---------------------------
        % compute search point s based on xp and x (with beta)
        beta=(alphap-1)/alpha;    s=x + beta* xxp;

        % --------------------------- step 2 ---------------------------
        % line search for L and compute the new approximate solution x

        % compute the gradient (g) at s
        As=Ax + beta* (Ax-Axp);

        % compute AT As
        if (opts.nFlag==0)
            ATAs=A'*As;
        elseif (opts.nFlag==1)
            ATAs=A'*As - sum(As) * mu';  ATAs=ATAs./nu;
        else
            invNu=As./nu;                ATAs=A'*invNu-sum(invNu)*mu';
        end

        % obtain the gradient g
        g=ATAs-ATy + rsL2 * s;

        % copy x and Ax to xp and Axp
        xp=x;    Axp=Ax;

        while (1)
            % let s walk in a step in the antigradient of s to get v
            % and project v onto the L1 ball
            v=s-g/L;

            % projection
            [x, lambda, zf_step]=eplb(v, n, z, lambda0);
            lambda0=lambda;

            v=x-s;  % the difference between the new approximate solution x
            % and the search point s

            % compute A x
            if (opts.nFlag==0)
                Ax=A* x;
            elseif (opts.nFlag==1)
                invNu=x./nu; mu_invNu=mu * invNu;
                Ax=A*invNu -repmat(mu_invNu, m, 1);
            else
                Ax=A*x-repmat(mu*x, m, 1);     Ax=Ax./nu;
            end

            Av=Ax -As;
            r_sum=v'*v; l_sum=Av'*Av;

            if (r_sum <=1e-20)
                bFlag=1; % this shows that, the gradient step makes little improvement
                break;
            end

            % the condition is ||Av||_2^2 <= (L - rsL2) * ||v||_2^2
            if(l_sum <= r_sum * (L-rsL2))
                break;
            else
                L=max(2*L, l_sum/r_sum + rsL2);
                % fprintf('\n L=%5.6f',L);
            end
        end

        ValueL(iterStep)=L;

        % --------------------------- step 3 ---------------------------
        % update alpha and alphap, and check whether converge
        alphap=alpha; alpha= (1+ sqrt(4*alpha*alpha +1))/2;

        xxp=x-xp;   Axy=Ax-y;
        funVal(iterStep)=Axy' * Axy/2 + rsL2/2 * x'*x;

        if (bFlag)
            % fprintf('\n The program terminates as the gradient step changes the solution very small.');
            break;
        end

        switch(opts.tFlag)
            case 0
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <= opts.tol)
                        break;
                    end
                end
            case 1
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <=...
                            opts.tol* funVal(iterStep-1))
                        break;
                    end
                end
            case 2
                if ( funVal(iterStep)<= opts.tol)
                    break;
                end
            case 3
                norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol)
                    break;
                end
            case 4
                norm_xp=sqrt(xp'*xp);    norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol * max(norm_xp,1))
                    break;
                end
            case 5
                if iterStep>=opts.maxIter
                    break;
                end
        end
    end % end of .lFlag=0
end

%% Adaptive Line Search

% we set gamma_0 to the L that is appropriate for the starting point
% opts.x0

if (opts.lFlag==1)

    L=1 + rsL2;
    % We assume that the maximum eigenvalue of A'A is over 1

    lambda0=0;
    % lambda0 is a guess of the root in the Euclidean projection

    gamma=1;
    % we shall set the value of gamma = L,
    % and L is appropriate for the starting point

    xp=x; Axp=Ax;
    % store x and Ax
    xxp=zeros(n,1);
    % the difference of x and xp

    % compute AT Ax
    if (opts.nFlag==0)
        ATAx=A'*Ax;
    elseif (opts.nFlag==1)
        ATAx=A'*Ax - sum(Ax) * mu';  ATAx=ATAx./nu;
    else
        invNu=Ax./nu;                ATAx=A'*invNu-sum(invNu)*mu';
    end

    % We begin the adaptive line search in the following
    %
    % Note that, in the line search, L and beta are changing

    for iterStep=1:opts.maxIter

        ATAxp=ATAx;
        % store ATAx to ATAxp

        if (iterStep~=1)
            % compute AT Ax
            if (opts.nFlag==0)
                ATAx=A'*Ax;
            elseif (opts.nFlag==1)
                ATAx=A'*Ax - sum(Ax) * mu';  ATAx=ATAx./nu;
            else
                invNu=Ax./nu;                ATAx=A'*invNu-sum(invNu)*mu';
            end
        end

        %--------- Line Search for L begins
        while (1)
            if (iterStep~=1)
                alpha= (-gamma+ sqrt(gamma*gamma + 4* L * gamma)) / (2*L);
                beta= (gamma - gamma* alphap) / (alphap * gamma + alphap* L * alpha);
                % beta is the coefficient for generating search point s

                s=x + beta* xxp;
                As=Ax + beta* (Ax-Axp);
                ATAs=ATAx + beta* (ATAx-ATAxp);
                % compute the search point s, A * s, and A' * A * s
            else
                alpha= (-1+ sqrt(5)) / 2;
                beta=0; s=x;  As=Ax; ATAs=ATAx;
            end

            g=ATAs-ATy + rsL2 * s;
            % compute the gradient g

            v=s-g/L;
            % a gradient step based on the search point s

            % projection
            [xnew, lambda, zf_step]=eplb(v, n, z, lambda0);
            lambda0=lambda;

            v=xnew-s;  % the difference between the new approximate solution x
            % and the search point s

            % compute A xnew
            if (opts.nFlag==0)
                Axnew=A* xnew;
            elseif (opts.nFlag==1)
                invNu=xnew./nu; mu_invNu=mu * invNu;
                Axnew=A*invNu -repmat(mu_invNu, m, 1);
            else
                Axnew=A*xnew-repmat(mu*xnew, m, 1);     Axnew=Axnew./nu;
            end

            Av=Axnew -As;
            r_sum=v'*v; l_sum=Av'*Av + v'*v * rsL2;

            if (r_sum <=1e-20)
                bFlag=1; % this shows that, the gradient step makes little improvement
                break;
            end

            % the condition is ||Av||_2^2  + rsL2 * ||v||_2^2<= L* ||v||_2^2
            if(l_sum <= r_sum * L)
                break;
            else
                L=max(2*L, l_sum/r_sum);
                % fprintf('\n L=%5.6f',L);
            end
        end
        %--------- Line Search for L ends

        gamma=L* alpha* alpha;    alphap=alpha;
        % update gamma, and alphap

        ValueL(iterStep)=L;
        % store values for L

        tao=L * r_sum / l_sum;
        if (tao >=5)
            L=L*0.8;
        end
        % decrease the value of L

        xp=x;   x=xnew;  xxp=x-xp;
        Axp=Ax; Ax=Axnew;
        % update x and Ax with xnew and Axnew

        Axy=Ax-y;
        funVal(iterStep)=Axy' * Axy/2 + rsL2/2 * x'*x;
        % compute function value

        if (bFlag)
            % fprintf('\n The program terminates as the gradient step changes the solution very small.');
            break;
        end

        switch(opts.tFlag)
            case 0
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <= opts.tol)
                        break;
                    end
                end
            case 1
                if iterStep>=2
                    if (abs( funVal(iterStep) - funVal(iterStep-1) ) <=...
                            opts.tol* funVal(iterStep-1))
                        break;
                    end
                end
            case 2
                if ( funVal(iterStep)<= opts.tol)
                    break;
                end
            case 3
                norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol)
                    break;
                end
            case 4
                norm_xp=sqrt(xp'*xp);    norm_xxp=sqrt(xxp'*xxp);
                if ( norm_xxp <=opts.tol * max(norm_xp,1))
                    break;
                end
            case 5
                if iterStep>=opts.maxIter
                    break;
                end
        end
    end
end


clear all; close all; clc

n=100;
L=20; x=linspace(-L,L,n); y=x;
[X,Y]=meshgrid(x,y);

Xd=[];
for j=1:100
u=tanh(sqrt(X.^2+Y.^2)).*cos(angle(X+i*Y)-(sqrt(X.^2+Y.^2))+j/10);
f=exp(-0.01*(X.^2+Y.^2));
uf=u.*f;
Xd(:,j)=reshape(uf,n^2,1);
pcolor(x,y,uf), shading interp, colormap(hot), caxis([-1 1]), drawnow
end

%%
[U,S,V]=svd(Xd,0);

figure(2)
subplot(4,1,3)
plot(100*diag(S)/sum(diag(S)),'ko','Linewidth',[2])
subplot(4,1,4)
semilogy(100*diag(S)/sum(diag(S)),'ko','Linewidth',[2])
subplot(2,1,1)
plot(V(:,1:4),'Linewidth',[2])
legend('mode1','mode2','mode3','mode4')
set(gca,'Fontsize',[15],'Xtick',[0 20 40 60 80 100])
subplot(4,1,3), set(gca,'Fontsize',[15],'Ylim',[0 60],'Ytick',[0 20 40 60],'Xlim',[0 40],'Xtick',[0 10 20 30 40])
subplot(4,1,4), set(gca,'Fontsize',[15],'Ylim',[10^(-20) 10^2],'Ytick',[10^(-20) 10^(-10) 10^2],'Xlim',[0 40],'Xtick',[0 10 20 30 40])

figure(3)
for j=1:4
  subplot(4,4,j)
  mode=reshape(U(:,j),n,n);
  pcolor(X,Y,mode), shading interp,caxis([-0.03 0.03]), colormap(gray)
  axis off
end

%%

figure(11)
u=tanh(sqrt(X.^2+Y.^2)).*cos(angle(X+i*Y)-(sqrt(X.^2+Y.^2)));
f=exp(-0.01*(X.^2+Y.^2));
uf=u.*f;
subplot(3,3,1),pcolor(x,y,uf), shading interp, caxis([-1 1]), axis off
subplot(3,3,2),pcolor(x,y,abs(uf)), shading interp, caxis([-1 1]), axis off
subplot(3,3,3),pcolor(x,y,uf.^5), shading interp, caxis([-1 1]), axis off
colormap(gray)

%% TRANSLATION
figure(5)
n=200; L=20; x=linspace(-L,L,n); y=x;  % space
m=41; T=10; t=linspace(0,T,m);         % time
c=3;   % wave speed

X=[];
for j=1:m
    X(:,j)=exp(-(x+15-c*t(j)).^2).';  % data snapshots
end
[U,S,V]=svd(X);  % SVD decomposition

%%
figure(6)
subplot(2,2,1)
waterfall(x,t,X.'),colormap([0 0 0])
view(20,75)
set(gca,'Xlim',[-20 20],'Xtick',[-20 -10 0 10 20],'Ylim',[0 10], ...
    'Ytick',[0 5 10],'Zlim',[0 1],'Ztick',[0  1],'Fontsize',[12])

[U2,S2,V2]=svd(X);

subplot(4,2,2)
plot(100*diag(S2)/sum(diag(S2)),'ko','Linewidth',[2])
set(gca,'Xlim',[0 40],'Xtick',0:10:40,'Ylim',[0 8],'Ytick',[0 4 8])
subplot(4,2,4)
semilogy(100*diag(S2)/sum(diag(S2)),'ko','Linewidth',[2])
grid on
set(gca,'Xlim',[0 40],'Xtick',0:10:40,'Ylim',[10^(-3) 2*10^1],'Ytick',[10^(-3) 10^(-2) 10^(-1) 10^0 10^1])

figure(8)
subplot(2,1,1)
plot(x,U2(:,1:4),'Linewidth',[2]);
legend('mode1','mode2','mode3','mode4','Location','SouthEast')
set(gca,'Fontsize',[15],'Ylim',[-0.15 0.15],'Ytick',[-0.15 0 0.15])
subplot(2,1,2)
plot(t,V2(:,1:4),'Linewidth',[2])
set(gca,'Fontsize',[15],'Ylim',[-.3 0.3],'Ytick',[-0.3 0 0.3])


function C=HestonCall(St,K,r,T,vt,kap,th,sig,rho,lda)
%--------------------------------------------------------------------------
%PURPOSE: computes the option price using Heston's model.
%--------------------------------------------------------------------------
%USAGE: C=HestonCall(St,K,r,sig,T,vt,kap,th,lda,rho)
%--------------------------------------------------------------------------
%INPUT: St - scalar or vector, price of underlying at time t
%       K - scalar or vector, strike price
%       r - scalar or vector, continuously compound risk free rate expressed as a
%       positive decimal number.
%       sig- scalar or vector, volatility of the volatility of the
%       underlying(same time units as for r)
%       T - scalar or vector, time to maturity (same time units as for r)
%       vt - scalar or vector, instantaneous volatility
%       kap - scalar or vector, is the rate at which vt reverts to th
%       th - scalar or vector, is the long vol, or long run average price
%       volatility; as t tends to infinity, the expected value of ?t tends to ?
%       lda - scalar or vector, risk premium for volatility
%       rho - scalar or vector, correlation between underlying and
%       volatility (rho<0 generates the leverage effect)
%--------------------------------------------------------------------------
%OUTPUT: C - scalar or vector, Heston's model call option price
%--------------------------------------------------------------------------

dphi=0.01;
maxphi=50;
phi=(eps:dphi:maxphi)';

%f1 = CF_SVj(log(St),vt,T,r,kap*th,0.5,kap+lda-rho*sig,rho,sig,phi);
%P1 = 0.5+(1/pi)*sum(real(exp(-i*phi*log(K)).*f1./(i*phi))*dphi);
%f2 = CF_SVj(log(St),vt,T,r,kap*th,-0.5,kap+lda,rho,sig,phi);
%P2 = 0.5+(1/pi)*sum(real(exp(-i*phi*log(K)).*f2./(i*phi))*dphi);
%C = St*P1 -K*exp(-r*T)*P2;

f1 = CF_SVj(log(St),vt,T,0,kap*th,0.5,kap+lda-rho*sig,rho,sig,phi);
P1 = 0.5+(1/pi)*sum(real(exp(-i*phi*log(K)).*f1./(i*phi))*dphi);
f2 = CF_SVj(log(St),vt,T,0,kap*th,-0.5,kap+lda,rho,sig,phi);
P2 = 0.5+(1/pi)*sum(real(exp(-i*phi*log(K)).*f2./(i*phi))*dphi);
C = St*P1 -K*exp(-r*T)*P2;


function [X_t,Mu_t,Sig_t]=OUstep(X_0,t,Mu,Th,Sig)

[NumSimul,N]=size(X_0);

% location
ExpM=expm(-Th*t);

Mu_t = repmat((Mu-ExpM*Mu)',NumSimul,1) +  X_0*ExpM';

% scatter
TsT=kron(Th,eye(N))+kron(eye(N),Th);

VecSig=reshape(Sig,N^2,1);
VecSig_t=inv(TsT)*(eye(N^2)-expm(-TsT*t))*VecSig;
Sig_t=reshape(VecSig_t,N,N);
Sig_t=(Sig_t+Sig_t')/2;

Eps=mvnrnd(zeros(N,1),Sig_t,NumSimul);

X_t=Mu_t+Eps;
Mu_t=mean(Mu_t,1)';


#!/usr/bin/env octave
%% 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 exam scores and the third column
%  contains the label.

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 = 1;

% 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);

pause;


% Sympoly demos

%% Various ways to create a sympoly

% A scalar (zero) sympoly
z = sympoly;

% Scalar sympolys 'x', 'y', 'u', 'v' created in the current workspace
sympoly x y u v

% A sympoly (identity matrix) array. The numeric element format is
% specified by the command window format style.
format short g
ayuh = sympoly(eye(3));

% Use deal to replicate a sympoly into several
[a,b] = deal(sympoly);

% Deal can also create a sympoly array
S(1:2) = deal(sympoly('x'));

% As can repmat
R = repmat(sympoly('x'),2,3);

whos

%% Arithmetic between sympolys, add, subtract, multiply, divide.

% add 1 to x
1 + x

%%

% double times a sympoly
2*y

%%

% subtraction, and a simple power
(x - y)^2

%%

% More complex expressions
(x - 2*y)^3/x + sqrt(y^3)

%% Synthetic division
[quotient,remainder] = syndivide(x^2+2*x-1,x+1)

%% Arrays of sympolys
[x , y ; 1 , x+y]

%%

% Arrays of sympolys
v = [1 x y x+y]

%% matrix multiplication
A = v*v'
B = v'*v
%% Selective extraction of terms
% The second term
terms(A,2)

%%
terms(A,x^2,'extract')

%%
% Delete a term
p = (1 + x^2 + x^7)^3
terms(p,x^2,'delete')

%% Selective deletion of terms
B = terms(A,x,'extract')

%%
% Operations on arrays
sympoly lambda
(rand(3) - lambda*eye(3))

%% Even eigenvalues, using det, then roots
roots(det(hilb(4) - lambda*eye(4)))

%% Sum on any dimension
sum(v,2)

%% And prod
prod(A(:))

%% Orthogonal polynomials from a variety of familes

% 3rd and 4th order Legendre polynomials
p3 = orthpoly(3,'legendre')
p4 = orthpoly(4,'legendre')

%%

% Orthogonal polynomials are orthogonal over the proper domain
defint(p3*p4,'x',[-1,1])

%%

% 2nd and 5th order Jacobi polynomials
p2 = orthpoly(2,'jacobi',2,3)
p5 = orthpoly(5,'jacobi',2,3)

%%

% Orthogonal polynomials are orthogonal over the proper domain.
% Numerical issures left this just eps shy from zero.
defint(p2*p5*(1-x)^2*(1+x)^5,'x',[-1,1])

%% Roots of the derivative of a sympoly
sort(roots(diff(orthpoly(6,'cheby2'))))

%% Error propagation through a sympoly

%  Given a unit Normal N(0,1) random variable, compute the
%  mean and variance of p(x) = 3*x + 2*x^2 - x^3

sympoly x
[polymean, polyvar] = polyerrorprop(3*x + 2*x^2 - x^3,'x',0,1)

%%

% Compute the mean and variance of x*y + 3*y^3, where x and y are
% respectively N(mux,sx^2), and N(muy,sy^2)

sympoly x y mux muy sx sy
[polymean,polyvar] = polyerrorprop(x*y+3*y^3,{'x' 'y'},[mux,muy],[sx,sy])

%% A simple construction for a Newton-Cotes integration rule
% Here I'll generate Simpson's 3/8 rule.
%
% <http://mathworld.wolfram.com/Simpsons38Rule.html |Simpson's 3/8 rule|>
%
M = vander(0:3);
sympoly x f0 f1 f2 f3
% an interpolating polynomial on this set of points
% { (0,f0), (1,f1), (2,f2), (3,f3) }
P_of_x = [x^3, x^2, x, 1]*pinv(M)*[f0;f1;f2;f3];

%% sympoly uses the command window format style to write out the coefficients
% Here, I'll force it to be in rational form
format rat

%%
% integrate the polynomial over its support
defint(P_of_x,'x',[0 3])

%%
% Or here, a 4 point open Newton-Cotes rule
M = vander(1:4);
sympoly x f1 f2 f3 f4
% an interpolating polynomial on this set of points
% { (1,f1), (2,f2), (3,f3) (4,f4) }
P_of_x = [x^3, x^2, x, 1]*pinv(M)*[f1;f2;f3;f4]

%%
% integrate the polynomial over the full domain of the rule
defint(P_of_x,'x',[0 5])


function [nll,g,H,T] = LogisticLoss(w,X,y)
% w(feature,1)
% X(instance,feature)
% y(instance,1)

[n,p] = size(X);

Xw = X*w;
yXw = y.*Xw;

nll = sum(mylogsumexp([zeros(n,1) -yXw]));

if nargout > 1
    if nargout > 2
        sig = 1./(1+exp(-yXw));
        g = -X.'*(y.*(1-sig));
    else
        %g = -X.'*(y./(1+exp(yXw)));
        g = -(X.'*(y./(1+exp(yXw))));
    end
end

if nargout > 2
    H = X.'*diag(sparse(sig.*(1-sig)))*X;
end

if nargout > 3
    T = zeros(p,p,p);
    for j1 = 1:p
        for j2 = 1:p
            for j3 = 1:p
                T(j1,j2,j3) = sum(y(:).^3.*X(:,j1).*X(:,j2).*X(:,j3).*sig.*(1-sig).*(1-2*sig));
            end
        end
    end
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));

% ====================== 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 = X*theta;
J = sum((H - y).^2) / (2 * m) + lambda*sum(theta(2:end).^2) / (2 * m);

grad = X'*(H - y) / m + lambda*[0;theta(2:end)] / m;

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

grad = grad(:);

end


function variance = normal_truncated_a_variance ( mu, s, a )

%*****************************************************************************80
%
%% NORMAL_TRUNCATED_A_VARIANCE: variance of the lower truncated Normal PDF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 August 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real MU, S, the mean and standard deviation of the
%    parent Normal distribution.
%
%    Input, real A, the lower truncation limit.
%
%    Output, real VARIANCE, the variance of the PDF.
%
  alpha = ( a - mu ) / s;
% beta = Inf;

  alpha_pdf = normal_01_pdf ( alpha );

  alpha_cdf = normal_01_cdf ( alpha );

  variance = s * s * ( 1.0 ...
    + ( alpha * alpha_pdf ) / ( 1.0 - alpha_cdf ) ...
    - ( alpha_pdf / ( 1.0 - alpha_cdf ) ) ^ 2 );

  return
end


% bpExampleScript

ctol = 0.000001;  % convergence tolerance
T = 0.1;       % annealing temperature
maxiter = Inf; % max iter for maxBeliefPropBethe

% factor for P(x1 | x2)
factor2var{1} = [1 2]; % which variables the factor involves
factors{1} = [0.9 0.5 ; ...
              0.1 0.5]; % P(x1=1|x2=1) = 0.9, P(x1=2|x2=1)=0.1
% factor for P(x2 | x3)
factor2var{2} = [2 3];
factors{2} = [0.25 0.01 ; ...
              0.75 0.99];
% factor for P(x3)
factor2var{3} = [3];
factors{3} = [0.25 ; ...
              0.75];  % P(x1=1)=0.25, P(x1=2)=0.75

nvals = [2 ; 2 ; 2]; % number of states for each node (variable)

[vals_max, bel_max] = maxBeliefPropBethe(factors, factor2var, nvals, ctol, T, maxiter);
bel_max = reshape(cell2mat(bel_max), [nvals(1) numel(nvals)])';

bel_marg = marginalBeliefPropBethe(factors, factor2var, nvals, ctol);
bel_marg = reshape(cell2mat(bel_marg), [nvals(1) numel(nvals)])';

% marginal answer should be:
%   P(x3=1) = 0.25;
%   P(x2=1) = (0.25)*P(x3=1) + (0.01)*P(x3=2) =  0.07
%   P(x1=1) = (0.9)*P(x2=1) + 0.5*P(x2=2) = 0.528
bel_marg

% max solution should be:
%   x1 = 2;
%   x2 = 2;
%   x3 = 1 or 2; (equally likely)
bel_max


%% Parzen Probabilistic Neural Networks
%  The Parzen Probabilistic Neural Networks (PPNN) are a simple type of
% neural network used to classify data vectors. This classifiers are based
% on the Bayesian theory where the a posteriori probability density
% function (apo-pdf) is estimated from data using the Parzen window
% technique.

%% A brief overview on the theory of the Parzen window and PPNN
%  The Bayesian classifiers use the Bayesian equation:
%
%                 P(x|wi)P(wi)
%  P(wi|x) = ----------------------
%             SUM_j P(x|wj)P(wj)
%
% to estimate the apo-pdf P(wi|x). Obviously to be usefull, this method
% needs the probabilities P(x|wi) and P(wi) to be known. A technique is to
% parametrize this pdfs, another is to estimate them from data.
%  The Parzen window technique estimates the probability defining a window
% (given the winow size) and a function on this window (i.e. an hypersphere
% with the gaussian function truncated inside). The computes the estimation
% of the probability function convolving the window function with the
% samples function. This obviously requires that the window function must
% have the integral (the hypervolume under the funciton) equal to 1 to
% mantain the scale in the estimated pdf.
%  The PPNN is a simple tool that is the composition of the pdf estimation
% with the Parzen window and the Bayesian classification selecting for a
% feature vector x the class wi where P(wi|x) is maximum.
%  In this quick explanation the particular derivations aren't reported but
% can be found in [1].
%
%  A PPNN is a two layer neural network (NN) where the input data are fully
% connected with the first neuron layer and the first layer is sparsely
% connected with the second (and ouput) layer. The output layer is composed
% of c neurons where c is the number of classes of the classifier.
% The wheights on the first layer are trained as follows: each sample data
% is normalized so that its length becames unitary, each sample data
% becames a neuron with the normalized values as weights w. The input data
% x is so dot-multiplied by the weights obtaining the network activation
% signal net=w^Tx. Then the exponential nonlinearity:
%
%          net - 1
%         ---------
%               2
%           sigm
%  act = e
%
% is computed to obtain the synaptic activation signals. During the
% learning process each first layer neuron is connected to the output layer
% neuron related to its class with wheight 1. During the classification
% process the output neuron of each class sums the activation signals from
% all the neurons of the neurons of the first layer. Simply the highest
% output value selects the class of the input data.
%
%  (w1)  (w2)  ...        OUTPUT
%    \     \ \__
%     |     |    \
%    ( )   ( )   ( )      internal layer
%    /|\   /|\   /|\
%                         INPUT
%
% [1] "Pattern Classification", second edition,
%     by Richard O. Duda, Peter E. Hart. and David G. Stork

%% A first simple example with 2D data
% In this simple example three set of points in the plane are selected in
% the region [1:100;1:100]. A PPNN is trained with this samples and then
% an image of the classification regions is produced.

% A training set for the class 'a' and 'b':
img=ones(100);
f=figure; imshow(img); [X,Y]=getpts; sa=[X,Y]'; close(f);
f=figure; imshow(img); [X,Y]=getpts; sb=[X,Y]'; close(f);
f=figure; imshow(img); [X,Y]=getpts; sc=[X,Y]'; close(f);
% The samples matrix:
S = [sa,sb,sc];
% The classification vector:
C = [repmat('a',[1,size(sa,2)]),repmat('b',[1,size(sb,2)]),repmat('c',[1,size(sc,2)])];
% Generating the network:
net = parzenPNNlearn(S,C);

% Generating the whole grid:
[X,Y] = meshgrid(1:100,1:100);
D = [X(:),Y(:)]';
% Classification of all points:
class = parzenPNNclassify(net,D);
class = reshape(class,[100,100]);
% Plotting:
sep = double(class=='a') + 2*double(class=='c');
figure; imshow(sep/2); hold on;
plot(sa(1,:),sa(2,:),'r.');
plot(sb(1,:),sb(2,:),'g.');
plot(sc(1,:),sc(2,:),'b.');

%% Adding samples to the network to increase the training
%  A PPNN can be simply improved adding new samples to it, the new samples
% generates new neurons in the internal layer that so can grow. Here an
% example of improving of the generated neural network.

% Getting new samples:
f=figure; imshow(img); hold on; plot(sa(1,:),sa(2,:),'r.');
[X,Y]=getpts; nsa=[X,Y]'; close(f);
f=figure; imshow(img); hold on; plot(sb(1,:),sb(2,:),'g.');
[X,Y]=getpts; nsb=[X,Y]'; close(f);
f=figure; imshow(img); hold on; plot(sc(1,:),sc(2,:),'b.');
[X,Y]=getpts; nsc=[X,Y]'; close(f);
Sa = [sa,nsa];
Sb = [sb,nsb];
Sc = [sc,nsc];

% The samples matrix:
nS = [nsa,nsb,nsc];
% The classification vector:
nC = [repmat('a',[1,size(nsa,2)]),repmat('b',[1,size(nsb,2)]),repmat('c',[1,size(nsc,2)])];
% Improving the network:
net = parzenPNNimprove(net,nS,nC);

% Classification of all points:
class = parzenPNNclassify(net,D);
class = reshape(class,[100,100]);
% Plotting:
sep = double(class=='a') + 2*double(class=='c');
figure; imshow(sep/2); hold on;
plot(Sa(1,:),Sa(2,:),'r.');
plot(Sb(1,:),Sb(2,:),'g.');
plot(Sc(1,:),Sc(2,:),'b.');


function [EC,ec,degij] = edge_nei_overlap_bd(CIJ)
% EDGE_NEI_OVERLAP_BD     Overlap amongst neighbors of two adjacent nodes
%
%   [EC,ec,degij] = edge_nei_bd(CIJ);
%
%   This function determines the neighbors of two nodes that are linked by
%   an edge, and then computes their overlap.  Connection matrix must be
%   binary and directed.  Entries of 'EC' that are 'inf' indicate that no
%   edge is present.  Entries of 'EC' that are 0 denote "local bridges",
%   i.e. edges that link completely non-overlapping neighborhoods.  Low
%   values of EC indicate edges that are "weak ties".
%
%   If CIJ is weighted, the weights are ignored. Neighbors of a node can be
%   linked by incoming, outgoing, or reciprocal connections.
%
%   Inputs:     CIJ,      directed (binary/weighted) connection matrix
%
%   Outputs:    EC,     edge neighborhood overlap matrix
%               ec,     edge neighborhood overlap per edge, in vector format
%               degij,  degrees of node pairs connected by each edge
%
%   Reference:
%
%       Easley and Kleinberg (2010) Networks, Crowds, and Markets.
%           Cambridge University Press, Chapter 3
%
%   Olaf Sporns, Indiana University, 2012

[ik,jk,ck] = find(CIJ);
lel = length(ck);
N = size(CIJ,1);

[~,~,deg] = degrees_dir(CIJ);

ec = zeros(1,lel);
degij = zeros(2,lel);
for e=1:lel
    neiik = setdiff(union(find(CIJ(ik(e),:)),find(CIJ(:,ik(e))')),[ik(e) jk(e)]);
    neijk = setdiff(union(find(CIJ(jk(e),:)),find(CIJ(:,jk(e))')),[ik(e) jk(e)]);
    ec(e) = length(intersect(neiik,neijk))/length(union(neiik,neijk));
    degij(:,e) = [deg(ik(e)) deg(jk(e))];
end;

ff = find(CIJ);
EC = 1./zeros(N);
EC(ff) = ec;                            %#ok<FNDSB>


function gx = p01_gx ( x )

%*****************************************************************************80
%
%% P01_GX evaluates the underlying function for problem 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X(2), the point at which the function is to
%    be evaluated.
%
%    Output, real GX(2), the value of the function at X.
%
  gx(1) = x(1) - ( ( x(2) - 5.0 ) * x(2) + 2.0 ) * x(2) - 13.0;
  gx(2) = x(1) + ( ( x(2) + 1.0 ) * x(2) - 14.0 ) * x(2) - 29.0;

  return
end


function [ cc_est, r_min, r_max ] = cube3d_grid_centralize ( ng, oc )

%*****************************************************************************80
%
%% CUBE3D_GRID_CENTRALIZE centralizes grid data from the surface of a 3D cube.
%
%  Discussion:
%
%    We generate a hypersphere grid of 1D index NG, with origin at OC,
%    and project these points onto the 3D cube of center [0,0,0]
%    and radius 1.
%
%    The cube is aligned with the coordinate axes.
%
%    We seek to estimate the value of the center.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 May 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NG, the grid index.  The hypersphere grid will have
%    order N = (2*NG+1) * (NG+1)^(M-2).
%
%    Input, real OC(M,1), the observation point, the original of the
%    hypersphere coordinate system.  OC should be inside the cube.
%
%    Output, real CC_EST(M,1), the estimated cube center.
%
%    Output, real R_MIN, R_MAX, the minimum and maximum distances
%    between the observation point and sample points on the cube surface.
%
  m = 3;
  n = ( 2 * ng + 1 ) * ( ng + 1 ) ^ ( m - 2 );
%
%  Destroy all row vectors!
%
  oc = oc(:);
%
%  Compute sample points on the cube surface.
%
  [ x1, x2, x3 ] = cube3d_grid ( ng, oc );
%
%  "Flatten" the data into vectors.
%
  x1 = reshape ( x1, n, 1 );
  x2 = reshape ( x2, n, 1 );
  x3 = reshape ( x3, n, 1 );
%
%  The center estimate is simply the average.
%
  cc_est = zeros ( 3, 1 );
  cc_est(1,1) = sum ( x1 ) / n;
  cc_est(2,1) = sum ( x2 ) / n;
  cc_est(3,1) = sum ( x3 ) / n;
%
%  For each point on the cube surface, the "radius" ROC is the norm of X - OC.
%
  roc = [ x1, x2, x3 ]' - repmat ( oc, 1, n );
  roc = roc.^2;
  roc = sum ( roc, 1 );
  roc = sqrt ( roc );
%
%  Return the minimum and maximum radiuses.
%
  r_min = min ( roc );
  r_max = max ( roc );

  return
end


function result = is_orthogonal_matrix(P)
%
% Orthogonal Matrices
%
% is_orthogonal_matrix(P) determines if the matrix P is an orthogonal
% matrix. An error is returned if a matrix that is not square is attempted
% to be determined for orthogonality.
%
%  Function written by Anthony Russo, downloaded from MatlabCentral.
%

matrix_size = size(P);

m = matrix_size(1,1);
n = matrix_size(1,2);

tolerance = 10^-10;

if m ~= n
    error('Only square matrices can be orthogonal.');
else
    count = 0;

    identity_matrix = P*P';

    if det(P) ~= 0
        for i = 1:m
            if abs(identity_matrix(i,i) - 1) <= tolerance
                count = count + 1;
            else
                break
            end
        end
    end

    if count == m
        result = 1;
    else
        result = 0;
    end
end


%% Demo of *plot_littlewood_paley_1d*

%% Usage
% littlewood = *plot_littlewood_paley_1d*(filters) (see
% <matlab:doc('plot_littlewood_paley_1d') plot_littlewood_paley_1d>).
%
%% Description
% *plot_littlewood_paley* computes, at every frequency, the
% Littlewood-Paley sum of a filter bank, i.e. the total power spectral
% density
% \sum_{j, \theta} |\hat{\psi_j} (\omega)|^2 + |\hat{\phi_J}(\omega)|^2
% If this sum is between $(1-epsilon)$ and $1$ for small $epsilon,
% the associated wavelet transform is proved to be contractive and
% almost unitary.

% In this demo, we display the Littlewood-Paley sum of a dyadic Morlet
% wavelet filter bank, with a very low averaging size of 8 samples. The
% Littlewood-Paley sum is shown in red, while the lowpass filter phi and
% the bandpass filters psi are respectively shown in green and blue.

figure;
T = 2^3;
interpolation = 2^10;
filt_opt.Q = 1;
filt_opt.J = T_to_J(T,filt_opt);
dyadic_filters = morlet_filter_bank_1d(T*interpolation,filt_opt);

plot_littlewood_paley_1d(dyadic_filters);
title('Q = 1 ; T = 8 samples (interpolated)');

% A more realistic example is constructed with an averaging size of 4096
% samples and a quality factor of 8. These values are typical in audio
% signal processing. The lowpass filter has such a narrow bandwidth that it
% is almost not visible in this second plot.

figure;
T = 2^12;
filt_opt.Q = 8;
filt_opt.J = T_to_J(T,filt_opt);
audio_filters = morlet_filter_bank_1d(T,filt_opt);

plot_littlewood_paley_1d(audio_filters);
title('Q = 8 ; T = 4096 samples');


function [ fea, out ] = ex_heattransfer7( varargin )
%EX_HEATTRANSFER7 1D Transient heat diffusion with analytic solution.
%
%   [ FEA, OUT ] = EX_HEATTRANSFER7( VARARGIN ) Transient heat
%   diffusion problem with analytic solution. A 1 m rod is kept at
%   fixed temperature on one end and constant outward heat flux at the
%   other end as in the following illustration.
%
%              +---------- L=1m ----------+ T = 25
%            q_n = 1       T(t=0) = 25
%
%   Accepts the following property/value pairs.
%
%       Input       Value/{Default}        Description
%       -----------------------------------------------------------------------------------
%       hmax        scalar {0.1}           Grid cell size
%       sfun        string {sflag1}        Finite element shape function
%       solver      string fenics/{}       Use FEniCS or default solver
%       ischeme     scalar {2}/1/3         Time stepping scheme
%       tmax        scalar {0.2}           Maximum time
%       tstep       scalar {0.01}          Time step size
%       iplot       scalar {1}/0           Plot solution (=1)
%                                                                                .
%       Output      Value/(Size)           Description
%       -----------------------------------------------------------------------------------
%       fea         struct                 Problem definition struct
%       out         struct                 Output struct
%
%   See also EX_HEATTRANSFER8.

% Copyright 2013-2022 Precise Simulation, Ltd.

cOptDef = { 'hmax',     0.1;
            'sfun',     'sflag1';
            'solver',   '';
            'ischeme',  2;
            'tmax',     0.2;
            'tstep',    0.01;
            'nstbwe',   0;
            'iplot',    1;
            'tol',      1e-3;
            'fid',      1 };
[got,opt] = parseopt(cOptDef,varargin{:});

% Grid generation.
fea.grid = linegrid( round(1/opt.hmax), 0, 1 );

% Problem definition.
fea.sdim  = { 'x' };                      % Space coordinate name.
fea = addphys( fea, @heattransfer );      % Add heat transfer physics mode.
fea.phys.ht.sfun = { opt.sfun };          % Set shape function.

% Equation coefficients.
fea.phys.ht.eqn.coef{1,end} = 1;          % Density.
fea.phys.ht.eqn.coef{2,end} = 1;          % Heat capacity.
fea.phys.ht.eqn.coef{3,end} = 1;          % Thermal conductivity.
fea.phys.ht.eqn.coef{6,end} = { 25 };     % Initial temperature.

% Boundary conditions.
fea.phys.ht.bdr.sel = [ 4 1 ];
fea.phys.ht.bdr.coef{1,end} = { [] 25 };
fea.phys.ht.bdr.coef{4,end}{1}{1} = -1;

% Parse physics modes and problem struct.
fea = parsephys(fea);
fea = parseprob(fea);

% Compute solution.
if( strcmp(opt.solver,'fenics') )
  fea = fenics( fea, 'fid', opt.fid, ...
                'tstep', opt.tstep, 'tmax', opt.tmax, 'ischeme', opt.ischeme );
  tlist = fea.sol.t;
else
  [fea.sol.u, tlist] = solvetime( fea, 'fid', opt.fid, 'init', {'T0_ht'}, 'ischeme', opt.ischeme, ...
                                  'tmax', opt.tmax, 'tstep', opt.tstep, 'nstbwe', opt.nstbwe );
end

% Postprocessing.
T_ref = refsol( fea.grid.p', tlist(end) );
if( opt.iplot>0 )
  postplot( fea, 'surfexpr', 'T', 'axequal', 0 )
  title(['Temperature at t=',num2str(tlist(end))])
  xlabel('x')
  ylabel('T')

  hold on
  plot( fea.grid.p, T_ref, 'r--' )
end

% Error checking.
T_sol = evalexpr( 'T', fea.grid.p, fea );
out.err  = norm( abs(T_sol-T_ref)/T_ref );
out.pass = out.err<opt.tol;

if( nargout==0 )
  clear fea out
end

% -----------------------------------
function [ u ] = refsol( x, t, dtol )

if( nargin<3 )
  dtol = 1e-7;
end

u0  = x + 24;
bdo = true;
n   = 0;
while( bdo )

  n   = n + 1;
  u   = u0 + 8/(1-2*n)^2/pi^2*cos((n-1/2)*pi*x)*exp(-((n-1/2)^2*pi^2)*t);
  bdo = any( max( u - u0 ) > dtol );
  u0  = u;

  if( n>1e3 )
    warning( ['Reference solution did not converge to tolerance ',num2str(dtol)] )
    break
  end
end


function [Ht,weights] = riskmetrics2006(data,tau0,tau1,kmax,rho)
% Computes the Riskmetrics 2006 covariance, which is a weighted average of
% EWMA covariances
%
% USAGE:
%  [HT,WEIGHTS] = riskmetrics2006(DATA,TAU0,TAU1,KMAX,RHO)
%
% INPUTS:
%   DATA     - A T by K matrix of zero mean residuals -OR-
%                K by K by T array of covariance estimators (e.g. realized covariance)
%   TAU0     - [OPTIONAL] Half-life of slowest EWMA
%   TAU1     - [OPTIONAL] Half-life of fastest EWMA
%   KMAX     - [OPTIONAL] Number of EWMA components to use
%   RHO      - [OPTIONAL] Decay factor to use in half-lives.  The
%                half-lives used are TAU1, TAU1*RHO, TAU1*RHO^2, ...
%
% OUTPUTS:
%   HT       - A [K K T] dimension matrix of conditional covariances
%   WEIGHTS  - A T by T matrix which contains the final weights used
%                computing all conditional covariances.  WEIGHT(i,j)
%                contains the weight of the outer-product in time period j
%                in the covariance forecast at period i+1
%
% COMMENTS:
%   The conditional variance, H(t), of a RM2006 covariance model
%
%      H(t) = w(i)*Htilde(t,i)
%
%   where Htilde(t,i) is an EWMA covariance, i=1,2,..., and
%
%   w(i) = 1-log(TAU1^((i-1)*RHO))/log(TAU0)
%
%   where the weights have been normalized so that they sum to 1.  All
%   EWMAs are initialized using a backward EWMA with the same decay.
%
% EXAMPLES:
%   RiskMetrics 2006 methodology using the suggested reference values
%     tau0   = 1560;
%     tau1   = 4;
%     taumax = 512;
%     rho    = sqrt(2);
%     kmax   = round(log(taumax/tau1)/log(rho)); % 14
%     Ht     = riskmetrics2006(data,tau0,tau1,kmax,rho)
%
%   RiskMetrics 1994 methodology using .94 as a special case of RM2006
%     tau0 = 1560;         % Does not matter
%     rho  = 1;            % Does not matter
%     tau1 = -1/log(.94);
%     kmax = 1;
%     Ht = riskmetrics2006(data,tau0,tau1,kmax,rho)

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 3    Date: 03/10/2011

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
switch nargin
    case 1
        tau0=[];
        tau1=[];
        kmax=[];
        rho =[];
    case 2
        tau1=[];
        kmax=[];
        rho =[];
    case 3
        kmax=[];
        rho =[];
    case 4
        rho =[];
    case 5
        % Nothing
    otherwise
        error('1 to 5 inputs required.')
end

if isempty(tau0)
    tau0 = 1560;
end
if isempty(tau1)
    tau1 = 4;
end
if isempty(kmax)
    kmax = 14;
end
if isempty(rho)
    rho = sqrt(2);
end

if tau1*rho^(kmax-1)>tau0
    error('The inputs must satisfy: TAU1*RHO^(KMAX-1)<TAU0')
end
if tau1<0
    error('TAU1 must be positive')
end
if tau0<0
    error('TAU0 must be positive')
end
if kmax<1 || floor(kmax)~=kmax
    error('KMAX must be an integer (weakly) larger than 1.')
end
if rho<0
    error('RHO must be positive')
end

if ndims(data)==2
    [T,K] = size(data);
    temp = zeros(K,K,T);
    for t=1:T
        temp(:,:,t) = data(t,:)'*data(t,:);
    end
    data = temp;
else
    K = size(data,1);
    T = size(data,3);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Input Checking
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tauks = tau1*rho.^((1:kmax)-1);
w= 1-log(tauks)/log(tau0);
w=w/sum(w);
Ht = zeros(K,K,T);
Httilde = zeros(K,K,T);

for k=1:kmax
    tauk = tauks(k);
    mu = exp(-1/tauk);
    % back casting
    endPoint = max(min(floor(log(.01)/log(mu)),T),k);
    weights = (1-mu).*mu.^(0:endPoint-1);
    weights = weights/sum(weights);
    backCast = zeros(K);
    for i=1:endPoint
        backCast = backCast + weights(i)*data(:,:,i);
    end
    Httilde(:,:,1) = backCast;

    for t=2:T
        Httilde(:,:,t) = mu*Httilde(:,:,t-1) + (1-mu)*data(:,:,t-1);
    end
    Ht = Ht + w(k) * Httilde;
end

if nargout>1
    weights = zeros(T,T);
    for k=1:kmax
        tauk = tauks(k);
        mu = exp(-1/tauk);
        weightMatrix = [mu.^(0:T-1)' zeros(T,T-1)];
        weightMatrix(T,T) = (1-mu);
        for j=1:(T-2);
            weightMatrix(T,T-j) = mu * weightMatrix(T,T-j+1);
        end
        for t=2:T-1
            weightMatrix(t,2:t) = weightMatrix(T,T+(-t+2:0));
        end
        weights = weights + w(k) * weightMatrix;
    end
end


% Reduce polygon to a given number of vertices
%
% poly = reduce_poly(poly, num)
%
% Inputs: poly        Polygon (2 rows, n columns)
%         num         Required number of vertices
%
% Outputs: poly       Final polygon
%
% Description: This code reduces the number of vertices in a closed polygon
% to the number specified by 'num'. It does this by calculating the
% importance of each vertex based on angle and segment length and then
% removing the least important. The process is repeated until the desired
% number of vertices is reached.
%
% Example:
% t = 0:0.1:2*pi;
% poly1 = [sin(t); cos(t)];
% poly2 = reduce_poly(poly1, 21);
% poly_draw = [poly2 poly2(:,1)];
% plot(poly_draw(1,:), poly_draw(2,:), '.-')
% axis equal
%
% Coded by: Peter Bone (peterbone@hotmail.com)
%------------------------------------------------------------------------
function poly = reduce_poly(poly, num)

numv = length(poly);

% Calculate initial importance of each vertex
imp = zeros(1,numv);
for v = 1 : numv
    imp(v) = vertex_importance(v, poly, numv);
end

% Iterate until desired number of vertices is reached
while numv > num

    [~, i] = min(imp(1:numv));

    % Remove vertex with least importance
    if i < numv
        poly(:,i:numv-1) = poly(:,i+1:numv);
        imp(i:numv-1) = imp(i+1:numv);
        vp = i;
    else
        vp = 1;
    end
    numv = numv - 1;

    % Recalculate importance for vertices neighbouring the removed one
    vm = 1 + mod(i - 2, numv);
    imp(vp) = vertex_importance(vp, poly, numv);
    imp(vm) = vertex_importance(vm, poly, numv);

end

% Clip polygon to the final length
poly = poly(:,1:num);

function a = vertex_importance(v, poly, numv)

% Find adjacent vertices
vp = 1 + mod(v, numv);
vm = 1 + mod(v - 2, numv);

% Obtain adjacent line segments and their lengths
dir1 = poly(:,v) - poly(:,vm);
dir2 = poly(:,vp) - poly(:,v);
len1 = norm(dir1);
len2 = norm(dir2);

% Calculate angle between vectors and multiply by segment lengths
% This is the importance of the vertex.
% Vertices with large angle and large segments attached are less
% likely to be removed
len1len2 = len1 * len2;
a = abs(acos((dir1' * dir2) / len1len2)) * len1len2;
%a = abs(1 - ((dir1' * dir2) / len1len2)) * len1len2;


% book : Signals and Systems Laboratory with MATLAB
% authors : Alex Palamides & Anastasia Veloni
%
%
%
%
% problem 2- Evaluate the Laplace Transform of  y''(t) and then replace y(t) by sin(t)u(t)

sym 'y(t)' ;
syms t s
z=laplace( diff('y(t)',2),s)

z=subs(z,'y(t)',sin(t))

z=subs(z,'y(0)',0)
z=subs(z,'D(y)(0)',1)
simplify(z)

%verification
x=sin(t);
x2=diff(x,2,t)
laplace(x2,s)


function y = pow_p( x, p )

%POW_P   Positive branch of the power function.
%   POW_P(X,P) computes a convex or concave branch of the power function:
%           P < 0: POW_P(X,P) = X.^P if X >  0, +Inf otherwise
%      0 <= P < 1: POW_P(X,P) = X.^P if X >= 0, -Inf otherwise
%      1 <= P    : POW_P(X,P) = X.^P if X >= 0, +Inf otherwise
%   Both P and X must be real.
%
%   Disciplined convex programming information:
%       The geometry of POW_P(X,P) depends on the precise value of P,
%       which must be a real constant:
%                P < 0: convex  and nonincreasing; X must be concave.
%           0 <= P < 1: concave and nondecreasing; X must be concave.
%           1 <= P    : convex  and nonmonotonic;  X must be affine.
%       In all cases, X must be real.

y = power( pdom( x ), p );

% Copyright 2005-2014 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


function  [mls,row,col] = mls(n)

%[mls,row,col] = mls(n);
%
%Generates a Maximum Length Sequence of n bits by utilizing a
%linear feedback shift register with an XOR gate on the tap bits
%Also given are the permutation vector row and col, used by prior and after
%the autocorreltion calculation via FHT.
%
%Function can accept bit lengths of between 2 and 24
%
%y is a vector of 1's & -1's that is (2^n)-1 in length.
%
%reference:
%	Davies, W.D.T. (June, July, August, 1966). Generation and
%properties of maximum-length sequences. Control, 302-4, 364-5,431-3.
%
%Spring 2001, Christopher Brown, cbrown@phi.luc.edu

switch n							%assign taps which will yeild a maximum
case 2								%length sequence for a given bit length
   taps=2;							%I forget the reference I used, but theres
   tap1=1;							%a list of appropriate tap values in
   tap2=2;							%Vanderkooy, JAES, 42(4), 1994.
case 3
   taps=2;
   tap1=1;
   tap2=3;
case 4
   taps=2;
   tap1=1;
   tap2=4;
case 5
   taps=2;
   tap1=2;
   tap2=5;
case 6
   taps=2;
   tap1=1;
   tap2=6;
case 7
   taps=2;
   tap1=1;
   tap2=7;
case 8
   taps=4;
   tap1=1;
   tap2=5;
   tap3=6;
   tap4=8;
case 9
   taps=2;
   tap1=4;
   tap2=9;
case 10
   taps=2;
   tap1=3;
   tap2=10;
case 11
   taps=2;
   tap1=2;
   tap2=11;
case 12
   taps=4;
   tap1=3;
   tap2=4;
   tap3=7;
   tap4=12;
case 13
   taps=4;
   tap1=1;
   tap2=3;
   tap3=4;
   tap4=13;
case 14
   taps=4;
   tap1=1;
   tap2=11;
   tap3=12;
   tap4=14;
case 15
   taps=2;
   tap1=1;
   tap2=15;
case 16
   taps=4;
   tap1=2;
   tap2=3;
   tap3=5;
   tap4=16;
case 17
   taps=2;
   tap1=3;
   tap2=17;
case 18
   taps=2;
   tap1=7;
   tap2=18;
case 19
   taps=4;
   tap1=1;
   tap2=5;
   tap3=6;
   tap4=19;
case 20
   taps=2;
   tap1=3;
   tap2=20;
case 21
   taps=2;
   tap1=2;
   tap2=21;
case 22
   taps=2;
   tap1=1;
   tap2=22;
case 23
   taps=2;
   tap1=5;
   tap2=23;
case 24
   taps=4;
   tap1=1;
   tap2=3;
   tap3=4;
   tap4=24;
case 25
  taps=2;
  tap1=3;
  tap2=25;
case 26
  taps=4;
  tap1=1;
  tap2=7;
  tap3=8;
  tap4=26;
case 27
  taps=4;
  tap1=1;
  tap2=7;
  tap3=8;
  tap4=27;
case 28
  taps=2;
  tap1=3;
  tap2=28;
case 29
  taps=2;
  tap1=2;
  tap2=29;
case 30
  taps=4;
  tap1=1;
  tap2=15;
  tap3=16;
  tap4=30;
case 31
  taps=2;
  tap1=3;
  tap2=31;
case 32
  taps=4;
  tap1=1;
  tap2=27;
  tap3=28;
  tap4=32;
otherwise
   disp(' ');
   error('input bits must be between 2 and 32');
end

if taps == 2
    [mls,row,col]=mls2tap(tap2,tap1,tap2);
elseif taps == 4
    [mls,row,col]=mls4tap(tap4,tap1,tap2,tap3,tap4);
end


% Chapter 2 - Nonlinear Discrete Dynamical Systems.
% Program 2g - Computing the Lyapunov Exponents of the Henon map.
% Copyright Birkhauser 2013. Stephen Lynch.

itermax=500;
a=1.2;b=0.4;x=0;y=0;
vec1=[1;0];vec2=[0;1];
for i=1:itermax
    x1=1-a*x^2+y;y1=b*x;
    x=x1;y=y1;
    J=[-2*a*x 1;b 0];
    vec1=J*vec1;
    vec2=J*vec2;
    dotprod1=dot(vec1,vec1);
    dotprod2=dot(vec1,vec2);
    vec2=vec2-(dotprod2/dotprod1)*vec1;
    lengthv1=sqrt(dotprod1);
    area=vec1(1)*vec2(2)-vec1(2)*vec2(1);
    h1=log(lengthv1)/i;
    h2=log(area)/i-h1;
end
fprintf('h1= %12.10f\n',h1)
fprintf('h2= %12.10f\n',h2)

% End of Program 2g.


% X = NGROUPSK(N, K)
%
% The number of ways N*K objects can be divided into N groups of equal size
% (K objects per group).
%
% N = number of groups
% K = size of the groups
%
% X = number of different group division combinations

% Last modified 2011-01-28
% Copyright (c) Jaakko Luttinen (jaakko.luttinen@tkk.fi)

function x = groupsk(n, k)

x = factorial(n.*k) ./ ( factorial(n) .* factorial(k).^n );


clear;
% some integration experiments

% Example 1: E[p(x)], x~N(0,1), p(x) polynomial
degree = 10;
p = rand(1,degree+1); % make some polynomial
fprintf('adaptive quad, tol %.1g = %.10g\n', ...
        1e-10, quad(@(x) polyval(p,x).*normpdf(x), ...
                    -30,30,1e-10));

fprintf(' gauss-hermite quadrature\n');
for n=1:((degree+1)/2+4)
  % use hermite -- will be exact for n>=(degree+1)/2
  int = gaussHermite(n);
  % notice the change of variables!
  ep = polyval(p,int.x*sqrt(2))'*int.w/sqrt(pi);
  if (n==round((degree+1)/2))
    fprintf('--- the rest should be exact ----\n');
  end
  fprintf('n=%2d  E[p(x)] = %.10g\n',n,ep);
end

fprintf('\n monte carlo integration\n')
for n=1:6
  fprintf('n=10^%d  E[p(x)] = %.10g\n',n, ...
          mean(polyval(p,randn(10^n,1))));
end

pause();

% Example 2: E[p(x)|x>-0.1], x~N(0,1)
fprintf('adaptive quad, tol %.1g = %.10g\n', ...
        1e-10, quad(@(x) polyval(p,x).*normpdf(x), ...
                    -0.1,30,1e-10) / ...
        quad(@(x) normpdf(x),-0.1,30,1e-10));

fprintf('\n gauss-hermite quadrature (not the right rule)\n');
for n=1:2:60
  int = gaussHermite(n);
  m = int.x>-0.1;
  ep = polyval(p,int.x(m)*sqrt(2))'* ...
       int.w(m)/sqrt(pi) ...
       * sum(int.w)/sum(int.w(m));
  fprintf('n=%2d  E[p(x)] = %.10g\n',sum(m),ep);
end

fprintf('\n monte carlo integration\n')
for n=1:6
  x = randn(10^n,1);
  x = x(x>-0.1);
  fprintf('n=10^%d  E[p(x)] = %.10g\n',numel(x), ...
          mean(polyval(p,x)));
end
pause();

% Example 2: E[p(x)|x>-0.1], x~N(0,1)
% Example 2: E[p(x)|x>-0.1], x~N(0,1)
fprintf('adaptive quad, tol %.1g = %.10g\n', ...
        1e-10, quad(@(x) exp(x).*normpdf(x), ...
                    -30,30,1e-10));

fprintf('\n gauss-hermite quadrature (not the right rule)\n');
for n=1:20
  int = gaussHermite(n);
  ep = exp(int.x*sqrt(2))'*int.w/sqrt(pi);
  fprintf('n=%2d  E[p(x)] = %.10g\n',n,ep);
end

fprintf('\n monte carlo integration\n')
for n=1:6
  x = randn(10^n,1);
  fprintf('n=10^%d  E[p(x)] = %.10g\n',numel(x), ...
          mean(exp(x)));
end
pause();


%inPoints = getPolygonGrid(xv,yv,ppa) returns points that are within a
%concave or convex polygon using the inpolygon function.

%xv and yv are columns representing the vertices of the polygon, as used in
%the Matlab function inpolygon

%ppa refers to the points per unit area you would like inside the polygon.
%Here unit area refers to a 1.0 X 1.0 square in the axes.

%Example:
% L = linspace(0,2.*pi,6); xv = cos(L)';yv = sin(L)'; %from the inpolygon documentation
% inPoints = getPolygonGrid(xv, yv, 10^5)
% plot(inPoints(:, 1),inPoints(:,2), '.k');

function [inPoints] = polygrid( xv, yv, ppa)

	N = sqrt(ppa);
%Find the bounding rectangle
	lower_x = min(xv);
	higher_x = max(xv);

	lower_y = min(yv);
	higher_y = max(yv);
%Create a grid of points within the bounding rectangle
	inc_x = 1/N;
	inc_y = 1/N;

	interval_x = lower_x:inc_x:higher_x;
	interval_y = lower_y:inc_y:higher_y;
	[bigGridX, bigGridY] = meshgrid(interval_x, interval_y);

%Filter grid to get only points in polygon
	in = inpolygon(bigGridX(:), bigGridY(:), xv, yv);
%Return the co-ordinates of the points that are in the polygon
	inPoints = [bigGridX(in), bigGridY(in)];

end


%% Optimal Kernel Selection
%
%%
% In the section <DensityEstimation.html density estimation> we have seen
% that the correct choice of the kernel halfwidth is essential for creating a good
% match between the true density function and the reconstructed density
% function. If the halfwidth is set too small the reconstructed density
% function is usually oscillating and the indiviudual sampling points are
% visible as sharp peaks. If the halfwidth is too large the resulting
% density function is usually too smooth and does not reproduce the
% features of the original density function.
%
% Finding an optimal kernel halfwidth is a hard problem as the optimal
% kernel halfwidth depends not only on the number of sampling points but also
% on the smoothness of the true but unknown density function.
% MTEX offers several options set by flags during the kernel calculation operation.  A very
% conserative choice for the kernel halfwidth that takes into account only
% the number of sampling points is implemented in MTEX with the flag |'magicRule'|. The flag
% |'RuleOfThumb'| considers both the number of sampling
% points and the variance of the sampling points as an estimate of the
% smoothness of the true density function. The most advanced (and default)
% method for estimating the optimal kernel halfwidth is
% <orientation.KLCV.html Kullback Leibler cross validation>.
% This method tests different kernel halfwidths on a subset of the
% random sample and selects the halfwidth which best reproduces the
% ommited points of the random sample.
%
% In order to demonstrate this functionality let's start with the following
% orientation density function

% Define trigonal crystal symmetry using Enantiomorphic Point Group notation
cs = crystalSymmetry('32');

% Build a density function by combining a uniform texture with two pre-defined texture components
odf = 0.25*uniformODF(cs) + 0.25*unimodalODF(orientation.brass(cs)) + ...
  0.5*fibreODF(fibre.alpha(cs),'halfwidth',10*degree);

% plot the density function as six sigma sections
plot(odf,'sections',6,'silent','sigma')
mtexColorbar

%%
% and compute $10000$ random orientations representing this density function using the command
% |<orientation.discreteSample.html discreteSample>|

ori = odf.discreteSample(10000)

%%
% Next we estimate the optimal <ODFShapes.html kernel function> using the
% command |<orientation.calcKernel.html calcKernel>| with the default settings.

psi  = calcKernel(ori)

%%
% This kernel can now be used to reconstruct the original ODF from the sampled points using the command
% <DensityEsimation.html density estimation>

odf_rec = calcDensity(ori,'kernel',psi)

% plot the reconstructed ODF and compare it to the plot of the original function.  The results are similar but not identical.
figure;plot(odf_rec,'sections',6,'silent','sigma')
mtexColorbar

%% Exploration of the relationship between estimation error and number of single orientations
%
% In this section we want to compare the different methods for estimating
% the optimal kernel halfwidth. To this end we simulate 10, 100, ...,
% 1000000 single orientations from the model ODF |odf|, compute optimal
% kernels according to the |'magicRule'|, the |'RuleOfThumb'| and
% <orientation.KLCV.html Kullback Leibler cross validation> and then
% compute the fit between the reconstructed |odf_rec| and the original
% |odf|.

% define a variable to hold the calculated error values
e = [];
for i = 1:6

  % calculate a sample of orientations from the model ODF
  ori = discreteSample(odf,10^i,'silent');

  % calculate the kernel using the function defaults, reconstruct the odf, and calculate error between this and the original ODF
  psi1 = calcKernel(ori,'SamplingSize',10000,'silent');
  odf_rec = calcDensity(ori,'kernel',psi1,'silent');
  e(i,1) = calcError(odf_rec,odf,'resolution',2.5*degree);

  % calculate the kernel using the RuleOfThumb, reconstruct the odf, and calculate error between this and the original ODF
  psi2 = calcKernel(ori,'method','RuleOfThumb','silent');
  odf_rec = calcDensity(ori,'kernel',psi2,'silent');
  e(i,2) = calcError(odf_rec,odf,'resolution',2.5*degree);

  % calculate the kernel using the magicRule, reconstruct the odf, and calculate error between this and the original ODF
  psi3 = calcKernel(ori,'method','magicRule','silent');
  odf_rec = calcDensity(ori,'kernel',psi3,'silent');
  e(i,3) = calcError(odf_rec,odf,'resolution',2.5*degree);

  % generate text showing the kernel size calculated with each method in each loop
  disp(['RuleOfThumb: ' int2str(psi2.halfwidth/degree) mtexdegchar ...
    ' KLCV: ' int2str(psi1.halfwidth/degree) mtexdegchar ...
    ' magicRule: ' int2str(psi3.halfwidth/degree) mtexdegchar ...
    ]);

end

%%
% Plot the error to the number of single orientations sampled from the original ODF.

close all;
loglog(10.^(1:length(e)),e,'LineWidth',2)
legend('Default','RuleOfThumb','magicRule')
xlabel('Number of orientations (log scale)')
ylabel('Estimation Error in degrees')
title('Error between original ODF model and the reconstructed ODF','FontWeight','bold')


function [X,Y,Z] = EquinNdes3D(N)

% function [X,Y,Z] = EquinNdes3D(N)
% Purpose: compute the equidistributed nodes on the reference tetrahedron

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

% 2) create equidistributed nodes on equilateral triangle
X = zeros(Np,1); Y = zeros(Np,1); Z = zeros(Np,1);

sk = 1;
for n=1:N+1
  for m=1:N+2-n
    for q=1:N+3-n-m
      X(sk) = -1 + (q-1)*2/N; Y(sk) = -1 + (m-1)*2/N; Z(sk) = -1 + (n-1)*2/N;
      sk = sk+1;
    end
  end
end
return;


function m = sqdist(p, q, A)
% SQDIST      Squared Euclidean or Mahalanobis distance.
% SQDIST(p,q)   returns m(i,j) = (p(:,i) - q(:,j))'*(p(:,i) - q(:,j)).
% SQDIST(p,q,A) returns m(i,j) = (p(:,i) - q(:,j))'*A*(p(:,i) - q(:,j)).
% The Lightspeed Matlab toolbox
% Written by Tom Minka

[d, pn] = size(p);
[d, qn] = size(q);

if pn == 0 || qn == 0
  m = zeros(pn,qn);
  return
end

if nargin == 2

  pmag = col_sum(p .* p);
  qmag = col_sum(q .* q);
  m = repmat(qmag, pn, 1) + repmat(pmag', 1, qn) - 2*p'*q;
  %m = ones(pn,1)*qmag + pmag'*ones(1,qn) - 2*p'*q;

else

  Ap = A*p;
  Aq = A*q;
  pmag = col_sum(p .* Ap);
  qmag = col_sum(q .* Aq);
  m = repmat(qmag, pn, 1) + repmat(pmag', 1, qn) - 2*p'*Aq;

end


function eps = leviCivita
% the Levi Civita permutation tensor
%
% Syntax
%   eps = tensor.leviCivita
%

eps = zeros(3,3,3);
eps(1,2,3) = 1;
eps(3,1,2) = 1;
eps(2,3,1) = 1;

eps(1,3,2) = -1;
eps(3,2,1) = -1;
eps(2,1,3) = -1;

eps = tensor(eps,'rank',3,'name','Levi Cevita');

end


function value = r8mat_norm_fro_affine ( m, n, a1, a2 )

%*****************************************************************************80
%
%% R8MAT_NORM_FRO_AFFINE returns the Frobenius norm of an R8MAT difference.
%
%  Discussion:
%
%    The Frobenius norm is defined as
%
%      value = sqrt ( sum ( 1 <= I <= M ) sum ( 1 <= j <= N ) A(I,J)^2 )
%
%    The matrix Frobenius norm is not derived from a vector norm, but
%    is compatible with the vector L2 norm, so that:
%
%      vec_norm_l2 ( A * x ) <= mat_norm_fro ( A ) * vec_norm_l2 ( x ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 September 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows.
%
%    Input, integer N, the number of columns.
%
%    Input, real A1(M,N), A2(M,N), the matrices for whose difference
%    the Frobenius norm is desired.
%
%    Output, real VALUE, the Frobenius norm of A1 - A2.
%
  value = sqrt ( sum ( sum ( ( a1(1:m,1:n) - a2(1:m,1:n) ).^2 ) ) );

  return
end


function mbasis = basis_matrix_beta_uni ( beta1, beta2 )

%*****************************************************************************80
%
%% BASIS_MATRIX_BETA_UNI sets up the uniform beta spline basis matrix.
%
%  Discussion:
%
%    If BETA1 = 1 and BETA2 = 0, then the beta spline reduces to
%    the B spline.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Foley, van Dam, Feiner, Hughes,
%    Computer Graphics: Principles and Practice,
%    page 505.
%
%  Parameters:
%
%    Input, real BETA1, the skew or bias parameter.
%    BETA1 = 1 for no skew or bias.
%
%    Input, real BETA2, the tension parameter.
%    BETA2 = 0 for no tension.
%
%    Output, real MBASIS(4,4), the basis matrix.
%
  mbasis = zeros(4,4);

  mbasis(1,1) = - 2.0 * beta1 * beta1 * beta1;
  mbasis(1,2) =   2.0 * beta2 ...
    + 2.0 * beta1 * ( beta1 * beta1 + beta1 + 1.0 );
  mbasis(1,3) = - 2.0 * ( beta2 + beta1 * beta1 + beta1 + 1.0 );
  mbasis(1,4) =   2.0;

  mbasis(2,1) =   6.0 * beta1 * beta1 * beta1;
  mbasis(2,2) = - 3.0 * beta2 ...
    - 6.0 * beta1 * beta1 * ( beta1 + 1.0 );
  mbasis(2,3) =   3.0 * beta2 + 6.0 * beta1 * beta1;
  mbasis(2,4) =   0.0;

  mbasis(3,1) = - 6.0 * beta1 * beta1 * beta1;
  mbasis(3,2) =   6.0 * beta1 * ( beta1 - 1.0 ) * ( beta1 + 1.0 );
  mbasis(3,3) =   6.0 * beta1;
  mbasis(3,4) =   0.0;

  mbasis(4,1) =   2.0 * beta1 * beta1 * beta1;
  mbasis(4,2) =   4.0 * beta1 * ( beta1 + 1.0 ) + beta2;
  mbasis(4,3) =   2.0;
  mbasis(4,4) =   0.0;

  delta = ( ( 2.0   ...
    * beta1 + 4.0 ) ...
    * beta1 + 4.0 ) ...
    * beta1 + 2.0 + beta2;

  mbasis(1:4,1:4) = mbasis(1:4,1:4) / delta;

  return
end


function [pval, k, K] = circ_kuipertest(alpha1, alpha2, res, vis_on)

% [pval, k, K] = circ_kuipertest(sample1, sample2, res, vis_on)
%
%   The Kuiper two-sample test tests whether the two samples differ
%   significantly.The difference can be in any property, such as mean
%   location and dispersion. It is a circular analogue of the
%   Kolmogorov-Smirnov test.
%
%   H0: The two distributions are identical.
%   HA: The two distributions are different.
%
% Input:
%   alpha1    fist sample (in radians)
%   alpha2    second sample (in radians)
%   res       resolution at which the cdf is evaluated
%   vis_on    display graph
%
% Output:
%   pval        p-value; the smallest of .10, .05, .02, .01, .005, .002,
%               .001, for which the test statistic is still higher
%               than the respective critical value. this is due to
%               the use of tabulated values. if p>.1, pval is set to 1.
%   k           test statistic
%   K           critical value
%
% References:
%   Batschelet, 1980, p. 112
%
% Circular Statistics Toolbox for Matlab

% Update 2012
% By Marc J. Velasco and Philipp Berens, 2009
% velasco@ccs.fau.edu

if nargin < 3
    res = 100;
end
if nargin < 4
    vis_on = 0;
end

n = length(alpha1(:));
m = length(alpha2(:));

% create cdfs of both samples
[phis1 cdf1 phiplot1 cdfplot1] = circ_samplecdf(alpha1, res);
[foo, cdf2 phiplot2 cdfplot2] = circ_samplecdf(alpha2, res); %#ok<ASGLU>

% maximal difference between sample cdfs
[dplus, gdpi] = max([0 cdf1-cdf2]);
[dminus, gdmi] = max([0 cdf2-cdf1]);

% calculate k-statistic
k = n * m * (dplus + dminus);

% find p-value
[pval K] = kuiperlookup(min(n,m),k/sqrt(n*m*(n+m)));
K = K * sqrt(n*m*(n+m));

% visualize
if vis_on
    figure
    plot(phiplot1, cdfplot1, 'b', phiplot2, cdfplot2, 'r');
    hold on
    plot([phis1(gdpi-1), phis1(gdpi-1)], [cdf1(gdpi-1) cdf2(gdpi-1)], 'o:g');
    plot([phis1(gdmi-1), phis1(gdmi-1)], [cdf1(gdmi-1) cdf2(gdmi-1)], 'o:g');
    hold off
    set(gca, 'XLim', [0, 2*pi]);
    set(gca, 'YLim', [0, 1.1]);
    xlabel('Circular Location')
    ylabel('Sample CDF')
    title('CircStat: Kuiper test')
    h = legend('Sample 1', 'Sample 2', 'Location', 'Southeast');
    set(h,'box','off')
    set(gca, 'XTick', pi*(0:.25:2))
    set(gca, 'XTickLabel', {'0', '', '', '', 'pi', '', '', '', '2pi'})
end

end

function [p K] = kuiperlookup(n, k)

load kuipertable.mat;
alpha = [.10, .05, .02, .01, .005, .002, .001];
nn = ktable(:,1);  %#ok<NODEF>

% find correct row of the table
[easy row] = ismember(n, nn);
if ~easy
   % find closest value if no entry is present)
   row = length(nn) - sum(n<nn);
   if row == 0
       error('N too small.');
   else
      warning('N=%d not found in table, using closest N=%d present.',n,nn(row)) %#ok<WNTAG>
   end
end

% find minimal p-value and test-statistic
idx = find(ktable(row,2:end)<k,1,'last');
if ~isempty(idx)
  p = alpha(idx);
else
  p = 1;
end
K = ktable(row,idx+1);

end


function bernstein_polynomial_test04 ( )

%*****************************************************************************80
%
%% BERNSTEIN_POLYNOMIAL_TEST04 tests BERNSTEIN_POLY_AB_APPROX.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 July 2011
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'BERNSTEIN_POLYNOMIAL_TEST04\n' );
  fprintf ( 1, '  BERNSTEIN_POLY_AB_APPROX evaluates the Bernstein polynomial\n' );
  fprintf ( 1, '  approximant to a function F(X).\n' );

  a = 1.0;
  b = 3.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, '     N      Max Error\n' );
  fprintf ( 1, '\n' );

  for degree = 0 : 20
%
%  Generate data values.
%
    xdata = zeros ( degree + 1, 1 );
    ydata = zeros ( degree + 1, 1 );

    for i = 0 : degree

      if ( degree == 0 )
        xdata(i+1) = 0.5 * ( a + b );
      else
        xdata(i+1) = ( ( degree - i ) * a   ...
                     + (          i ) * b ) ...
                     / ( degree     );
      end

      ydata(i+1) = sin ( xdata(i+1) );

    end
%
%  Compare the true function and the approximant.
%
    nval = 501;

    xval = linspace ( a, b, nval );

    yval = bernstein_poly_ab_approx ( degree, a, b, ydata, nval, xval );

    error_max = max ( abs ( yval(1:nval) - sin ( xval(1:nval) ) ) );

    fprintf ( 1, '  %4d  %14.6g\n', degree, error_max );

  end

  return
end


function P = vecperm(m, n)
%VECPERM    Vec-permutation matrix.
%           VECPERM(M, N) is the vec-permutation matrix, an MN-by-MN
%           permutation matrix P with the property that if A is M-by-N then
%           vec(A) = P*vec(A').
%           If N is omitted, it defaults to M.

%   P is formed by taking every n'th row from EYE(M*N), starting with
%   the first and working down - see p. 277 of the reference.

%   Reference:
%   H. V. Henderson and S. R. Searle The vec-permutation matrix,
%   the vec operator and Kronecker products: A review Linear and
%   Multilinear Algebra, 9 (1981), pp. 271-288.

if nargin == 1, n = m; end

P = zeros(m*n);
I = eye(m*n);

k = 1;
for i=1:n
    for j=i:n:m*n
        P(k,:) = I(j,:);
        k = k+1;
    end
end
end


function [p1ext p2ext degen] = extline(p1, p2, imgwidth, imgheight)
% p1: [x y]
% p2: [x y]

dir = p2 - p1;

% intersection with top
% p1(1) + alpha*dir(2) = 1
% int1 = p1 + alpha*dir
alpha = (1 - p1(2)) / dir(2);
intp{1} = p1 + alpha*dir;
intp{1}(2) = 1; % numerical precision issues....
intp{1} = intp{1}(:)'; % [2x1]

% intersection with bottom
% p1(1) + alpha*dir(2) = imgheight
% int2 = p1 + alpha*dir
alpha = (imgheight - p1(2)) / dir(2);
intp{2} = p1 + alpha*dir;
intp{2}(2) = imgheight; % numerical precision issues....
intp{2} = intp{2}(:)'; % [2x1]

% intersection with left
% p1(2) + alpha*dir(1) = 1
% int3 = p1 + alpha*dir
alpha = (1 - p1(1)) / dir(1);
intp{3} = p1 + alpha*dir;
intp{3}(1) = 1; % numerical precision issues....
intp{3} = intp{3}(:)'; % [2x1]

% intersection with right
% p1(2) + alpha*dir(2) = imgwidth
% int4 = p1 + alpha*dir
alpha = (imgwidth - p1(1)) / dir(1);
intp{4} = p1 + alpha*dir;
intp{4}(1) = imgwidth; % numerical precision issues....
intp{4} = intp{4}(:)'; % [2x1]

b(1) = isinimage(intp{1}, imgwidth, imgheight);
b(2) = isinimage(intp{2}, imgwidth, imgheight);
b(3) = isinimage(intp{3}, imgwidth, imgheight);
b(4) = isinimage(intp{4}, imgwidth, imgheight);

% should touch at least 2 edges
% greater than 2 when intersects exactly at corner of image
% assert(b(1)+b(2)+b(3)+b(4) >= 2);
if b(1)+b(2)+b(3)+b(4) < 2
    degen = 1;
    p1ext = [0 0];
    p2ext = [0 0];
    return;
else
    degen = 0;
end

% b = find(b);
% p1ext = intp{b(1)};
% p2ext = intp{b(2)};

p = cat(1, intp{logical(b)});
% p = unique(p, 'rows');
% assert(size(p,1)==2);
p1ext = p(1,:);
p2ext = p(2,:);

%%
function flag = isinimage(p, imgwidth, imgheight)
if p(1)>=1 && p(1)<=imgwidth && p(2)>=1 && p(2)<=imgheight
    flag = 1;
else
    flag = 0;
end


function r = msmoothboxrnd(a,b,sigma,n)
%MSMOOTHBOXRND Random arrays from the multivariate smooth-box distribution.
%   R = MSMOOTHBOXRND(A,B,SIGMA) returns an N-by-D matrix R of random
%   vectors chosen from the multivariate smooth-box distribution
%   with pivots A and B and scale SIGMA. A, B and SIGMA are N-by-D matrices,
%   and MSMOOTHBOXRND generates each row of R using the corresponding row
%   of A, B and SIGMA.
%
%   R = MSMOOTHBOXRND(A,B,SIGMA,N) returns a N-by-D matrix R of random
%   vectors chosen from the multivariate smooth-box distribution
%   with pivots A and B and scale SIGMA.
%
%   See also MSMOOTHBOXPDF.

% Luigi Acerbi 2022

[Na,Da] = size(a);
[Nb,Db] = size(b);
[Nsigma,Dsigma] = size(sigma);

if any(sigma(:) <= 0)
    error('msmoothboxrnd:NonPositiveSigma', ...
        'All elements of SIGMA should be positive.');
end

if nargin < 4 || isempty(n)
    n = max([Na,Nb,Nsigma]);
else
    if (Na ~= 1 && Na ~= n) || (Nb ~= 1 && Nb ~= n) || ...
            (Nsigma ~= 1 && Nsigma ~= n)
        error('msmoothboxrnd:SizeError', ...
            'A, B, SIGMA should be 1-by-D or N-by-D arrays.');
    end
end
if Na ~= Nb || Da ~= Db || Na ~= Nsigma || Da ~= Dsigma
    error('msmoothboxrnd:SizeError', ...
        'A, B, SIGMA should be arrays of the same size.');
end

D = Da;

if size(a,1) == 1; a = repmat(a,[n,1]); end
if size(b,1) == 1; b = repmat(b,[n,1]); end
if size(sigma,1) == 1; sigma = repmat(sigma,[n,1]); end

r = zeros(n,D);

nf = 1 + 1/sqrt(2*pi)./sigma.*(b - a);

% Sample one dimension at a time
for d = 1:D
    % Draw component (left/right tails or plateau)
    u = nf(:,d) .* rand(n,1);

    % Left Gaussian tails
    idx = u < 0.5;
    if any(idx)
        z1 = abs(randn(sum(idx),1).*sigma(idx,d));
        r(idx,d) = a(idx) - z1;
    end

    % Right Gaussian tails
    idx = (u >= 0.5 & u < 1);
    if any(idx)
        z1 = abs(randn(sum(idx),1).*sigma(idx,d));
        r(idx,d) = b(idx) + z1;
    end

    % Plateau
    idx = u >= 1;
    if any(idx)
        r(idx,d) = a(idx,d) + (b(idx,d) - a(idx,d)).*rand(sum(idx),1);
    end
end


function c = i4_division ( a, b )

%*****************************************************************************80
%
%% I4_DIVISION returns the result of integer division.
%
%  Discussion:
%
%    This routine computes C = A / B, where the result is rounded to the
%    integer value nearest 0.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer A, B, the number to be divided,
%    and the divisor.
%
%    Output, integer C, the rounded result of the division.
%
  if ( a * b < 0.0 )
    s = -1;
  else
    s = +1;
  end

  a = abs ( a );
  b = abs ( b );
  c = s * floor ( a / b );

  return
end


  function xs = alg_art1(x, At, y, varargin)
%|function xs = alg_art1(x, At, y, [options])
%| classical ART algorithm, aka, Kaczmarz algorithm; tries to solve y=Ax
%|
%| in
%|	x	[np 1]		initial guess, possibly empty
%|	Caution: x must be in the range of A' for convergence!
%|	At	[np nd]		(hermitian) *transpose* of system matrix
%|	y	[nb na]		measurement
%|
%| option
%|	wi	[nb na]		weights
%|	niter			# of iterations
%|	isave			default: [] 'last'
%|	pixmin
%|	pixmax
%|	anorms	[nd 1]		see below
%|	eps
%|
%| out
%|	xs	[np niter]	iterates
%|
%| Copyright 2006-4-2, Jeff Fessler, University of Michigan

if nargin == 1 && streq(x, 'test'), alg_art1_test, return, end
if nargin < 3, ir_usage, end
if isempty(x), x = zeros(nrow(A),1); end

% defaults
arg.niter = 1;
arg.isave = [];
arg.anorms = [];
arg.eps = eps;
%arg.pixmax = inf;
%arg.pixmin = -inf;

% options
arg = vararg_pair(arg, varargin);

arg.isave = iter_saver(arg.isave, arg.niter);

[nb na] = size(y);
starts = subset_start(na);

% For WLS, premultiply y and postmultiply At by W^{1/2}
%Wh = spdiag(sqrt(wi(:)), 'nowarn');
%y = Wh * y(:);
%At = At * Wh;

% weighted row norms
if isempty(arg.anorms)
	arg.anorms = sum(At.^2); % | e_i' A |^2
end

iglist = col(outer_sum(1:nb, (starts-1)*nb));
iglist = iglist(arg.anorms(iglist) ~= 0);

adenom = arg.anorms + eps; % trick:

np = length(x);
xs = zeros(np, length(arg.isave));
if any(arg.isave == 0)
	xs(:, arg.isave == 0) = x;
end

ticker(mfilename, 1, arg.niter)

for iter=1:arg.niter
	ticker(mfilename, iter, arg.niter)

	for ii=iglist'
		ai = At(:,ii);
		step = (y(ii) - ai' * x) / adenom(ii);
		x = x + ai * step;

%		todo: try following approach to see if faster
%		[j ignore ai] = find(At(:,ii));
%		xj = x(j);
%		step = (y(ii) - ai' * xj) / adenom(ii);
%		x(j) = xj - step * ai;
	end

	if any(arg.isave == iter)
		xs(:, arg.isave == iter) = x;
	end
end


function result = graph_adj_is_node_connected ( adj, nnode )

%*****************************************************************************80
%
%% GRAPH_ADJ_IS_NODE_CONNECTED determines if a graph is nodewise connected.
%
%  Definition:
%
%    A graph is nodewise connected if, from every node, there is a path
%    to any other node.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 June 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer ADJ(NNODE,NNODE), the adjacency matrix for the
%    graph.  ADJ(I,J) is nonzero if there is an edge from node I to node J.
%
%    Input, integer NNODE, the number of nodes.
%
%    Output, integer RESULT.
%    0, the graph is not nodewise connected.
%    1, the graph is nodewise connected.
%

%
%  FOUND(I) is 1 if node I has been reached.
%  LIST(I) contains a list of the nodes as they are reached.
%
  list(1:nnode) = 0;
  found(1:nnode) = 0;
%
%  Start at node 1.
%
  found(1) = 1;
  list(1) = 1;
  ilo = 1;
  ihi = 1;
%
%  From the batch of nodes found last time, LIST(ILO:IHI),
%  look for unfound neighbors, and store their indices in LIST(JLO:JHI).
%
  while ( 1 )

    jlo = ihi + 1;
    jhi = ihi;

    for ii = ilo : ihi

      i = list(ii);

      for j = 1 : nnode

        if ( adj(i,j) ~= 0 || adj(j,i) ~= 0 )

          if ( found(j) == 0 )
            jhi = jhi + 1;
            list(jhi) = j;
            found(j) = 1;
          end

        end

      end

    end
%
%  If no neighbors were found, exit.
%
    if ( jhi < jlo )
      break
    end
%
%  If neighbors were found, then go back and find THEIR neighbors.
%
    ilo = jlo;
    ihi = jhi;

  end
%
%  No more neighbors were found.  Have we reached all nodes?
%
  if ( ihi == nnode )
    result = 1;
  else
    result = 0;
  end

  return
end


function integral = sphere01_monomial_integral ( e )

%*****************************************************************************80
%
%% SPHERE01_MONOMIAL_INTEGRAL returns monomial integrals on the unit sphere.
%
%  Discussion:
%
%    The integration region is
%
%      X^2 + Y^2 + Z^2 = 1.
%
%    The monomial is F(X,Y,Z) = X^E(1) * Y^E(2) * Z^E(3).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 September 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Philip Davis, Philip Rabinowitz,
%    Methods of Numerical Integration,
%    Second Edition,
%    Academic Press, 1984, page 263.
%
%  Parameters:
%
%    Input, integer E(3), the exponents of X, Y and Z in the
%    monomial.  Each exponent must be nonnegative.
%
%    Output, real INTEGRAL, the integral.
%
  if ( any ( e(1:3) < 0 ) )
    integral = - Inf;
    fprintf ( 1, '\n' );
    fprintf ( 1, 'SPHERE01_MONOMIAL_INTEGRAL - Fatal error!\n' );
    fprintf ( 1, '  All exponents must be nonnegative.\n' );
    fprintf ( 1, '  E(1) = %d\n', e(1) );
    fprintf ( 1, '  E(2) = %d\n', e(2) );
    fprintf ( 1, '  E(3) = %d\n', e(3) );
    error ( 'SPHERE01_MONOMIAL_INTEGRAL - Fatal error!' );
  end

  if ( all ( e(1:3) == 0 ) )

    integral = 2.0 * sqrt ( pi^3 ) / gamma ( 1.5 );

  elseif ( any ( mod ( e(1:3), 2 ) == 1 ) )

    integral = 0.0;

  else

    integral = 2.0;

    for i = 1 : 3
      integral = integral * gamma ( 0.5 * ( e(i) + 1 ) );
    end

    integral = integral / gamma ( 0.5 * sum ( e(1:3) + 1 ) );

  end

  return
end


function [R Rx Ry Rz] = angles2rotmat(angles)
% [R Rx Ry Rz] = angles2rotmat(angles)
%
% Convert 3 euler angles into a rotation matrix
%
% angles is a 3x1 vector in radians
% angles(1) - pitch - rotation about x or LR (gamma)
% angles(2) - yaw   - rotation about y or AP (beta)
% angles(3) - roll  - rotation about z or SI (alpha)
% R = Rz*Ry*Rx;
%
% See also: rotmat2angles
% Ref: Craig, Intro to Robotics
%
% $Id: angles2rotmat.m,v 1.4 2011/03/02 00:04:12 nicks Exp $

%
% angles2rotmat.m
%
% Original Author: Doug Greve
% CVS Revision Info:
%    $Author: nicks $
%    $Date: 2011/03/02 00:04:12 $
%    $Revision: 1.4 $
%
% Copyright © 2011 The General Hospital Corporation (Boston, MA) "MGH"
%
% Terms and conditions for use, reproduction, distribution and contribution
% are found in the 'FreeSurfer Software License Agreement' contained
% in the file 'LICENSE' found in the FreeSurfer distribution, and here:
%
% https://surfer.nmr.mgh.harvard.edu/fswiki/FreeSurferSoftwareLicense
%
% Reporting: freesurfer@nmr.mgh.harvard.edu
%

R  = [];
Rx = [];
Ry = [];
Rz = [];
if(nargin ~= 1)
  fprintf('R = angles2rotmat(angles)\n');
  return;
end

gamma = angles(1);
beta  = angles(2);
alpha = angles(3);

Rx = zeros(3,3);
Rx(1,1) = +1;
Rx(2,2) = +cos(gamma);
Rx(2,3) = -sin(gamma);
Rx(3,2) = +sin(gamma);
Rx(3,3) = +cos(gamma);

Ry = zeros(3,3);
Ry(1,1) = +cos(beta);
Ry(1,3) = +sin(beta);
Ry(2,2) = +1;
Ry(3,1) = -sin(beta);
Ry(3,3) = +cos(beta);

Rz = zeros(3,3);
Rz(1,1) = +cos(alpha);
Rz(1,2) = -sin(alpha);
Rz(2,1) = +sin(alpha);
Rz(2,2) = +cos(alpha);
Rz(3,3) = +1;

R = Rz*Ry*Rx;

return;


function [ pp, normal ] = plane_exp2normal_3d ( p1, p2, p3 )

%*****************************************************************************80
%
%% PLANE_EXP2NORMAL_3D converts an explicit plane to normal form in 3D.
%
%  Discussion:
%
%    The explicit form of a plane in 3D is
%
%      the plane through P1, P2 and P3.
%
%    The normal form of a plane in 3D is
%
%      PP, a point on the plane, and
%      N, the unit normal to the plane.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real P1(3), P2(3), P3(3), three points on the plane.
%
%    Output, real PP(3), a point on the plane.
%
%    Output, real NORMAL(3), a unit normal vector to the plane.
%
  dim_num = 3;

  pp(1:dim_num) = p1(1:dim_num);

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

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

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

  norm = sqrt ( sum ( normal(1:dim_num).^2 ) );

  if ( norm == 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'PLANE_EXP2NORMAL_3D - Fatal error!\n' );
    fprintf ( 1, '  The normal vector is null.\n' );
    fprintf ( 1, '  Two points coincide, or nearly so.\n' );
    error ( 'PLANE_EXP2NORMAL_3D - Fatal error!' );
  end

  normal(1:dim_num) = normal(1:dim_num) / norm;

  return
end


clc
clear
hold on

n=100;          % number of intervals (i.e. parametric curve would be evaluted n+1 times)
k=0.5522847498; % kappa (See documentation how this value is obtained)

% First Quadrant
Px=[1 1 k 0];
Py=[0 k 1 1];

PlotBezier1(Px,Py,n);

% Second Quadrant
Px=[0 -k -1 -1];
Py=[1  1  k  0];
PlotBezier1(Px,Py,n)

% Third Quadrant
Px=[-1 -1 -k  0];
Py=[ 0 -k -1 -1];
PlotBezier1(Px,Py,n)

% Fourth Quadrant
Px=[ 0  k  1 1];
Py=[-1 -1 -k 0];
PlotBezier1(Px,Py,n)

title('Approximation of Circle using Cubic Bezier');

hold off

% % % --------------------------------
% % % Author: Dr. Murtaza Khan
% % % Email : drkhanmurtaza@gmail.com
% % % --------------------------------


function y = testfunctions(varargin)
% TESTFUNCTIONS   Integration test functions of A. Genz
%    Y = TESTFUNCTIONS(X1, X2, ..., XD, TYPE, C, W) Evaluates test
%    function TYPE at the point (X1,...,XN). C and W are arrays of
%    constants defining the test function (see below). The test
%    functions are defined according to A. Genz: A package for
%    testing multiple integration subroutines, in Numerical
%    Integration, P. Keast and G. Fairweather (Eds.), D. Riedel,
%    pp. 337-340, 1987. The functions are defined on [0 1]^d.
%
% TYPE = 'oscillatory'   | TYPE = 1:
% f(x) = cos(2*pi*w_1 + sum_{i=1}^d ( c_i * x_i ) )
%
% TYPE = 'product peak'  | TYPE = 2:
% f(x) = prod_{i=1}^d ( c_i^{-2} + (x_i - w_i)^2 )^{-1}
%
% TYPE = 'corner peak'   | TYPE = 3:
% f(x) = ( 1 + sum_{i=1}^d (c_i * x_i) )^(-(d+1))
%
% TYPE = 'gaussian'      | TYPE = 4:
% f(x) = exp( - sum_{i=1}^d c_i^2 * (x_i - w_i)^2 )
%
% TYPE = 'continuous'    | TYPE = 5:
% f(x) = exp( - sum_{i=1}^d c_i * abs(x_i - w_i) )
%
% TYPE = 'discontinuous' | TYPE = 6:
% f(x) = { 0                            , if x_1>w_1 or x_2>w_2,
%        { exp( sum_{i=1}^d c_i * x_i ) , otherwise
%
% With the parameters c = (c_1, ..., c_d) and w = (w_1, ..., w_d).
% d denotes the dimension of the function.
%
% Examples:
%    testfunctions(0.5, 0.5, 'product peak', [2, 5.25], [0.2, 0.7])
%    testfunctions(0.5, 0.5, 2, [2, 5.25], [0.2, 0.7])
%
%    x = linspace(0,1,20);
%    [X,Y] = meshgrid(x,x);
%    surf(X,Y, ...
%      testfunctions(X, Y, 'product peak', [2, 5.25], [0.2 0.7]));

% Author : Andreas Klimke, Universitaet Stuttgart
% Version: 1.0
% Date   : August 2, 2003

% ------------------------------------------------------------
% Sparse Grid Interpolation Toolbox
% Copyright (c) 2006 W. Andreas Klimke, Universitaet Stuttgart
% Copyright (c) 2007-2008 W. A. Klimke. All Rights Reserved.
% See LICENSE.txt for license.
% email: klimkeas@ians.uni-stuttgart.de
% web  : http://www.ians.uni-stuttgart.de/spinterp
% ------------------------------------------------------------

type = varargin{end-2};
c = varargin{end-1};
w = varargin{end};

if isa(type, 'char')
	fnames = {'oscillatory', 'product peak', 'corner peak', 'gaussian', ...
						'continuous', 'discontinuous'};
	for k = 1:length(fnames)
		if strcmp(fnames{k},type)
			type = k;
			break
		end
	end
end

d = length(c);

switch type
 case 1  % oscillatory
	temp = 2*pi*w(1);
	for i = 1:d
		temp = temp + c(i).*varargin{i};
	end
	y = cos(temp);

 case 2  % product peak
	temp = 1;
	for i = 1:d
		temp = temp .* (c(i)^(-2)+(varargin{i}-w(i)).^2);
	end
	y = 1./temp;

 case 3  % corner peak
	temp = 1;
	for i = 1:d
		temp = temp + c(i).*varargin{i};
	end
	y = temp .^ (-(d+1));

 case 4  % gaussian
	temp = 0;
	for i = 1:d
		temp = temp + c(i)^2 .* (varargin{i} - w(i)).^2;
	end
	y = exp(-temp);

 case 5  % continuous
	temp = 0;
	for i = 1:d
		temp = temp + c(i) .* abs(varargin{i} - w(i));
	end
	y = exp(-temp);

 case 6  % discontinuous
	temp = 0;
	if d >= 2
		mask = varargin{1} > w(1) | varargin{2} > w(2);
	else
		mask = varargin{1} > w(1);
	end
	for i = 1:d
		temp = temp + (c(i) .* varargin{i});
	end
	y = exp(temp) .* (~mask);
end


function [normed_traindata,normed_testdata ] = normalization(traindata,testdata)
% Calculating mean and standard deviation of train samples on each band
% Using calculated mean and standard deviation to perform normalization on
% both train samples and test samples

mean_val=mean(traindata,1);
sigma_val=std(traindata,0,1);

traindata=bsxfun(@minus,traindata,mean_val);
normed_traindata=bsxfun(@rdivide,traindata,sigma_val);

testdata=bsxfun(@minus,testdata,mean_val);
normed_testdata=bsxfun(@rdivide,testdata,sigma_val);

%selTrainData=bsxfun(@rdivide,selTrainData,sum(selTrainData,2));
%selTestData=bsxfun(@rdivide,selTestData,sum(selTestData,2));

% mean_val = mean(traindata,1);
% normed_traindata = bsxfun(@minus,traindata,mean_val);
%
% sigma_val = std(normed_traindata,0,1);
% normed_traindata = bsxfun(@rdivide,normed_traindata,sigma_val);
% normed_testdata = bsxfun(@minus,testdata,mean_val);
% normed_testdata = bsxfun(@rdivide,normed_testdata,sigma_val);