function [ x, seed ] = ball_unit_sample_nd ( n, seed )

%*****************************************************************************80
%
%% BALL_UNIT_SAMPLE_ND picks a random point in the unit ball in ND.
%
%  Discussion:
%
%    N-1 random Givens rotations are applied to the point ( 1, 0, 0, ..., 0 ).
%
%    The I-th Givens rotation is in the plane of coordinate axes I and I+1,
%    and has the form:
%
%     [ cos ( theta )  - sin ( theta ) ] * x(i)      = x'(i)
%     [ sin ( theta )    cos ( theta ) ]   x(i+1)      x'(i+1)
%
%    Finally, a scaling is applied to set the point at a distance R
%    from the center, in a way that results in a uniform distribution.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 June 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the dimension of the space.
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, real X(N), the random point.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
  x(1) = 1.0;
  x(2:n) = 0.0;

  for i = 1 : n-1

    [ r, seed ] = r8_uniform_01 ( seed );
    random_cosine = 2.0 * r - 1.0;
    [ r, seed ] = r8_uniform_01 ( seed );
    random_sign = 2 * floor ( 2.0 * r ) - 1;
    [ r, seed ] = r8_uniform_01 ( seed );
    random_sine = random_sign * sqrt ( 1.0 - random_cosine * random_cosine );

    xi = x(i);
    x(i  ) = random_cosine * xi;
    x(i+1) = random_sine   * xi;

  end

  [ r, seed ] = r8_uniform_01 ( seed );

  r = r^( 1.0 / n );

  x(1:n) = r * x(1:n);

  return
end


%% Learns the weights of a perceptron and displays the results.
function [w] = learn_perceptron(neg_examples_nobias,pos_examples_nobias,w_init,w_gen_feas)
%%
% Learns the weights of a perceptron for a 2-dimensional dataset and plots
% the perceptron at each iteration where an iteration is defined as one
% full pass through the data. If a generously feasible weight vector
% is provided then the visualization will also show the distance
% of the learned weight vectors to the generously feasible weight vector.
% Required Inputs:
%   neg_examples_nobias - The num_neg_examples x 2 matrix for the examples with target 0.
%       num_neg_examples is the number of examples for the negative class.
%   pos_examples_nobias - The num_pos_examples x 2 matrix for the examples with target 1.
%       num_pos_examples is the number of examples for the positive class.
%   w_init - A 3-dimensional initial weight vector. The last element is the bias.
%   w_gen_feas - A generously feasible weight vector.
% Returns:
%   w - The learned weight vector.
%%

%Bookkeeping
num_neg_examples = size(neg_examples_nobias,1);
num_pos_examples = size(pos_examples_nobias,1);
num_err_history = [];
w_dist_history = [];

%Here we add a column of ones to the examples in order to allow us to learn
%bias parameters.
neg_examples = [neg_examples_nobias,ones(num_neg_examples,1)];
pos_examples = [pos_examples_nobias,ones(num_pos_examples,1)];

%If weight vectors have not been provided, initialize them appropriately.
if (~exist('w_init','var') || isempty(w_init))
    w = randn(3,1);
else
    w = w_init;
end

if (~exist('w_gen_feas','var'))
    w_gen_feas = [];
end

%Find the data points that the perceptron has incorrectly classified
%and record the number of errors it makes.
iter = 0;
[mistakes0, mistakes1] = eval_perceptron(neg_examples,pos_examples,w);
num_errs = size(mistakes0,1) + size(mistakes1,1);
num_err_history(end+1) = num_errs;
fprintf('Number of errors in iteration %d:\t%d\n',iter,num_errs);
fprintf(['weights:\t', mat2str(w), '\n']);
plot_perceptron(neg_examples, pos_examples, mistakes0, mistakes1, num_err_history, w, w_dist_history);
key = input('<Press enter to continue, q to quit.>', 's');
if (key == 'q')
    return;
end

%If a generously feasible weight vector exists, record the distance
%to it from the initial weight vector.
if (length(w_gen_feas) ~= 0)
    w_dist_history(end+1) = norm(w - w_gen_feas);
end

%Iterate until the perceptron has correctly classified all points.
while (num_errs > 0)
    iter = iter + 1;

    %Update the weights of the perceptron.
    w = update_weights(neg_examples,pos_examples,w);

    %If a generously feasible weight vector exists, record the distance
    %to it from the current weight vector.
    if (length(w_gen_feas) ~= 0)
        w_dist_history(end+1) = norm(w - w_gen_feas);
    end

    %Find the data points that the perceptron has incorrectly classified.
    %and record the number of errors it makes.
    [mistakes0, mistakes1] = eval_perceptron(neg_examples,pos_examples,w);
    num_errs = size(mistakes0,1) + size(mistakes1,1);
    num_err_history(end+1) = num_errs;

    fprintf('Number of errors in iteration %d:\t%d\n',iter,num_errs);
    fprintf(['weights:\t', mat2str(w), '\n']);
    plot_perceptron(neg_examples, pos_examples, mistakes0, mistakes1, num_err_history, w, w_dist_history);
    key = input('<Press enter to continue, q to quit.>', 's');
    if (key == 'q')
        break;
    end
end

%WRITE THE CODE TO COMPLETE THIS FUNCTION
function [w] = update_weights(neg_examples, pos_examples, w_current)
%%
% Updates the weights of the perceptron for incorrectly classified points
% using the perceptron update algorithm. This function makes one sweep
% over the dataset.
% Inputs:
%   neg_examples - The num_neg_examples x 3 matrix for the examples with target 0.
%       num_neg_examples is the number of examples for the negative class.
%   pos_examples- The num_pos_examples x 3 matrix for the examples with target 1.
%       num_pos_examples is the number of examples for the positive class.
%   w_current - A 3-dimensional weight vector, the last element is the bias.
% Returns:
%   w - The weight vector after one pass through the dataset using the perceptron
%       learning rule.
%%
w = w_current;
num_neg_examples = size(neg_examples,1);
num_pos_examples = size(pos_examples,1);
for i=1:num_neg_examples
    this_case = neg_examples(i,:);
    x = this_case'; %Hint
    activation = this_case*w;
    if (activation >= 0)
        %YOUR CODE HERE
        w = w - x;
    end
end
for i=1:num_pos_examples
    this_case = pos_examples(i,:);
    x = this_case';
    activation = this_case*w;
    if (activation < 0)
        %YOUR CODE HERE
        w = w + x;
    end
end

function [mistakes0, mistakes1] =  eval_perceptron(neg_examples, pos_examples, w)
%%
% Evaluates the perceptron using a given weight vector. Here, evaluation
% refers to finding the data points that the perceptron incorrectly classifies.
% Inputs:
%   neg_examples - The num_neg_examples x 3 matrix for the examples with target 0.
%       num_neg_examples is the number of examples for the negative class.
%   pos_examples- The num_pos_examples x 3 matrix for the examples with target 1.
%       num_pos_examples is the number of examples for the positive class.
%   w - A 3-dimensional weight vector, the last element is the bias.
% Returns:
%   mistakes0 - A vector containing the indices of the negative examples that have been
%       incorrectly classified as positive.
%   mistakes0 - A vector containing the indices of the positive examples that have been
%       incorrectly classified as negative.
%%
num_neg_examples = size(neg_examples,1);
num_pos_examples = size(pos_examples,1);
mistakes0 = [];
mistakes1 = [];
for i=1:num_neg_examples
    x = neg_examples(i,:)';
    activation = x'*w;
    if (activation >= 0)
        mistakes0 = [mistakes0;i];
    end
end
for i=1:num_pos_examples
    x = pos_examples(i,:)';
    activation = x'*w;
    if (activation < 0)
        mistakes1 = [mistakes1;i];
    end
end


function b = r8but_to_r8ge ( n, mu, a )

%*****************************************************************************80
%
%% R8BUT_TO_R8GE copies a R8BUT matrix to a R8GE matrix.
%
%  Discussion:
%
%    The R8BUT storage format is for a banded upper triangular matrix.
%
%    To save storage, only the diagonal and upper triangle of A is stored,
%    in a compact diagonal format that preserves columns.
%
%    The diagonal is stored in row MU+1 of the array.
%    The first superdiagonal in row MU, columns 2 through N.
%    The second superdiagonal in row MU-1, columns 3 through N.
%    The MU-th superdiagonal in row 1, columns MU+1 through N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 March 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrices.
%    N must be positive.
%
%    Input, integer MU, the upper bandwidth of A1.
%    MU must be nonnegative, and no greater than N-1.
%
%    Input, real A(MU+1,N), the R8BUT matrix.
%
%    Output, real B(N,N), the R8GE matrix.
%
  for i = 1 : n
    for j = 1 : n
      if ( i <= j & j <= i+mu )
        b(i,j) = a(mu+1+i-j,j);
      else
        b(i,j) = 0.0;
      end
    end
  end

  return
end


function mu_pq = moment_central ( n, x, y, p, q )

%*****************************************************************************80
%
%% MOMENT_CENTRAL computes central moments of a polygon.
%
%  Discussion:
%
%    The central moment Mu(P,Q) is defined by
%
%      Mu(P,Q) = Integral ( polygon ) (x-Alpha(1,0))^p (y-Alpha(0,1))^q dx dy
%              / Area ( polygon )
%
%    where
%
%      Alpha(1,0) = Integral ( polygon ) x dx dy / Area ( polygon )
%      Alpha(0,1) = Integral ( polygon ) y dx dy / Area ( polygon )
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 October 2012
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carsten Steger,
%    On the calculation of arbitrary moments of polygons,
%    Technical Report FGBV-96-05,
%    Forschungsgruppe Bildverstehen, Informatik IX,
%    Technische Universitaet Muenchen, October 1996.
%
%  Parameters:
%
%    Input, integer N, the number of vertices of the polygon.
%
%    Input, real X(N), Y(N), the vertex coordinates.
%
%    Input, integer P, Q, the indices of the moment.
%
%    Output, real MU_PQ, the unnormalized moment Mu(P,Q).
%
  alpha_10 = moment_normalized ( n, x, y, 1, 0 );
  alpha_01 = moment_normalized ( n, x, y, 0, 1 );

  mu_pq = 0.0;

  for i = 0 : p
    for j = 0 : q

      alpha_ij = moment_normalized ( n, x, y, i, j );

      mu_pq = mu_pq + r8_mop ( p + q - i - j ) ...
        * r8_choose ( p, i ) * r8_choose ( q, j ) ...
        * alpha_10 ^ ( p - i ) * alpha_01 ^ ( q - j ) * alpha_ij;

    end
  end

  return
end


function [I_dx, I_dy] = sobel5x5(img)
%SOBEL5X5 Apply Sobel–Feldman filter over input image
% Sobel filters are discrete differentiation operator. They are used to
% compute an approximation of the gradient of an image intensity function
%
% INPUT:
%   - img(image): Given input image
%
% OUTPUT:
%   - I_dx: gradient of image along x-axis
%   - I_dy: gradient of image along y-axis

% sobel kernels
sobel_kernel1 = [1, 4, 6, 4, 1];
sobel_kernel2 = [1, 2, 0, -2, -1];
divisor = 48;

% gradient along x
I_dx = conv2(sobel_kernel2', sobel_kernel1, img, 'valid');
I_dx = uint8(I_dx / divisor + 128);

% gradient along y
I_dy = conv2(sobel_kernel1', sobel_kernel2, img, 'valid');
I_dy = uint8(I_dy / divisor + 128);

% imshowpair(I_dx, I_dy, 'montage');
end


function a = minij ( m, n )

%*****************************************************************************80
%
%% MINIJ returns the MINIJ matrix.
%
%  Formula:
%
%    A(I,J) = min ( I, J )
%
%  Example:
%
%    N = 5
%
%    1 1 1 1 1
%    1 2 2 2 2
%    1 2 3 3 3
%    1 2 3 4 4
%    1 2 3 4 5
%
%  Properties:
%
%    A is integral, therefore det ( A ) is integral, and
%    det ( A ) * inverse ( A ) is integral.
%
%    A is positive definite.
%
%    A is symmetric: A' = A.
%
%    Because A is symmetric, it is normal.
%
%    Because A is normal, it is diagonalizable.
%
%    The inverse of A is tridiagonal.
%
%    The eigenvalues of A are
%
%      LAMBDA(I) = 0.5 / ( 1 - cos ( ( 2 * I - 1 ) * pi / ( 2 * N + 1 ) ) ),
%
%    For N = 12, the characteristic polynomial is
%      P(X) = X**12 - 78 X**11 + 1001 X**10 - 5005 X**9 + 12870 X**8
%        - 19448 X**7 + 18564 X**6 - 11628 X**5 + 4845 X**4 - 1330 X**3
%        + 231 X**2 - 23 X + 1.
%
%    (N+1)*ONES(N) - A also has a tridiagonal inverse.
%
%    Gregory and Karney consider the matrix defined by
%
%      B(I,J) = N + 1 - MAX(I,J)
%
%    which is equal to the MINIJ matrix, but with the rows and
%    columns reversed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Robert Gregory, David Karney,
%    Example 3.12, Example 4.14,
%    A Collection of Matrices for Testing Computational Algorithms,
%    Wiley, 1969, page 41, page 74,
%    LC: QA263.G68.
%
%    Daniel Rutherford,
%    Some continuant determinants arising in physics and chemistry II,
%    Proceedings of the Royal Society Edinburgh,
%    Volume 63, A, 1952, pages 232-241.
%
%    John Todd,
%    Basic Numerical Mathematics, Vol. 2: Numerical Algebra,
%    Academic Press, 1977, page 158.
%
%    Joan Westlake,
%    A Handbook of Numerical Matrix Inversion and Solution of
%    Linear Equations,
%    John Wiley, 1968,
%    ISBN13: 978-0471936756,
%    LC: QA263.W47.
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns
%    of the matrix.
%
%    Output, real A(M,N), the matrix.
%
  for i = 1 : m
    for j = 1 : n
      a(i,j) = min ( i, j );
    end
  end

  return
end


function [rlvm, frvals, frvecs, trnsfrmd, mn, dv] = TSTL_pca(data, mode, maxpercent, sil)

%   [rlvm, frvals, frvecs, trnsfrmd, mn, dv] = pca(data, mode, maxpercent, silent)
%
%   principal component analysis of column orientated data set <data>
%
%   input arguments :
%
%   - each row of data is one 'observation', e.g. the sample values of
%     all channels in a multichannel measurement at one point in time
%
%   - mode can be one of the following : 'normalized' (default), 'mean', 'raw'
%     - in mode 'normalized' each column of data is centered by removing its mean
%       and then normalized by dividing through its standard deviation before
%       the covariance matrix is calculated
%     - in mode 'mean' only the mean of every column of data is removed
%     - in mode 'raw' no preprocessing is applied to data
%
%   - maxpercent gives the limit of the accumulated percentage of the resulting
%     eigenvalues, default is 95 %
%
%   - silent is an optional flag which supresses output of text and plot on the matlab
%     screen. Returned values (see below) are in no way affected
%
%   output arguments :
%
%   - rlvm : number of relevant modes to reach maxpercent
%   - frvals : first rlvm relevant eigenvalues
%   - frvecs : first rlvm relevant eigenvectors (eigenmodes, or principal components)
%   - trnsfrmd : data points transformed to the coordinate system given be the eigenvectors
%   - mn : mean of the original data set (only in mode 'mean' and 'normalized')
%   - dv : standard deviation of the original data set (only in mode 'normalized')
%
%
%   To compute an approximation of data : data = trnsfrmd * frvecs'
%
%   Christian Merkwirth (cmerk) Maerz 1997
%   cmerk Jan.  1998

global silent

if nargin  < 1, help(mfilename); end

if nargin < 2
	mode = 'normalized';
end
if nargin < 3
	maxpercent = 95;
end
if nargin < 4
	silent = 0;
else
	silent = 1;
end

%rang = rank(data);
[n,m] = size(data);

printline('principal component analysis')
printline(['on data set of size ' num2str(n) 'x' num2str(m)]);	% ' with rank ' num2str(rang)])
printline(['eigenvalues are computed up to ' num2str(maxpercent) ' percent']);

maxpercent = maxpercent/100;
mode = lower(mode); 		% no problems with uppercase letters

if strncmp(mode, 'r',1)
	mode = 'raw';
	printline('no data preprocessing');
elseif strncmp(mode, 'm',1)
	mode = 'mean';
	printline('removing mean from data set');
	mn = mean(data);
	data = data - repmat(mn, n, 1);
else
	mode = 'normalized';
	printline('removing mean and normalizing data');
	mn = mean(data);
	dv = std(data);
	data = data - repmat(mn, n, 1);
	data = data ./ repmat(dv, n, 1);
end

%sum(mean(data))/m	% test
%sum(std(data))/m	% test

if n>m
	printline('using direct method to compute covariance matrix');
	K =   data' * data;       % oder K = corrcoef(data)
	[Q,D] = eig(K);
 else
    printline('using indirect method to compute covariance matrix');
 	C = data * data';
 	[Q,D] = eig(C);
end

[evalues,index] = sort(diag(D));
evalues = flipud(evalues);
index = flipud(index);

total = sum(evalues);
rlvm = min(find(cumsum(evalues) >= (total*maxpercent)));

if isempty(rlvm)			% in case percentage was choosen ober 100 %,
	rlvm = length(evalues); % return all eigenvalues
end

frvals = evalues(1:rlvm);

if n>m
	frvecs = Q(:, index(1:rlvm));
	trnsfrmd=data*frvecs;
 else
 	scalefac = 1./ sqrt(evalues(1:rlvm));
 	for i = 1:rlvm
 		P(:,i) = Q(:,index(i)) * scalefac(i);
 	end
 	frvecs = data' * P; % '
	trnsfrmd=C*P;
end

if silent~=1
	bar(100*frvals/total);
	title('Eigenvalues in percent');
end

function printline(string)
global silent
if silent~=1
	disp(string)
end


function [xnew, Vnew, loglik, VVnew] = kalman_update(A, C, Q, R, y, x, V, varargin)
% KALMAN_UPDATE Do a one step update of the Kalman filter
% [xnew, Vnew, loglik] = kalman_update(A, C, Q, R, y, x, V, ...)
%
% INPUTS:
% A - the system matrix
% C - the observation matrix
% Q - the system covariance
% R - the observation covariance
% y(:)   - the observation at time t
% x(:) - E[X | y(:, 1:t-1)] prior mean
% V(:,:) - Cov[X | y(:, 1:t-1)] prior covariance
%
% OPTIONAL INPUTS (string/value pairs [default in brackets])
% 'initial' - 1 means x and V are taken as initial conditions (so A and Q are ignored) [0]
% 'u'     - u(:) the control signal at time t [ [] ]
% 'B'     - the input regression matrix
%
% OUTPUTS (where X is the hidden state being estimated)
%  xnew(:) =   E[ X | y(:, 1:t) ]
%  Vnew(:,:) = Var[ X(t) | y(:, 1:t) ]
%  VVnew(:,:) = Cov[ X(t), X(t-1) | y(:, 1:t) ]
%  loglik = log P(y(:,t) | y(:,1:t-1)) log-likelihood of innovatio

% set default params
u = [];
B = [];
initial = 0;

args = varargin;
for i=1:2:length(args)
  switch args{i}
   case 'u', u = args{i+1};
   case 'B', B = args{i+1};
   case 'initial', initial = args{i+1};
   otherwise, error(['unrecognized argument ' args{i}])
  end
end

%  xpred(:) = E[X_t+1 | y(:, 1:t)]
%  Vpred(:,:) = Cov[X_t+1 | y(:, 1:t)]

if initial
  if isempty(u)
    xpred = x;
  else
    xpred = x + B*u;
  end
  Vpred = V;
else
  if isempty(u)
    xpred = A*x;
  else
    xpred = A*x + B*u;
  end
  Vpred = A*V*A' + Q;
end

e = y - C*xpred; % error (innovation)
n = length(e);
ss = length(A);
S = C*Vpred*C' + R;
Sinv = inv(S);
ss = length(V);
loglik = gaussian_prob(e, zeros(1,length(e)), S, 1);
K = Vpred*C'*Sinv; % Kalman gain matrix
% If there is no observation vector, set K = zeros(ss).
xnew = xpred + K*e;
Vnew = (eye(ss) - K*C)*Vpred;
VVnew = (eye(ss) - K*C)*A*V;


% stein9 0-1 integer program from MIPLIB 2.0 by George Nemhauser et al.,
% solving a nine item Steiner triple system
% See, e.g., http://miplib.zib.de/miplib2/miplib/stein9.mps.gz

clear;

% the (dense) 0-1 matrix with the constraints
% the first twelve constraints are of the form <sum of three variables greater equal one>
% the last constraints gives a trivial bound on the objective and is actually redundant
matrix = [
0, 1, 1, 1, 0, 0, 0, 0, 0;...
1, 0, 1, 0, 1, 0, 0, 0, 0;...
1, 1, 0, 0, 0, 1, 0, 0, 0;...
0, 0, 0, 0, 1, 1, 1, 0, 0;...
0, 0, 0, 1, 0, 1, 0, 1, 0;...
0, 0, 0, 1, 1, 0, 0, 0, 1;...
1, 0, 0, 0, 0, 0, 0, 1, 1;...
0, 1, 0, 0, 0, 0, 1, 0, 1;...
0, 0, 1, 0, 0, 0, 1, 1, 0;...
1, 0, 0, 1, 0, 0, 1, 0, 0;...
0, 1, 0, 0, 1, 0, 0, 1, 0;...
0, 0, 1, 0, 0, 1, 0, 0, 1;...
1, 1, 1, 1, 1, 1, 1, 1, 1;...
];

% all constraints are of the type a_1*x_1+...+a9*x_9 >= b
% In SCIP, constraints are represented as left hand side <= linear sum <= right hand side
% Hence, the left hand sides are all finite, the right hand sides are plus infinity
lhs = [1,1,1,1,1,1,1,1,1,1,1,1,4]';
rhs = [1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20,1e+20]';

% the variables are binary, hence, the lower bounds are zero, the upper bounds are one
lb = [0,0,0,0,0,0,0,0,0]';
ub = [1,1,1,1,1,1,1,1,1]';

% all variables are binary decision variables (you put an item into the system or not)
% the goal is to minimize the number of used variables/items
vartype = ['b','b','b','b','b','b','b','b','b'];
obj = [1,1,1,1,1,1,1,1,1]';
objsense = 'min';

% call SCIP
[bestsol, objval] = scip(matrix, lhs, rhs, obj, lb, ub, vartype, objsense);


% GCD    Greatest common divisor.
% G = GCD(A,B) is the greatest common divisor of A and B
function g = gcd(a,b)
	if isscalar(a)
		a = a*ones(size(b),'int64');
	elseif isscalar(b)
		b = a*ones(size(b),'int64');
	end
	if ~isequal(size(a),size(b))
		error('Size mismatch');
	end

	g = zeros(size(a),'int64');
	for k = 1:length(a)
		g(k) = a(k);
		while b(k) ~= 0
		   t    = b(k);
		   b(k) = mod(g(k),b(k));
		   g(k) = t;
		end
	end
end


function C = cumsummat(N, dom, disc)
%CUMSUMMAT   Indefinite integration matrix.
%   C = CUMSUMMAT(N) returns the NxN indefinite integration matrix associated
%   with the Chebyshev spectral collocation method at second-kind Chebyshev
%   points. By convection, the arbitrary constant is chosen so that the result
%   is zero at -1. See CHEBCOLLOC2.CUMSUMMAT for further details.
%
%   D = CUMSUMMAT(N, DOM) scales the indefinite integration matrix D to the
%   domain DOM. DOM should be a 1x2 vector.
%
%   D = CUMSUMMAT(N, DOM, DISC) or CUMSUMMAT(N, DISC) returns the indefinite
%   integration matrix associated with the OPDISCRETIZATION DISC.
%
% See also CUMSUM, CHEBCOLLOC2.DIFFMAT, DIFFMAT.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

%% Parse the inputs:
if ( (nargin == 2) )
    if ( isa(dom, 'function_handle') || ischar(dom) )
        disc = dom;
        dom = cheboppref().domain;
    else
        disc = chebcolloc2();
    end
elseif ( nargin == 1 )
    disc = chebcolloc2();
    dom = cheboppref().domain;
end
% Ensure DISC is a discretization:
if ( ischar(disc) )
    disc = str2func(disc);
end
if ( isa(disc, 'function_handle') )
    disc = disc();
end
% No breakpoints allowed:
if ( numel(dom) > 2 )
    dom = dom([1 end]);
    warning('CHEBFUN:cumsummat:noBreaks', ...
        'CUMSUMMAT does not support domains with breakpoints.');
end

%% Call DISC.DIFFMAT(N) and scale appropriately.
scl = .5*(dom(end) - dom(1));
C = scl*disc.cumsummat(N);

end


%% Example of clustering with AIC and BIC computed for K-means with RSS
clear all; close all;

%% Generate Perfect circle

nb_samples  = 100;
phi         = linspace(0,2 * pi,nb_samples);
r           = 10;
X           = [r .* cos(phi(:)), r .* sin(phi(:))];

%% Plot circle points

plot_options                = [];
plot_options.title          = 'Circle';

if exist('h1','var') && isvalid(h1), delete(h1);end
h1  = ml_plot_data(X,plot_options);
axis square;

%% Generate Random Clusters from GMM

clear all; close all;
num_samples         = 400;
num_classes         = 4;
dim                 = 2;
[X,labels,gmm]      = ml_clusters_data(num_samples,dim,num_classes);
options.title       = 'Random Gaussian';

if exist('h1','var') && isvalid(h1), delete(h1);end
h1 = ml_plot_data(X,options);
axis equal;

%% K-means

cluster_options             = [];
cluster_options.method_name = 'kmeans';
cluster_options.K           = 2;

result1                     = ml_clustering(X,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);

result1.lambda              = 2;
[rss,aic,bic]               = ml_clustering_eval(X,result1);

% Plot decision boundary
if exist('hd','var') && isvalid(hd), delete(hd);end
hd = ml_plot_class_boundary(X,result1);
%% Search for optimal \lambda value in AIC(RSS)
clc;
cluster_options             = [];
cluster_options.method_name = 'kmeans';

% Compute Maximum RSS values (when K=1,\alpha)
[N,D]       = size(X);
alpha       = N/4;
repeats     = 1;
K           = 1:alpha;
[mus, stds] = ml_clustering_optimise(X,K,repeats,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);

% Compute lower/upper bounds of \lambda values according to limits derived
% in slide 9,12,13 of TP2-Metrics-Recap
rss_k1         = mus(1,1);
rss_k2         = mus(1,alpha);
upper_lambda   = (rss_k1 - rss_k2) / (alpha*D);
lower_lambda   = (rss_k1) / (D*N);
lambda_range   = [floor(lower_lambda):1:ceil(upper_lambda)+1];

% Plot AIC(RSS) with a constrained range of lambda's
clc;
if exist('h_aic','var')     && isvalid(h_aic),     delete(h_aic);    end
h_aic = figure;hold on;
leg_names = [];
aic_mins = [];
for l=1:length(lambda_range)
    cluster_options.lambda    = lambda_range(l); %Magic number
    repeats                   = 1;
    Ks                        = 1:N;
    [mus, stds]               = ml_clustering_optimise(X,Ks,repeats,cluster_options,'Start','plus','Distance','sqeuclidean','MaxIter',500);
    plot(mus(2,:),'-');
    hold on;
    [min_aic, min_k] = min(mus(2,:));
    leg_names = [leg_names; {strcat('\lambda= ',num2str(lambda_range(l)))}];
    aic_mins = [aic_mins; [min_aic, min_k]];
end
legend(leg_names);
grid on;
box on;
xlabel('K');
title('AIC(RSS) for K-means')

%% Plot BIC(RSS)

if exist('h_bic','var')     && isvalid(h_bic),     delete(h_bic);    end
h_bic = figure;hold on;
plot(mus(3,:),'-');
grid on;
box on;
xlabel('K');
title('BIC(RSS) for K-means')


function a = gfpp_inverse ( n, alpha )

%*****************************************************************************80
%
%% GFPP_INVERSE returns the inverse of the GFPP matrix.
%
%  Example:
%
%    N = 5, ALPHA = 1
%
%    0.5000   -0.2500   -0.1250   -0.0625   -0.0625
%         0    0.5000   -0.2500   -0.1250   -0.1250
%         0         0    0.5000   -0.2500   -0.2500
%         0         0         0    0.5000   -0.5000
%    0.5000    0.2500    0.1250    0.0625    0.0625
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%
%    Input, real ALPHA, determines subdiagonal elements.
%
%    Output, real A(N,N), the inverse matrix.
%
  [ p, l, u ] = gfpp_plu ( n, alpha );

  p_inverse = p';

  l_inverse = tri_l1_inverse ( n, l );

  u_inverse = tri_u_inverse ( n, u );

  a = u_inverse * l_inverse * p_inverse;

  return
end


function a = daub4_matrix ( n )

%*****************************************************************************80
%
%% DAUB4_MATRIX returns the DAUB4 matrix.
%
%  Discussion:
%
%    The DAUB4 matrix is the Daubechies wavelet transformation matrix
%    with 4 coefficients.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 July 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrix.
%    N must be at least 4, and a multiple of 2.
%
%    Output, real A(N,N), the matrix.
%
  c = [  0.4829629131445341E+00; ...
         0.8365163037378079E+00; ...
         0.2241438680420133E+00; ...
        -0.1294095225512603E+00 ];

  if ( n < 4 || mod ( n, 2 ) ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'DAUB4_MATRIX - Fatal error!\n' );
    fprintf ( 1, '  N must be at least 4 and a multiple of 2.\n' );
    error ( 'DAUB4_MATRIX - Fatal error!' );
  end

  a = zeros ( n, n );

  for i = 1 : 2 : n - 1

    a(i,i)                  =   c(1);
    a(i,i+1)                =   c(2);
    a(i,i4_wrap(i+2,1,n))   =   c(3);
    a(i,i4_wrap(i+3,1,n))   =   c(4);

    a(i+1,i)                =   c(4);
    a(i+1,i+1)              = - c(3);
    a(i+1,i4_wrap(i+2,1,n)) =   c(2);
    a(i+1,i4_wrap(i+3,1,n)) = - c(1);

  end

  return
end


function [V_sorted, S_sorted] = sorted_eig(X, direction)
%SORTED_EIG Compute the sorted eigenvalue decomposition of a square matrix
%
%   Inputs:
%       X:          matrix to decompose
%       direction:  'ascend','descend' for ordering of eigenvectors and
%           eigenvalues
%
%   Outputs:
%       V_sorted:   matrix of eigenvectors sorted according to the
%           eigenvalues
%       S_sorted:   diagonal matrix of sorted eigenvalues
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% SORTED_EIG.M - 5/10/2016
% Archontis Politis, archontis.politis@aalto.fi
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%

if nargin<2, direction = 'descend'; end

if size(X,1) ~= size(X,2)
    error('input matrix should be square')
end

[V, S] = eig(X);
[~, perm] = sort(diag(S), 1, direction);
S_sorted = S(perm, perm); V_sorted = V(:, perm);

end


function a = lock ( n )

%*****************************************************************************80
%
%% LOCK returns the number of codes for a lock with N buttons.
%
%  Discussion:
%
%    A button lock has N numbered buttons.  To open the lock, groups
%    of buttons must be pressed in the correct order.  Each button
%    may be pushed no more than once.  Thus, a code for the lock is
%    an ordered list of the groups of buttons to be pushed.
%
%    For this discussion, we will assume that EVERY button is pushed
%    at some time, as part of the code.  To count the total number
%    of codes, including those which don't use all the buttons, then
%    the number is 2 * A(N), or 2 * A(N) - 1 if we don't consider the
%    empty code to be valid.
%
%  Examples:
%
%    If there are 3 buttons, then there are 13 possible "full button" codes:
%
%      (123)
%      (12) (3)
%      (13) (2)
%      (23) (1)
%      (1) (23)
%      (2) (13)
%      (3) (12)
%      (1) (2) (3)
%      (1) (3) (2)
%      (2) (1) (3)
%      (2) (3) (1)
%      (3) (1) (2)
%      (3) (2) (1)
%
%    and, if we don't need to push all the buttons, every "full button" code above
%    yields a distinct "partial button" code by dropping the last set of buttons:
%
%      ()
%      (12)
%      (13)
%      (23)
%      (1)
%      (2)
%      (3)
%      (1) (2)
%      (1) (3)
%      (2) (1)
%      (2) (3)
%      (3) (1)
%      (3) (2)
%
%  First values:
%
%     N         A(N)
%     0           1
%     1           1
%     2           3
%     3          13
%     4          75
%     5         541
%     6        4683
%     7       47293
%     8      545835
%     9     7087261
%    10   102247563
%
%  Recursion:
%
%    A(I) = sum ( 0 <= J < I ) Binomial ( I, N-J ) * A(J)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 June 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Daniel Velleman, Gregory Call,
%    Permutations and Combination Locks,
%    Mathematics Magazine,
%    Volume 68, Number 4, October 1995, pages 243-253.
%
%  Parameters:
%
%    Input, integer N, the maximum number of lock buttons.
%
%    Output, integer A(1:N+1), the number of lock codes.
%
  if ( n < 0 )
    a = [];
    return
  end

  a(1) = 1;

  for i = 1 : n
    a(i+1) = 0;
    for j = 0 : i-1
      a(i+1) = a(i+1) + i4_choose ( i, i-j ) * a(j+1);
    end
  end

  return
end


function pols = ortho2eva0 ( mmax, z )

%*****************************************************************************80
%
%% ORTHO2EVA0 evaluates the orthonormal polynomials on the triangle.
%
%  Licensing:
%
%    This code is distributed under the GNU GPL license.
%
%  Modified:
%
%    28 June 2014
%
%  Author:
%
%    Original FORTRAN77 version by Hong Xiao, Zydrunas Gimbutas.
%    This MATLAB version by John Burkardt.
%
%  Reference:
%
%    Hong Xiao, Zydrunas Gimbutas,
%    A numerical algorithm for the construction of efficient quadrature
%    rules in two and higher dimensions,
%    Computers and Mathematics with Applications,
%    Volume 59, 2010, pages 663-676.
%
%  Parameters:
%
%    Input, integer MMAX, the maximum order to which the polynomials are
%    to be evaluated.
%
%    Input, real Z(2), the coordinates of the evaluation point.
%
%    Output, real POLS((mmax+1)*(mmax+2)/2), the orthogonal
%    polynomials evaluated at the point Z.
%
  zero = 0.0;
  sqrt2 = sqrt ( 2.0 );
  sqrt3 = sqrt ( 3.0 );
  r11 = -1.0 / 3.0;
  r12 = -1.0 / sqrt3;
  r21 = - 1.0 / 3.0;
  r22 = 2.0 / sqrt3;

  a = z(1);
  b = z(2);
%
%  Map the reference triangle to the right
%  triangle with the vertices (-1,-1), (1,-1), (-1,1)
%
  x = r11 + r12 * b + a;
  y = r21 + r22 * b;
%
%  Evaluate the Koornwinder's polynomials via the three term recursion.
%
  par1 = ( 2.0 * x + 1.0 + y ) / 2.0;
  par2 = ( 1.0 - y ) / 2.0;
  f1 = klegeypols ( par1, par2, mmax );

  f2 = zeros(mmax+1,mmax+1);
  for m = 0 : mmax
    par1 = 2 * m + 1;
    f2(1:mmax+1,m+1) = kjacopols ( y, par1, zero, mmax - m );
  end

  npols = ( ( mmax + 1 ) * ( mmax + 2 ) ) / 2;
  pols = zeros(npols,1);

  kk = 0;
  for m = 0 : mmax
    for n = 0 : m
      kk = kk + 1;
%
%  Evaluate the polynomial (m-n, n)
%
      pols(kk) = f1(m-n+1) * f2(n+1,m-n+1);
%
%  Normalize.
%
      scale = sqrt ...
      ( ...
        ( ...
          ( 1 + ( m - n ) + n ) * ...
          ( 1 + ( m - n ) + ( m - n ) ) ...
        ) / sqrt3 ...
      );

      pols(kk) = pols(kk) * scale;

    end

  end

  return
end


function cgs_test ( )

%*****************************************************************************80
%
%% CGS_TEST tests CGS.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CGS_TEST:\n' );
  fprintf ( 1, '  CGS uses the Conjugate Gradient Squared \n' );
  fprintf ( 1, '  iterative method to approximate the solution \n' );
  fprintf ( 1, '  of a linear system A * x = b.\n' );

  n = 10;

  A = zeros ( n, n );

  for i = 1 : n
    A(i,i) = 2.0;
  end
  for i = 1 : n-1
    A(i,i+1) = -1;
  end
  for i = 2 : n
    A(i-1,i) = -1;
  end
  x = [ 1 : n ]';
  b = A * x;
  x = ones ( n, 1 );

  M = 0;
  max_it = 10;
  tol = 0.0001;

  fprintf ( 1, '\n' );
  fprintf ( 1, '  For this example, the order of the system is N = %d\n', n );
  fprintf ( 1, '  The matrix A is the simple tridiagonal -1, 2, -1.\n' );
  fprintf ( 1, '  The correct solution is x = [ 1, 2, ..., n].\n' );
  fprintf ( 1, '  The right hand side b is determined by computing A * x.\n' );
  fprintf ( 1, '  The exact x is then replaced by a vector of all 1''s for\n' );
  fprintf ( 1, '  use as a starting guess.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Other parameters are set as follows:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The maximum number of steps is %d.\n', max_it );
  fprintf ( 1, '  The error tolerance is %f\n', tol );

  [ x, error_norm, iter, flag ] = cgs ( A, x, b, M, max_it, tol );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The CGS routine has returned with FLAG = %d\n', flag );
  if ( flag == 0 )
    fprintf ( 1, '  This indicates that the iteration has converged.\n' );
  elseif ( flag == 1 )
    fprintf ( 1, '  This indicates that the iteration has NOT converged.\n' );
  elseif ( flag == -1 )
    fprintf ( 1, '  This indicates that the iteration has broken down.\n' );
  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  The number of iterations taken was %d\n', iter );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The L2 norm of the error per iteration:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : iter
    fprintf ( 1, '  %4d  %f\n', i, error_norm(i) );
  end
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The computed solution vector X:\n' );
  fprintf ( 1, '\n' );
  for i = 1 : n
    fprintf ( 1, '  %4d  %f\n', i, x(i) );
  end

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

  return
end


function tw = trigauss ( n, alpha, beta )

%*****************************************************************************80
%
%% TRIGAUSS computes a trigonometric gaussian quadrature formula.
%
%  Discussion:
%
%    This function computes the N+1 angles and weights of a trigonometric
%    gaussian quadrature formula on [ALPHA,BETA], with
%    0 < BETA - ALPHA <= pi.
%
%    The formula integrates the canonical trigonometric basis with accuracy
%    from about 10^(-15) (for small omega) to about 10^(-13) (for omega --> pi)
%    up to N = 300.
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Gaspare Da Fies, Alvise Sommariva, Marco Vianello
%
%  Parameters:
%
%    Input, integer N, the trigonometric degree of exactness.
%
%    Input, real ALPHA, BETA, the angular interval.
%    0 < BETA - ALPHA <= pi.
%
%    Output, real TW(N+1,2) array of angles and weights.
%
  np1 = n + 1;
%
%  Compute the half angle subtended by the circle segment.
%
  omega = ( beta - alpha ) / 2.0;
%
%  Compute the modified Chebyshev recursion coefficients.
%
  ab = r_subchebyshev ( np1, omega );
%
%  Compute the quadrature rule.
%
  xw_symm_eigw = SymmMw ( np1, ab );
  tw = trigauss_conversion ( xw_symm_eigw, omega );
%
%  Adjust angles from the reference system to the physical system.
%
  tw(:,1) = tw(:,1) + ( beta + alpha ) / 2.0;

  return
end
function ab = r_subchebyshev ( n, omega )

%*****************************************************************************80
%
%% R_SUBCHEBYSHEV computes the modified Chebyshev recursion coefficients.
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Gerard Meurant, Alvise Sommariva
%
%  Parameters:
%
%    Input, integer N, the number of points.
%
%    Input, real OMEGA, the arc angle.
%
%    Output, real AB(NN,2), the coefficients of the three term recursion.
%    The dimension NN is N + 1 if N is odd, or N if N is even.
%
  N = n;
  n = n - 1;

  if rem ( N, 2 ) == 1
    NN = N + 1;
    nn = n + 1;
  else
    NN = N;
    nn = n;
  end
%
%  Compute the moments.
%
  mom = fast_moments_computation ( omega, 2 * nn + 1 );
%
%  Recurrence coefficients of the monic Chebyshev polynomials.
%
  abm(:,1) = zeros ( 2 * nn + 1, 1 );
  abm(:,2) = 0.25 * ones ( 2 * nn + 1, 1 );
  abm(1,2) = pi;
  abm(2,2) = 0.5;
%
%  Recurrence coefficients for the monic orthogonal polynomials
%  with respect to the weight function
%    w(x) = 2 * sin ( omega / 2 ) / sqrt ( 1 - sin^2 ( omega / 2 ) * x^2 )
%  by the modified Chebyshev algorithm.
%
% ab = chebyshev ( NN + 1, mom, abm );
  ab = fast_chebyshev ( NN, mom, abm );

  return
end
function ab = fast_chebyshev ( N, mom, abm )

%*****************************************************************************80
%
%% SUBP_MOD_CHEBYSHEV carries out a modified Chebyshev algorithm.
%
%  Discussion:
%
%    This works only for the subperiodic weight function.
%
%    This is a simplified version of a routine by Walter Gautschi.
%
%  Modified:
%
%    19 May 2013
%
%  Parameters:
%
%    Input, integer N, ?
%
%    Input, real MOM(2*N), ?
%
%    Input, real ABM(?), ?
%
%    Output, real AB(N,2), ?
%
  ab = zeros(N,2);
  sig = zeros(N+1,2*N);

  ab(1,2) = mom(1);

  sig(1,1:2*N) = 0;
  sig(2,:) = mom(1:2*N);

  for n = 3:N+1
    for m = n-1:2*N-n+2
      sig(n,m) = sig(n-1,m+1) + abm(m,2) * sig(n-1,m-1) - ab(n-2,2) * sig(n-2,m);
    end

    ab(n-1,2) = sig(n,n-1) / sig(n-1,n-2);
  end

  return
end
function mom = fast_moments_computation ( omega, n )

%*****************************************************************************80
%
%% FAST_MOMENTS_COMPUTATION computes the moments.
%
%  Modified:
%
%    19 May 2013
%
%  Parameters:
%
%    Input, real OMEGA, the arc angle.
%
%    Input, integer N, the index of the highest moment to compute.
%
%    Output, real MOM(1,N+1), the 0-th through N-th moments.
%
  mom = zeros(1,n+1);
%
%  Set the first moment.
%
  mom(1) = 2.0 * omega;

  if ( 2 <= n )

    if ( omega <= 1/4*pi)
      l = 10;
    elseif ( omega <= 1/2*pi)
      l = 20;
    elseif ( omega <= 3/4*pi)
      l = 40;
    elseif ( omega == pi )
      l = 2*ceil(10*pi);
    else
      l = 2*ceil(10*pi/(pi-omega));
    end
%
%  Auxilliary vectors.
%
    temp=(2:2:n+2*l-2);
    temp2=temp.^2-1;
%
%  Diagonals.
%
    dl = 1/4 -1./(4*(temp-1));
    dc = 1/2 -1/sin(omega/2)^2 -1./(2*temp2);
    du = 1/4 +1./(4*(temp+1));

    d = 4*cos(omega/2)/sin(omega/2)./temp2';
    d(end) = d(end);
%
%  Solve the tridiagonal system.
%
    z = tridisolve ( dl(2:end), dc, du(1:end-1 ), d );
%
%  Set the odd moments.
%
    mom(3:2:n+1) = z(1:floor(n/2));

  end

  mom = mom';
%
%  Normalize.
%
  M = length ( mom );
  kk = 2.^(-((1:2:M)-2))';
  kk(1) = 1;
  v = ones(M,1);
  v(1:2:M) = kk;
  mom = v .* mom;

  return
end
function xw = SymmMw ( N, ab )

%*****************************************************************************80
%
%% SYMMMW computes a quadrature rule for a symmetric weight function.
%
%  Discussion:
%
%    This function uses the reduced matrix and eig and
%    computation of weights with the 3-term recurrence.
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Gerard Meurant, Alvise Sommariva
%
%  Reference:
%
%    Gerard Meurant, Alvise Sommariva,
%    Fast variants of the Golub and Welsch algorithm for symmetric
%    weight functions,
%    Submitted, 2012.
%
%  Parameters:
%
%    Input, integer N, the cardinality of the rule.
%
%    Input, real AB(*,2), the 3-term recurrence for the orthogonal polynomials
%    same as in OPQ.  Note that AB(1,2) is the 0th moment.
%
%    Output, real XW(N,2), the nodes and weights of the quadrature rule.
%
  N0 = size ( ab, 1 );

  if ( N0 < N )
    error('SymmMw: input array ab is too short')
  end

  na = norm(ab(:,1));

  if na > 0
    error('SymmMw: the weight function must be symmetric')
  end
%
%  Computation of the reduced matrix in vectors (a,b)
%
  if mod(N,2) == 0
    even = 1;
    Nc = N / 2;
  else
    even = 0;
    Nc = fix(N / 2) +1;
  end

  absd = ab(:,2);
  absq = sqrt(absd);

  a = zeros(1,Nc);
  b = a;

  switch even
    case 1
        % N even
        a(1) = absd(2);
        b(1) = absq(2) * absq(3);

        k = (2:Nc-1);
        a(k) = absd(2*k-1) + absd(2*k);
        b(k) = absq(2*k) .* absq(2*k+1);
        a(Nc) = absd(N) + absd(N-1);
        start = 1;

       J = diag(a) + diag(b(1:Nc-1),1) + diag(b(1:Nc-1),-1);
       t = sort(eig(J));
       w = weights_3t(t',a,b);
%
% w are the squares of the first components
%
       w = w' / 2;
    case 0
        % N odd
        a(1) = absd(2);
        b(1) = absq(2) * absq(3);

        k = (2:Nc-1);
        a(k) = absd(2*k-1) + absd(2*k);
        b(k) = absq(2*k) .* absq(2*k+1);
        a(Nc) = absd(N);
        start = 2;
%
%  the first node must be zero
%
        J = diag(a) + diag(b(1:Nc-1),1) + diag(b(1:Nc-1),-1);
        t = sort(eig(J));
        t(1) = 0;
        w = weights_3t(t',a,b);
        w = [w(1); w(2:end)' / 2];
    otherwise
        error('this is not possible')
  end

  xwp = sqrt(t);

  xw(:,1) = [-xwp(end:-1:start,1); xwp];
  xw(:,2) = ab(1,2) * ([w(end:-1:start); w]);

  return
end
function tw = trigauss_conversion ( xw, omega )

%*****************************************************************************80
%
%% TRIGAUSS_CONVERSION ???
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Gaspare Da Fies, Alvise Sommariva, Marco Vianello
%
%  Parameters:
%
%    Input, real XW(?,2), ?
%
%    Input, real OMEGA, the arc angle.
%
%    Output, real TW(?,2), the angles and weights for the trigonometic
%    quadrature rule.
%
  tw(:,1) = 2.0 * asin ( sin ( omega / 2.0 ) * xw(:,1) );
  tw(:,2) = xw(:,2);

  return
end
function w = weights_3t ( t, a, b )

%*****************************************************************************80
%
%% WEIGHTS_3T computes squares of the 1st components of eigenvectors.
%
%  Discussion:
%
%    The results are computed from the 3-term recurrence relation of
%    the orthogonal polynomials.
%
%  Modified:
%
%    19 May 2013
%
%  Author:
%
%    Gerard Meurant, Alvise Sommariva
%
%  Parameters:
%
%    Input, real T(N), the nodes.
%
%    Input, real A(N-1), B(N-1), the coefficients of the 3-term recurrence.
%
%    Output, real W(N), the squares of the first components of the eigenvectors.
%
  n = length ( t );

  P = zeros ( n, n );
  P(1,:) = ones ( 1, n );
  P(2,:) = ( t - a(1) ) / b(1);

  for k = 3 : n
    k1 = k - 1;
    k2 = k - 2;
    P(k,:) = ( ( t - a(k1) ) .* P(k1,:) - b(k2) * P(k2,:) ) / b(k1);
  end

  P2 = P .* P;

  w = 1.0 ./ sum ( P2 );

  return
end


function fx = p47_fun ( n, x )

%*****************************************************************************80
%
%% P47_FUN evaluates the integrand for problem 47.
%
%  Discussion:
%
%    The function is singular at the left endpoint.
%
%  Interval:
%
%    0 <= x <= 1
%
%  Integrand:
%
%    sqrt ( x ) * ln ( x )
%
%  Exact Integral:
%
%    -4/9 = -0.4444...
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Robert Piessens, Elise de Doncker-Kapenga,
%    Christian Ueberhuber, David Kahaner,
%    QUADPACK: A Subroutine Package for Automatic Integration,
%    Springer, 1983, page 101.
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N), the evaluation points.
%
%    Output, real FX(N), the integrand values.
%
  fx(1:n) = sqrt ( x(1:n) ) .* log ( x(1:n) );

  i = find ( x == 0.0 );
  fx(i) = 0.0;

  return
end


function line_ncc_rule_test02 ( )

%*****************************************************************************80
%
%% LINE_NCC_RULE_TEST02 estimates the integral of exp(x) from 0 to 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    10 April 2014
%
%  Author:
%
%    John Burkardt
%
  a =  0.0;
  b = +1.0;
  exact = exp ( b ) - exp ( a );

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST02\n' );
  fprintf ( 1, '  Use a sequence of NCC rules to compute an estimate Q\n' );
  fprintf ( 1, '  of the integral:\n' );
  fprintf ( 1, '    I = integral ( 0 <= x <= 1 ) exp(x) dx.\n' );
  fprintf ( 1, '  The exact value is:\n' );
  fprintf ( 1, '    I = %g\n', exact );

  fprintf ( 1, '\n' );
  fprintf ( 1, '   N       Q             |Q-I|\n' );
  fprintf ( 1, '\n' );

  for n = 1 : 22

    [ x, w ] = line_ncc_rule ( n, a, b );

    q = w(1:n)' * exp ( x(1:n) );
    error = abs ( exact - q );
    fprintf ( 1, '  %2d  %14.6g  %14.6g\n', n, q, error );

  end

  return
end


% sieveEr: returns a vector with prime numbers from 2 up to N
% assumes: N >= 2
function  y = sieveER(N)
  % precondition
  assert(N >= 2,"N must be >= 2")
  tmp = [false,true(1,N-1)]; % indexed by all numbers from 2 up to N

  % labels all composite number with false
  for i = 2 : 1 : sqrt(N)
    if (tmp(i))
      for j = i^2 : i : N
        tmp(j) = false;
      endfor
    endif
  endfor

  % fills up all prime numbers in vector y
  y = find(tmp);

endfunction


% Prim's minimal spanning tree algorithm
% Prim's alg idea:
%  start at any node, find closest neighbor and mark edges
%  for all remaining nodes, find closest to previous cluster, mark edge
%  continue until no nodes remain
%
% INPUTS: graph defined by adjacency matrix, nxn
% OUTPUTS: matrix specifying minimum spanning tree (subgraph), nxn
%
% Other routines used: isConnected.m
% GB: Oct 7, 2012

function tr = minSpanTree(adj)

% check if graph is connected:
if not(isConnected(adj)); printf('This graph is not connected. No spanning tree exists.\n'); return; end

n = length(adj); % number of nodes
tr = zeros(n);   % initialize tree

adj(find(adj==0))=inf; % set all zeros in the matrix to inf

conn_nodes = 1;        % nodes part of the min-span-tree
rem_nodes = [2:n];     % remaining nodes

while length(rem_nodes)>0

  [minlink]=min(min(adj(conn_nodes,rem_nodes)));
  ind=find(adj(conn_nodes,rem_nodes)==minlink);

  [ind_i,ind_j] = ind2sub([length(conn_nodes),length(rem_nodes)],ind(1));

  i=conn_nodes(ind_i); j=rem_nodes(ind_j); % gets back to adj indices
  tr(i,j)=1; tr(j,i)=1;
  conn_nodes = [conn_nodes j];
  rem_nodes = setdiff(rem_nodes,j);

end


close all;
clear all;
clc;
rng('default');
png_export = true;
pdf_export = false;
% Create the directory for storing images
[status_code,message,message_id] = mkdir('bin');

mf = spx.graphics.Figures();

% Signal space
N = 256;
% Number of measurements
M = 64;
% Sparsity level
K = 8;
% Number of signals
S = 4;
% Construct the signal generator.
gen  = spx.data.synthetic.SparseSignalGenerator(N, K, S);
% Generate bi-uniform signals
X = gen.biUniform(1, 2);
% Sensing matrix
Phi = spx.dict.simple.gaussian_dict(M, N);
% Measurement vectors
Y = Phi * X;

solver = spx.pursuit.joint.BasisPursuit(Phi);
result = solver.solve_linf_l1(Y);
% Solution vectors
Z = result.Z;

solver = spx.pursuit.joint.BasisPursuit(Phi);
result = solver.solve_l1_l1(Y);
% Solution vectors
Z = result.Z;

for s=1:S
    mf.new_figure(sprintf('MMV signal: %d', s));
    subplot(411);
    stem(X(:, s), '.');
    title('Sparse vector');
    subplot(412);
    stem(Z(:, s), '.');
    title('Recovered sparse vector');
    subplot(413);
    stem(abs(X(:, s) - Z(:, s)), '.');
    title('Recovery error');
    subplot(414);
    stem(Y(:, s), '.');
    title('Measurement vector');
end


function [x fval] =  runps(a,b,c,x0)
[x, fval] = patternsearch(@nestedfun,x0);
% Nested function that computes the objective function
    function y = nestedfun(x)
        y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
         (-c + c*x(2)^2)*x(2)^2;
    end
end


% FEATURE NORMALIZE function.
% Normalizes the features in X. Returns a normalized version of X where the mean value of
% each feature is 0 and the standard deviation is 1.
function [X_normalized, mu, sigma] = feature_normalize(X)
    X_normalized = X;
    mu = zeros(1, size(X_normalized, 2));
    sigma = zeros(1, size(X_normalized, 2));

    % Get average values for each feature (column) in X.
    mu = mean(X_normalized);

    % Calculate the standard deviation for each feature.
    sigma = std(X_normalized);

    % Subtract mean values from each feature (column) of every example (row)
    % to make all features be spread around zero.
    X_normalized = X_normalized - mu;

    % Normalize each feature values for each example so that all features
    % are close to [-1:1] boundaries.
    X_normalized = X_normalized ./ sigma;
end


function [ r, s, area ] = node_reference_t3 ( )

%*****************************************************************************80
%
%% NODE_REFERENCE_T3 returns the basis nodes for the 3 node triangle.
%
%  Reference Element T3:
%
%    |
%    1  3
%    |  |\
%    |  | \
%    S  |  \
%    |  |   \
%    |  |    \
%    0  1-----2
%    |
%    +--0--R--1-->
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real R(3), S(3), the coordinates of the basis nodes.
%
%    Output, real AREA, the area of the element.
%
  r(1:3) = [ 0.0, 1.0, 0.0 ];
  s(1:3) = [ 0.0, 0.0, 1.0 ];

  area = 0.5;

  return
end


function sftpack_test05 ( )

%*****************************************************************************80
%
%% TEST05 tests R8VEC_SQSTB and R8VEC_SQSTF.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2010
%
%  Author:
%
%    John Burkardt
%
  n = 256;
  alo = 0.0;
  ahi = 5.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST05\n' );
  fprintf ( 1, '  For real slow quarter wave sine transforms,\n' );
  fprintf ( 1, '  R8VEC_SQSTF does a forward transform;\n' );
  fprintf ( 1, '  R8VEC_SQSTB does a backward transform.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  The number of data items is N = %d\n', n );
%
%  Set the data values.
%
  seed = 123456789;

  [ x, seed ] = r8vec_uniform ( n, alo, ahi, seed );

  r8vec_print_part ( n, x, 10, '  The original data:' );
%
%  Compute the coefficients.
%
  y = r8vec_sqstf ( n, x );

  r8vec_print_part ( n, y, 10, '  The sine coefficients:' );
%
%  Now compute inverse transform of coefficients.  Should get back the
%  original data.

  x = r8vec_sqstb ( n, y );

  r8vec_print_part ( n, x, 10, '  The retrieved data:' );

  return
end


function score = mutual_info_score(i,si,j,sj,data)
% G = mutual_info_score(i,si,j,sj,data)
% Only for tabular node which values are 1,2,...,size .
% si is size of node i, sj is size of node j.
% data(i,m) is the node i in the case m.
%
% Ref :
% C. Chow and C. Liu (1968). Approximating discrete probability distributions with dependence trees.
% IEEE Transactions on Information Theory, 14(3):462--467, May 1968.
%
% francois.olivier.c.h@gmail.com, philippe.leray@univ-nantes.fr, wangxiangyang@sjtu.edu.cn

[n N]=size(data);
Nj=hist(data(j,:),1:sj);
Ni=hist(data(i,:),1:si);
NiNj=Ni'*Nj;

for k=1:si
 ind=find(data(i,:)==k) ;
 Nij(k,:) = hist(data(j,ind),1:sj);
end

% sommons les valeurs non-infinies:
ind=find(NiNj~=0 & Nij~=0);
score=sum(sum(Nij(ind).*log(N*Nij(ind)./NiNj(ind))/N));


%% Test Difference Routines

% Comparing Different Strategies

% 1) DERIVEST Suite
% 2) MKL djacobi
% 3) adiff

%% Test 1
clc
fun = @(x) 2*x(1) + 3*x(2);
x0 = [1;1];

tic
% g1 = gradest(fun,x0)
toc

tic
[g2,stat] = mklJac(fun,x0)
toc

tic
g3 = autoJac(fun,x0)
toc

%%
clc
f = symJac(fun)

%% Test 2
clc
fun = @(x) 2.1*x(1) + 3*x(2)^2 + 4.2*sqrt(x(3));
x0 = [1;1;2];

tic
% g1 = gradest(fun,x0)
toc

tic
[g2,stat] = mklJac(fun,x0)
toc

tic
g3 = autoJac(fun,x0)
toc

%% Test 3
clc
nlcon = @(x) [8 - x(1)^2 - x(2)^2 - x(3)^2 - x(4)^2 - x(1) + x(2) - x(3) + x(4);
              10 - x(1)^2 - 2*x(2)^2 - x(3)^2 - 2*x(4)^2 + x(1) + x(4);
              5 - 2*x(1)^2 - x(2)^2 - x(3)^2 - 2*x(1) + x(2) + x(4)];
x0 = [1;1;1;1];

tic
% g1 = jacobianest(nlcon,x0)
toc

tic
[jac,stat] = mklJac(nlcon,x0,3)
toc

tic
g3 = autoJac(nlcon,x0)
toc


%%
% Visual display of convolutive kernels.

addpath('../toolbox/');
addpath('../toolbox/img/');
addpath('../toolbox/export_fig/');

rep = 'results/rkhs/';
[~,~] = mkdir(rep);

normalize = @(x)x/sum(x(:));

if not(exist('kernel'))
kernel = 'gaussian-medium';
kernel = 'gaussian-large';
kernel = 'gaussian-small';
kernel = 'energy-dist';
end

% grid points for display
q = 512;
% with padding
q1 = q*8;

% input

rand('state', 1243);
N = 20;
mu = zeros(q,q);
I = randperm(q*q);
mu(I(1:N)) = 1/N;

nu = zeros(q,q);
I = randperm(q*q);
nu(I(1:N)) = 1/N;

mu = load_image('shape-1',q);
nu = load_image('shape-2',q);

mu = normalize(rescale(-mu));
nu = normalize(rescale(-nu));

xi = mu-nu;

% compute sqrt kernel
u = 2 * [0:q1/2, -q1/2+1:-1]' / q1;
[Y,X] = meshgrid(u,u);
D = sqrt(X.^2+Y.^2);

% soft max
s=1/5;
sm = @(t)s*log( 1+exp(t/s) );

switch kernel
    case 'energy-dist'
        r = .3;
        K = max(r-D,0);
        K = sm(r-D);
    case 'gaussian-small'
        sigma = .005;
        K = exp( -D.^2./(2*sigma^2) );
    case 'gaussian-medium'
        sigma = .02;
        K = exp( -D.^2./(2*sigma^2) );
    case 'gaussian-large'
        sigma = .05;
        K = exp( -D.^2./(2*sigma^2) );
end

Kh = fft2(K);
% Kh = max(real(Kh),0);

% for display
K1 = real( ifft2(sqrt(Kh)) );
K1 = fftshift(K1);
K1 = K1(end/2-q/2:end/2+q/2-1, end/2-q/2:end/2+q/2-1);

% zero padding
U = zeros(q1);
U(1:q,1:q) = xi;
xiC = real( ifft2( fft2(U) .* sqrt(Kh) ) );
xiC = xiC(1:q,1:q);

mu1 = mu/max(mu(:));
nu1 = nu/max(nu(:));
imagesc( cat(3, 2-nu1, 2-mu1-nu1, 2-mu1 )/2 );
axis image; axis off;
colormap jet(256);
% saveas(gcf, [rep 'input.png'], 'png');
export_fig([rep 'input.png'], '-m3');

disp_distrib(xiC);
axis image; axis off;
% saveas(gcf, [rep kernel '.png'], 'png');
export_fig([rep kernel '.png'], '-m3');

if strcmp(kernel, 'energy-dist')
    t = linspace(-1,1,q);
    [y,x] = meshgrid(t,t);
    r = .5*1e-3;
    A = -1 ./ sqrt(r + x.^2+y.^2); A = A/max(abs(A(:)));
    disp_distrib( A, 40 );
else
    disp_distrib(-K1, 40);
end
axis image; axis off;
% saveas(gcf, [rep kernel '-kernel.png'], 'png');
export_fig([rep kernel '-kernel.png'], '-m3');


function sigm = sigmoid(x)

    sigm = 1 ./ (1 + exp(-x));
end


% 计算欧式距离
function dist = distEclud(vecA,vecB)
    dist  = sum(power((vecA-vecB),2));
end

function dist = softDist(vecA,vecB)
    dist = sum(abs(vecB-vecA));
end


%%
% Interpolation of 1D Gaussians

rep = 'results/gaussian-1d/';
[~,~] = mkdir(rep);

N = 1024;
x = linspace(0,1,N)';
normalize = @(x)x/sum(x(:));
gauss = @(m,s)normalize( exp( -(x-m).^2/(2*s^2) ) );

m0 = .1;  s0 = .025;
m1 = .8;  s1 = .08;

q = 16;
clf; hold on;
for i=1:q
    t = (i-1)/(q-1);
    m = (1-t)*m0+t*m1;
    s = (1-t)*s0+t*s1;
    lw = 2;
    plot(x, gauss(m,s), 'color', [1-t 0 t], 'LineWidth', lw);
end
set(gca, 'XTick', [], 'YTick', []);
box on; axis tight;
saveas(gcf, [rep 'interp-density.eps']);

clf; hold on;
for i=1:q
    t = (i-1)/(q-1);
    m = (1-t)*m0+t*m1;
    s = (1-t)*s0+t*s1;
    lw = 2;
    plot(x, gauss(m,s), 'color', [1-t 0 t], 'LineWidth', lw);
end
set(gca, 'XTick', [], 'YTick', []);
box on; axis tight;
saveas(gcf, [rep 'interp-density.eps'], 'epsc');


function [ H, f, c ] = trifbank( M, K, R, fs, h2w, w2h )
% TRIFBANK Triangular filterbank.
%
%   [H,F,C]=TRIFBANK(M,K,R,FS,H2W,W2H) returns matrix of M triangular filters
%   (one per row), each K coefficients long along with a K coefficient long
%   frequency vector F and M+2 coefficient long cutoff frequency vector C.
%   The triangular filters are between limits given in R (Hz) and are
%   uniformly spaced on a warped scale defined by forward (H2W) and backward
%   (W2H) warping functions.
%
%   Inputs
%           M is the number of filters, i.e., number of rows of H
%
%           K is the length of frequency response of each filter
%             i.e., number of columns of H
%
%           R is a two element vector that specifies frequency limits (Hz),
%             i.e., R = [ low_frequency high_frequency ];
%
%           FS is the sampling frequency (Hz)
%
%           H2W is a Hertz scale to warped scale function handle
%
%           W2H is a wared scale to Hertz scale function handle
%
%   Outputs
%           H is a M by K triangular filterbank matrix (one filter per row)
%
%           F is a frequency vector (Hz) of 1xK dimension
%
%           C is a vector of filter cutoff frequencies (Hz),
%             note that C(2:end) also represents filter center frequencies,
%             and the dimension of C is 1x(M+2)
%
%   Example
%           fs = 16000;               % sampling frequency (Hz)
%           nfft = 2^12;              % fft size (number of frequency bins)
%           K = nfft/2+1;             % length of each filter
%           M = 23;                   % number of filters
%
%           hz2mel = @(hz)(1127*log(1+hz/700)); % Hertz to mel warping function
%           mel2hz = @(mel)(700*exp(mel/1127)-700); % mel to Hertz warping function
%
%           % Design mel filterbank of M filters each K coefficients long,
%           % filters are uniformly spaced on the mel scale between 0 and Fs/2 Hz
%           [ H1, freq ] = trifbank( M, K, [0 fs/2], fs, hz2mel, mel2hz );
%
%           % Design mel filterbank of M filters each K coefficients long,
%           % filters are uniformly spaced on the mel scale between 300 and 3750 Hz
%           [ H2, freq ] = trifbank( M, K, [300 3750], fs, hz2mel, mel2hz );
%
%           % Design mel filterbank of 18 filters each K coefficients long,
%           % filters are uniformly spaced on the Hertz scale between 4 and 6 kHz
%           [ H3, freq ] = trifbank( 18, K, [4 6]*1E3, fs, @(h)(h), @(h)(h) );
%
%            hfig = figure('Position', [25 100 800 600], 'PaperPositionMode', ...
%                              'auto', 'Visible', 'on', 'color', 'w'); hold on;
%           subplot( 3,1,1 );
%           plot( freq, H1 );
%           xlabel( 'Frequency (Hz)' ); ylabel( 'Weight' ); set( gca, 'box', 'off' );
%
%           subplot( 3,1,2 );
%           plot( freq, H2 );
%           xlabel( 'Frequency (Hz)' ); ylabel( 'Weight' ); set( gca, 'box', 'off' );
%
%           subplot( 3,1,3 );
%           plot( freq, H3 );
%           xlabel( 'Frequency (Hz)' ); ylabel( 'Weight' ); set( gca, 'box', 'off' );
%
%   Reference
%           [1] Huang, X., Acero, A., Hon, H., 2001. Spoken Language Processing:
%               A guide to theory, algorithm, and system development.
%               Prentice Hall, Upper Saddle River, NJ, USA (pp. 314-315).

%   Author  Kamil Wojcicki, UTD, June 2011

    if( nargin~= 6 ), help trifbank; return; end; % very lite input validation

    f_min = 0;          % filter coefficients start at this frequency (Hz)
    f_low = R(1);       % lower cutoff frequency (Hz) for the filterbank
    f_high = R(2);      % upper cutoff frequency (Hz) for the filterbank
    f_max = 0.5*fs;     % filter coefficients end at this frequency (Hz)
    f = linspace( f_min, f_max, K ); % frequency range (Hz), size 1xK
    fw = h2w( f );

    % filter cutoff frequencies (Hz) for all filters, size 1x(M+2)
    c = w2h( h2w(f_low)+[0:M+1]*((h2w(f_high)-h2w(f_low))/(M+1)) );
    cw = h2w( c );

    H = zeros( M, K );                  % zero otherwise
    for m = 1:M

        % implements Eq. (6.140) on page 314 of [1]
        % k = f>=c(m)&f<=c(m+1); % up-slope
        % H(m,k) = 2*(f(k)-c(m)) / ((c(m+2)-c(m))*(c(m+1)-c(m)));
        % k = f>=c(m+1)&f<=c(m+2); % down-slope
        % H(m,k) = 2*(c(m+2)-f(k)) / ((c(m+2)-c(m))*(c(m+2)-c(m+1)));

        % implements Eq. (6.141) on page 315 of [1]
        k = f>=c(m)&f<=c(m+1); % up-slope
        H(m,k) = (f(k)-c(m))/(c(m+1)-c(m));
        k = f>=c(m+1)&f<=c(m+2); % down-slope
        H(m,k) = (c(m+2)-f(k))/(c(m+2)-c(m+1));

   end

   % H = H./repmat(max(H,[],2),1,K);  % normalize to unit height (inherently done)
   % H = H./repmat(trapz(f,H,2),1,K); % normalize to unit area

% EOF


function x = pwPoly4(tGrid,xGrid,dxGrid,t)
% x = pwPoly4(tGrid,xGrid,t)
%
% This function does piece-wise quadratic interpolation of a set of data.
%
% INPUTS:
%   tGrid = [1, 2*n-1] = time at each grid point
%   xGrid = [m, 2*n-1] = function value at each grid point
%   dxGrid = [m, 2*n-1] = function slope at each grid point
%   t = [1, k] = vector of query times (must be contained within tGrid)
%
% OUTPUTS:
%   x = [m, k] = function value at each query time
%
% NOTES:
%   If t is out of bounds, then all corresponding values for x are replaced
%   with NaN
%

nGrid = length(tGrid);
if mod(nGrid-1,2)~=0 || nGrid < 3
    error('The number of grid-points must be odd and at least 3');
end

% Figure out sizes
n = floor((length(tGrid)-1)/2);
m = size(xGrid,1);
k = length(t);
x = zeros(m, k);

% Figure out which segment each value of t should be on
edges = [-inf, tGrid(1:2:end), inf];
[~, bin] = histc(t,edges);

% Loop over each quartic segment
for i=1:n
    idx = bin==(i+1);
    if sum(idx) > 0
        gridIdx = 2*(i-1) + [1,2,3];
        x(:,idx) = quartInterp(...
            tGrid(gridIdx), ...
            xGrid(:,gridIdx), ...
            dxGrid(:,gridIdx), ...
            t(idx));
    end
end

% Replace any out-of-bounds queries with NaN
outOfBounds = bin==1 | bin==(n+2);
x(:,outOfBounds) = nan;

end

function x = quartInterp(tGrid,xGrid,dxGrid,t)
%
% This function computes the interpolant over a single interval
%
% INPUTS:
%   tGrid = [1, 3] = time at endpoints and midpoint
%   xGrid = [m, 3] = function at endpoints and midpoint
%   dxGrid = [m, 3] = derivative at endpoints and midpoint
%   t = [1, p] = query times, spanned by tGrid
%
% OUTPUTS:
%   x = [m, p] = function at query times
%

% Rescale the query points to be on the domain [-1,1]
t = 2*(t-tGrid(1))/(tGrid(3)-tGrid(1)) - 1;

% Unpack function and derivative:
xLow = xGrid(:,1);
xMid = xGrid(:,2);
xUpp = xGrid(:,3);
dxLow = dxGrid(:,1);
dxUpp = dxGrid(:,3);

% Compute the coefficients:
a = dxUpp/4 - dxLow/4 - xLow/2 + xMid - xUpp/2;
b = dxLow/4 + dxUpp/4 + xLow/4 - xUpp/4;
c = dxLow/4 - dxUpp/4 + xLow - 2*xMid + xUpp;
d = (3*xUpp)/4 - dxUpp/4 - (3*xLow)/4 - dxLow/4;
e = xMid;

% Evaluate the polynomial for each dimension of the function:
p = length(t);
m = size(xGrid,1);
x = zeros(m,p);
for i=1:m
    x(i,:) = e(i,:) + t.*(d(i,:) + t.*(c(i,:) + t.*(b(i,:) + t.*a(i,:))));
end

end


% This example demonstrates how to use the auxilliary routine
% (postprocess.m) to calculate the four remaining field
% components (Hz, Ex, Ey, Ez) once the transverse magnetic
% field components (Hx, Hy) are known.  The waveguide
% considered here is a uniaxial channel waveguide with the
% c-axis oriented at pi/4 relative to the x-y axes.

n1 = 1.55;
n2x = 2.156;
n2y = 2.232;
n2z = 2.232;
theta = pi/4;

e2xx = n2x^2*cos(theta)^2 + n2y^2*sin(theta)^2;
e2yy = n2y^2*cos(theta)^2 + n2x^2*sin(theta)^2;
e2xy = cos(theta)*sin(theta)*(n2x^2-n2y^2);
e2yx = e2xy;

Rx = 0.30;
Ry = 0.20;
side = 0.20;

dx = 0.0025;        % grid size (x)
dy = dx;            % grid size (y)

lambda = 1.00;      % wavelength
nmodes = 1;         % number of modes to compute

fprintf (1,'generating index mesh...\n');

[x,y,xc,yc,nx,ny,epsxx,edges] = ...
    waveguidemeshfull([n1,sqrt(e2xx),n1],[side,2*Ry,side],2*Ry,Rx, ...
                  side,dx,dy);
[x,y,xc,yc,nx,ny,epsxy,edges] = ...
    waveguidemeshfull([0,sqrt(e2xy),0],[side,2*Ry,side],2*Ry,Rx, ...
                  side,dx,dy);
[x,y,xc,yc,nx,ny,epsyx,edges] = ...
    waveguidemeshfull([0,sqrt(e2yx),0],[side,2*Ry,side],2*Ry,Rx, ...
                  side,dx,dy);
[x,y,xc,yc,nx,ny,epsyy,edges] = ...
    waveguidemeshfull([n1,sqrt(e2yy),n1],[side,2*Ry,side],2*Ry,Rx, ...
                  side,dx,dy);
[x,y,xc,yc,nx,ny,epszz,edges] = ...
    waveguidemeshfull([n1,n2z,n1],[side,2*Ry,side],2*Ry,Rx, ...
                  side,dx,dy);

% Now we stretch out the mesh at the boundaries:
[x,y,xc,yc,dx,dy] = stretchmesh(x,y,[80,80,80,80],[4,4,4,4]);

[Hx,Hy,neff] = wgmodes (lambda, n2y, nmodes, dx, dy, epsxx, epsxy, epsyx, epsyy, epszz, '0000');

fprintf(1,'neff = %7.5f\n',neff);

[Hz,Ex,Ey,Ez] = postprocess (lambda, neff, Hx, Hy, dx, dy, epsxx, epsxy, epsyx, epsyy, epszz, '0000');

figure(1);

subplot(231);
contourmode(x,y,Hx);
title('Hx');
for v = edges, line(v{:}); end

subplot(232);
contourmode(x,y,Hy);
title('Hy');
for v = edges, line(v{:}); end

subplot(233);
contourmode(x,y,Hz);
title('Hz');
for v = edges, line(v{:}); end

subplot(234);
contourmode(x,y,Ex);
title('Ex');
for v = edges, line(v{:}); end

subplot(235);
contourmode(x,y,Ey);
title('Ey');
for v = edges, line(v{:}); end

subplot(236);
contourmode(x,y,Ez);
title('Ez');
for v = edges, line(v{:}); end

figure(2);

ii = 1;
colormap(jet(256));
hn = abs(interp2(y,x,Hy,side+Ry,0));
en = abs(interp2(yc,xc,Ex,side+Ry,0));

subplot(231);
imagemode(x,y,Hx/hn);
title(sprintf('Hx (mode %d)',ii));
for v = edges, line(v{:}); end

subplot(232);
imagemode(x,y,Hy/hn);
title(sprintf('Hy (mode %d)',ii));
for v = edges, line(v{:}); end

subplot(233);
imagemode(x,y,Hz/hn);
title(sprintf('Hz (mode %d)',ii));
for v = edges, line(v{:}); end

subplot(234);
imagemode(x,y,Ex/en);
title(sprintf('Ex (mode %d)',ii));
for v = edges, line(v{:}); end

subplot(235);
imagemode(x,y,Ey/en);
title(sprintf('Ey (mode %d)',ii));
for v = edges, line(v{:}); end

subplot(236);
imagemode(x,y,Ez/en);
title(sprintf('Ez (mode %d)',ii));
for v = edges, line(v{:}); end


function fx = p05_fx ( x )

%*****************************************************************************80
%
%% P05_FX evaluates ( x + 3 ) * ( x - 1 )^2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 July 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X(*), the point at which F is to be evaluated.
%
%    Output, real FX(*), the value of the function at X.
%
  fx = ( x + 3.0 ) .* ( x - 1.0 ) .* ( x - 1.0 );

  return
end


function [ f, d, s, t ] = cubic_value ( x )

%*****************************************************************************80
%
%% CUBIC_VALUE evaluates a cubic function.
%
%  Discussion:
%
%    f(x) =   x^3 -  7 x^2 + 10 x
%    d(x) = 3 x^2 - 14 x   + 10
%    s(x) = 6 x   - 14
%    t(x) = 6
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 February 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real F, D, S, T, the value and first three derivatives of
%    the cubic function.
%

%
%  If X is a vector, force it to be a column vector.
%
  x = x ( : );

  f = 0.0 + x .* ( 10.0 + x .* (  - 7.0 + x * 1.0 ) );
  d =              10.0 + x .* ( - 14.0 + x * 3.0 );
  s =                            - 14.0 + x * 6.0;
  t =                                         6.0;

  return
end


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

% problem 3 -  Polar form and real and imaginary parts of the DFT of cos(n*pi/3)

n=0:8;
x=cos((1/3)*pi*n);
Xk=fft(x);
Xk.'

A=abs(Xk).*exp(j*angle(Xk));
A.'

B=real(Xk)+j*imag(Xk);
B.'


function R=q2dcm(q)
% Q2DCM(Q) converts quaternions into direction cosine matrices.
%
%     The resultant DCM(s) will perform the same transformations as the
%     quaternion(s) in Q, i.e.:
%
%       R*v = qvxform(q, v)
%
%     where R is the DCM, V is a vector, and Q is the quaternion.  Note that
%     for purposes of quaternion-vector multiplication, a vector is treated
%     as a quaterion with a scalar element of zero.
%
%     If the input, Q, is a vector of quaternions, the output, R, will be
%     3x3xN where input quaternion Q(k,:) corresponds to output DCM
%     R(:,:,k).
%
%     Note that the input Q will be processed by QNORM to ensure normality.
%
% See also DCM2Q, QNORM.

% Release: $Name: quaternions-1_2_2 $
% $Revision: 1.13 $
% $Date: 2002/01/21 06:46:20 $

% Copyright (C) 2000-02, Jay A. St. Pierre.  All rights reserved.

if nargin~=1
  error('q2dcm() requires one input argument');
else
  qtype=isq(q);
  if ( qtype == 0 )
    error(['Invalid input: must be a quaternion or a vector of' ...
          ' quaternions'])
  end
end

% Make sure input is a column of quaternions
if( qtype==1 )
  q=q.';
end

% Make sure quaternion is normalized to prevent skewed DCM
q=qnorm(q);

% Build quaternion element products
q1q1=q(:,1).*q(:,1);
q1q2=q(:,1).*q(:,2);
q1q3=q(:,1).*q(:,3);
q1q4=q(:,1).*q(:,4);

q2q2=q(:,2).*q(:,2);
q2q3=q(:,2).*q(:,3);
q2q4=q(:,2).*q(:,4);

q3q3=q(:,3).*q(:,3);
q3q4=q(:,3).*q(:,4);

q4q4=q(:,4).*q(:,4);

% Build DCM
R(1,1,:) =  q1q1 - q2q2 - q3q3 + q4q4;
R(1,2,:) = 2*(q1q2 + q3q4);
R(1,3,:) = 2*(q1q3 - q2q4);

R(2,1,:) = 2*(q1q2 - q3q4);
R(2,2,:) = -q1q1 + q2q2 - q3q3 + q4q4;
R(2,3,:) = 2*(q2q3 + q1q4);

R(3,1,:) = 2*(q1q3 + q2q4);
R(3,2,:) = 2*(q2q3 - q1q4);
R(3,3,:) = -q1q1 - q2q2 + q3q3 + q4q4;


function OUT = MovAvg(DATA,window)
% =======================================================================
% Moving average of the matrix DATA (TxN). The moving average is
% computed down each column.
% =======================================================================
% OUT = MovAvg(DATA,window)
% -----------------------------------------------------------------------
% INPUT
%   DATA: T observations x N variables [double]
%   window: window of the moving average [double]
% -----------------------------------------------------------------------
% OUPUT
%   OUT: T x N matrix (the first windows-1 observations are NaN) [double]
% -----------------------------------------------------------------------
% EXAMPLE
%   X = rand(20,2);
%   OUT = MovAvg(X,2)
% =======================================================================
% VAR Toolbox 3.0
% Ambrogio Cesa-Bianchi
% ambrogiocesabianchi@gmail.com
% March 2012. Updated November 2020
% -----------------------------------------------------------------------

if nargin<2,                error('Not enough input.'),          end
if window<=0,               error('Window must be positive.'),   end
if (window~=floor(window)), error('Window must be an integer.'), end

if min(size(DATA))==1
    DATA = DATA(:); % forces DATA to be a column vector
end

[nobs,nvar] = size(DATA);
if window>nobs
    error('window must not be greater than the length of DATA.')
end

temp=[];
for row=1:(nobs-window+1),
    temp = [temp; mean(DATA(row:(row+window-1),:))];
end

OUT = temp;
OUT = [nan(window-1,nvar); OUT]; % add nans to make conformable to original


function b_nm = beamWeightsFromFunction(fHandleArray, order)
%BEAMWEIGHTSFROMFUNCTION Generate spherical beamweights for arbitrary pattern
%
%   This function computes the SH coefficients of an arbitrary target
%   beampattern, by performing the SHT on it. The pattern should be
%   specified as a function handle that expects a Kx1 vector of azimuths as
%   first argument, and a vector of Kx1 elevations as the second argument,
%   and return the functions values for these K directions.
%   Multiple patterns can be passed as an array of function handles.
%   The order specifies the maximum SH order of the beamweights.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% BEAMWEIGHTSFROMFUNCTION.M - 10/4/2013
% Archontis Politis, archontis.politis@aalto.fi
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% get a dense uniform design
[~, dirsAziElev] = getTdesign(20);
% convert azi-elev to azi-incl
dirsAziInc = [dirsAziElev(:,1) pi/2-dirsAziElev(:,2)];

Nfunc = length(fHandleArray);
b_nm = zeros((order+1)^2, Nfunc);
for nf =1:Nfunc
    if Nfunc==1, fPattern = fHandleArray;
    else fPattern = fHandleArray{nf};
    end

    % compute the pattern at grid points
    F_dirs = fPattern(dirsAziElev(:,1), dirsAziElev(:,2));

    % get harmonic coefficients
    b_nm(:,nf) = directSHT(order, F_dirs, dirsAziInc, 'real');
end


%% (Internal) Intersection of two sets with tolerance
%
%     [sft_intersect1 idx1 idx2 ] = soft_set_intersect( val1, val2, win_size )
%
%
% Arguments:
%
%   + val1, val2: data elements to be intersected,
%
%   + win_size: tolerance to consider val1(i) == val2(i). In fact we
%   consider equal two elements if val1(val1 >= (val2(i) - win_size) & val1 <= (val2(i) + win_size) )
%
% Output:
%
%   + sft_intersect1: the elements in the soft intersection
%
%   + idx1, idx2: the indexes of val1(idx1) which are in the soft
%   intersection.
%
% Example:
%
%
% See also soft_set_difference, soft_set_union
%
% Author: Mariano Llamedo Soria (llamedom at frba.utn.edu.ar)
% Version: 0.1 beta
% Birthdate: 17/12/2010
% Last update: 17/12/2010
% Copyright 2008-2015
%
function [sft_intersect1, idx1 ] = soft_set_intersect( val1, val2, win_size )

% Find the intersection between index sequence val1-2 within a windows
% win_size.
idx1 = [];

sft_intersect1 = unique(cell2mat(arrayfun(@(a)( colvec( val1(val1 >= (a - win_size) & val1 <= (a + win_size) ) ) ), colvec(val2), 'UniformOutput', false)));

if( nargout > 1)
    [ ~, idx1] = intersect(val1, sft_intersect1);
end


%
%
% Copyright (c) 2012 University of Crete - Computer Science Department (UOC-CSD)
%
% License
%  This file is under the LGPL license,  you can
%  redistribute it and/or modify it under the terms of the GNU Lesser General
%  Public License as published by the Free Software Foundation, either version 3
%  of the License, or (at your option) any later version. This file is
%  distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
%  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
%  PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
%  details.
%
% This function is part of the Covarep project: http://covarep.github.io/covarep
%
% Author
%  Gilles Degottex <degottex@csd.uoc.gr>
%

% Estimate the paramaters of a wrapped normal distribution
% http://en.wikipedia.org/wiki/Wrapped_normal_distribution
function [m s] = wrappednormestim(angles, dim)

    if nargin<2; dim=1; end

    expjangle = exp(1j*angles);

    z = mean(expjangle, dim);

    m = angle(z);

    s = sqrt(-2*log(abs(z)));

    if nargout==0
        hx = -pi:0.1:pi;
        hy = hist(angles, hx);
        hy = hy./sum(hy);

        hold off;
        plot(hx, (hy), 'k');
        hold on;
        p = wrappednormpdf(hx, m, s);
        p = p./sum(p);
        plot(hx, (p), 'b');
        ylim([0 max(p)+0.1]);
        title(['m=' num2str(m) ' s=' num2str(s)]);
    end

return


function hypercube_integrals_test01 ( )

%*****************************************************************************80
%
%% HYPERCUBE_INTEGRALS_TEST01: estimate integrals over the unit hypercube in 3D
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 January 2014
%
%  Author:
%
%    John Burkardt
%
  m = 3;
  n = 4192;
  test_num = 20;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST01\n' );
  fprintf ( 1, '  Compare exact and estimated integrals\n' );
  fprintf ( 1, '  over the interior of the unit hypercube in 3D.\n' );
%
%  Get sample points.
%
  seed = 123456789;
  [ x, seed ] = hypercube01_sample ( m, n, seed );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of sample points used is %d\n', n );
%
%  Randomly choose exponents.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Ex  Ey  Ez     MC-Estimate           Exact      Error\n' );
  fprintf ( 1, '\n' );

  for test = 1 : test_num

    [ e, seed ] = i4vec_uniform_ab ( m, 0, 4, seed );

    value = monomial_value ( m, n, e, x );

    result = hypercube01_volume ( m ) * sum ( value(1:n) ) / n;
    exact = hypercube01_monomial_integral ( m, e );
    error = abs ( result - exact );

    fprintf ( 1, '  %2d  %2d  %2d  %14.6g  %14.6g  %10.2e\n', ...
      e(1:m), result, exact, error );

  end

  return
end


%% RES = factorial(NUM)
%
% Factorial function that works on matrices (matlab's does not).

% EPS, 11/02

function res = factorial(num)

res = ones(size(num));

ind = find(num > 0);
if ( ~isempty(ind) )
  subNum = num(ind);
  res(ind) = subNum .* factorial(subNum-1);
end


function [ x, error_norm, iter, flag ]  = gs ( A, x, b, max_it, tol )

%*****************************************************************************80
%
%% GS solves the linear system Ax=b using the Gauss-Seidel Method.
%
%  Modified:
%
%    02 April 2006
%
%  Reference:
%
%    Richard Barrett, Michael Berry, Tony Chan, James Demmel,
%      June Donato, Jack Dongarra, Victor Eijkhout, Roidan Pozo,
%      Charles Romine, Henk van der Vorst
%    Templates for the Solution of Linear Systems: Building Blocks for
%      Iterative Methods,
%    SIAM Publications, 1993.
%
%  Parameters:
%
%    Input, real A(N,N), the symmetric positive definite matrix.
%
%    Input, real X(N), the initial guess vector.
%
%    Input, real B(N), the right hand side vector.
%
%    Input, integer MAX_IT, the maximum number of iterations.
%
%    Input, real TOL, an error tolerance.
%
%    Output, real X(N), the solution.
%
%    Output, real ERROR_NORM, the norm of the error.
%
%    Output, integer ITER, the number of iterations performed.
%
%    Output, integer FLAG, the return flag.
%    0 = the solution was found to within the specified tolerance.
%    1 = a satisfactory solution was not found.  The iteration limit
%        was exceeded.
%

%
%  Initialization.
%
  flag = 1;
  iter = 0;

  bnrm2 = norm ( b );
  if ( bnrm2 == 0.0 )
    bnrm2 = 1.0
  end

  r = b - A * x;
  error_norm = norm ( r ) / bnrm2;
  errorhist = [ ];
  errorhist(1) = error_norm;

  if ( error_norm < tol )
    flag = 0;
    return
  end
%
%  Split the matrix.
%
  w = 1.0;
  [ M, N, b ] = split ( A, b, w, 3 );

  for iter = 1 : max_it

    x_1 = x;
%
%  Update the approximation.
%
    x = M \ ( N * x + b );
%
%  Compute the error.
%
    error_norm = norm ( x - x_1 ) / norm ( x );
    errorhist(iter+1) = error_norm;
%
%  Check for convergence.
%
    if ( error_norm <= tol )
      flag = 0;
      break
    end

  end

  error_norm = errorhist;

  return
end


function h = r8mat_house_pre ( n, a, row, col )

%*****************************************************************************80
%
%% R8MAT_HOUSE_PRE computes a Householder pre-multiplier matrix.
%
%  Discussion:
%
%    H(ROW,COL) has the property that the COL-th column of
%    H(ROW,COL)*A is zero from entry ROW+1 to the end.
%
%    In the most common case, where a QR factorization is being computed,
%    ROW = COL.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 April 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of the matrices.
%
%    Input, real A(N,N), the matrix whose Householder matrix
%    is to be computed.
%
%    Input, integer ROW, COL, specify the location of the
%    entry of the matrix A which is to be preserved.  The entries in
%    the same column, but higher rows, will be zeroed out if A is
%    premultiplied by H.
%
%    Output, real H(N,N), the Householder matrix.
%

%
%  Set up the vector V.
%
  a_col(1:row-1,1) = 0.0;
  a_col(row:n,1) = a(row:n,col);

  v = r8vec_house_column ( n, a_col, row );
%
%  Form the matrix H(V).
%
  h = r8mat_house_form ( n, v );

  return
end


function [result] = mc(x)

%MC calculates the medcouple, a robust measure of skewness.
%
% The medcouple is described in:
%    Brys, G., Hubert, M. and Struyf, A. (2004),
%    "A Robust Measure of Skewness",
%    Journal of Computational and Graphical Statistics,
%    13, 996-1017.
%
% Required input arguments:
%    x : Data matrix.
%        Rows of x represent observations, and columns represent variables.
%        Missing values (NaN's) and infinite values (Inf's) are allowed, since observations (rows)
%        with missing or infinite values will automatically be excluded from the computations.
%
% The output of MC is a vector containing the medcouple for each column
%     of the data matrix x.
%
% Example:
%    result = mc([chi2rnd(5,1000,1) trnd(3,1000,1)]);
%
% This function is part of LIBRA: the Matlab Library for Robust Analysis,
% available at:
%              http://wis.kuleuven.be/stat/robust.html
%
% Written by Guy Brys
% Last Update: 31/07/2007

if (nargin<1)
    error('No input arguments')
end
[n,p] = size(x);
if n==1
    x = x';
    p = 1;
end
x(sum(~isfinite(x),2)>0,:)=[];
n = size(x,1);
if (n>50000)
    error('When there are more than 50000 observations, the MC may be uncomputable due to memory limitations.')
elseif (n>100)
    result = mcc(x);
elseif n==0
    error('Due to missing values, the data matrix is empty and the MC can not be computed.')
else
    result = 0.5*(-mcc(repmat(max(x),size(x,1),1)-x)+mcc(x));
end


function fx = p18_fx ( x )

%*****************************************************************************80
%
%% P18_FX evaluates the function for problem 18.
%
%  Discussion:
%
%    F(X) = 10^14 * (x-1)^7, but is written in term by term form.
%
%    This polynomial becomes difficult to evaluate accurately when
%    written this way.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 October 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Cleve Moler,
%    Numerical Computing with MATLAB,
%    SIAM, 2004,
%    ISBN13: 978-0-898716-60-3,
%    LC: QA297.M625.
%
%  Parameters:
%
%    Input, real X(*), the point at which F is to be evaluated.
%
%    Output, real FX(*), the value of the function at X.
%
  fx = 10.0^14 * ( ...
            x.^7 ...
     -  7 * x.^6 ...
     + 21 * x.^5 ...
     - 35 * x.^4 ...
     + 35 * x.^3 ...
     - 21 * x.^2 ...
     +  7 * x ...
     -  1 );

  return
end


function [ region_image ] = average_feature_region(im, region_size)
%compute cell wise averages, where a cell is a region_size*region_sized
%region in the image. Input can be uint8t, single or double matrices
%of arbitrary dimension

% region_image = zeros(floor(size(im,1)/region_size),...
%                     floor(size(im,2)/region_size),...
%                     size(im,3), 'single');

region_area = region_size.^2;

if isa(im,'double') || isa(im,'single')
    maxval = 1.0;
elseif isa(im,'unit8')
    maxval = 255;
end;

% for n = 1:size(im,3);

  %compute the integral image
  iImage = integralVecImage(im);
  %region indices
  i1 = (region_size:region_size:size(im,1)) + 1;
  i2 = (region_size:region_size:size(im,2)) + 1;
  %sum over region, divided by number of elements, and normalize to [0,1]
  %range if integer image
  region_image = (iImage(i1,i2,:,:) - iImage(i1,i2-region_size,:,:) - iImage(i1-region_size,i2,:,:) + iImage(i1-region_size,i2-region_size,:,:)) ./ (region_area * maxval);
% end;

end


function M=movwv2at(N,Np);
%MOVWV2AT Oscillating structure of the interferences of the WVD.
%	M=MOVWV2AT(N,Np) generates the movie frames illustrating the
%	influence of the distance between two components on the oscillating
%	structure of the interferences of the WVD.
%
%	N : number of points for the signal;
%	Np : number of snapshots (default : 9)
%	M : matrix of movie frames.
%
%	Example :
%	 M=movwv2at(128,15); movie(M,10);

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

if nargin<1,
 error('At least one argument required');
elseif nargin==1,
 Np=9;
end
Np=odd(Np);

M  = moviein(Np);

c  = Np/0.2;

ampl=amgauss(N/2,N/2,N/2);

for k=1:(Np+1)/2,
 sig=[ampl.*fmconst(N/2,0.25-(k-1)/c);ampl.*fmconst(N/2,0.25+(k-1)/c)];
 [tfr,t,f]=tfrwv(sig);
 Max=max(max(tfr));V=[0.1 0.3 0.5 0.7 0.9]*Max;
 contour(t,f,tfr,V);xlabel('Time'); ylabel('Frequency');
 title('Wigner-Ville distribution'); axis('xy')
 M(:,k) = getframe;
end

for k=(Np+3)/2:Np,
 M(:,k) = M(:,Np+1-k);
end


function rank = gray_code_rank ( n, t )

%*****************************************************************************80
%
%% GRAY_CODE_RANK computes the rank of a Gray code element.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 January 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Donald Kreher, Douglas Simpson,
%    Combinatorial Algorithms,
%    CRC Press, 1998,
%    ISBN: 0-8493-3988-X,
%    LC: QA164.K73.
%
%  Parameters:
%
%    Input, integer N, the number of digits in each element.
%    N must be positive.
%
%    Input, integer T(N), an element of the Gray code.
%    Each entry T(I) is either 0 or 1.
%
%    Output, integer RANK, the rank of the element.
%

%
%  Check.
%
  ierror = gray_code_check ( n, t );

  if ( ierror ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'GRAY_CODE_RANK - Fatal error!\n' );
    fprintf ( 1, '  The input array is illegal.\n' );
    fprintf ( 1, '  IERROR = %d\n', ierror );
    error ( 'GRAY_CODE_RANK - Fatal error!' );
  end

  rank = 0;
  b = 0;

  for i = n - 1 : -1 : 0

    if ( t(n-i) ~= 0 )
      b = 1 - b;
    end

    if ( b == 1 )
      rank = rank + 2^i;
    end

  end

  return
end


function [centroid, dimension_weight, class] = Subspace_Kmeans(data, iteration, K, beta, verbose)

% Pre-allocate weights
centroid = zeros(K,size(data,2)); % centroid for each class
class = zeros(size(data,1),1); % classification result for each observation
dimension_weight = ones(K,size(data,2)); % weights for each dimension in each class

% Initialization
n = size(data,1);
J = 0; % used to record objective function value

% First round
centroid = data(unidrnd(n,K,1),:); % randomly choose K initial centroids
dimension_weight = 1/size(data,2) * dimension_weight; % initialize weights for each dimension using uniform distribution

% Partially optimization
for i = 1:iteration

    J0 = J;

    % body part
    class = classify(centroid,dimension_weight,data);
    centroid = centroid_update(centroid,data,class);
    [dimension_weight,J] = dimension_weight_update(K,centroid,class,dimension_weight,data,beta);

    % whether display intermediate information
    if(verbose == 1)
        disp(['Objective Function(J) Value: ',num2str(J)]);
    end

    % early stop condition
    if(abs(J-J0)<1e-9)
        fprintf('*** Clustering terminates after %i iterations ***\n',i);
        break;
    end
end
end

% Details on the scheme of updating dimension weights
function [alpha,J] = dimension_weight_update(K,m,c,alpha,data,beta)
all_matrix = zeros(size(data,1),size(data,2));
for i = 1:size(data,1)
    all_matrix(i,:) = (m(c(i,1),:)-data(i,:)) .* (m(c(i,1),:)-data(i,:));
end
J = 0;

for i = 1:K
    class_matrix = all_matrix(c==i,:); % pick out data in all_matrix that corresponds to class i
    t_sum = sum(class_matrix,1) + 1e-9; % adding a small positive constant to make weights computatable
    J = J + (alpha(i,:).^beta) * t_sum';
    if(size(class_matrix,1)>0)
        for j = 1:size(alpha,2)
            % variables used to avoid redundant calculation
            tt_numerator = t_sum(1,j);
            t_denominator = sum(tt_numerator./t_sum,2);
            alpha(i,j) = 1/((t_denominator+1e-9)^(1/(beta-1)));
        end
    else
        continue;
    end
end

% Normalize
for i = 1:size(alpha,1)
    alpha(i,:) = alpha(i,:)./(sum(alpha(i,:),2));
end

end

function [result] = classify(m,alpha,data)

result = zeros(size(data,1),1);

% Construct temporary matrix for efficiently computing dimention-weighted distance
matrix = zeros(size(m,1),size(data,2));

for i = 1:size(result,1)
    for j = 1:size(m,1)
        matrix(j,:) = (m(j,:)-data(i,:)) .* (m(j,:)-data(i,:));
    end
    temp = sum(alpha .* matrix,2);

    % To avoid more than one class having the minimum distance.
    t_index = find(temp == min(temp));
    result(i,1) = t_index(1,1);
end
end

function [m] = centroid_update(m,data,c)
for i = 1:size(m,1)
    if(~isempty(data(c==i,:)))
        m(i,:) = mean(data(c==i,:),1);
    else
        continue;
    end
end
end


% The Hurst exponent
%--------------------------------------------------------------------------
% The first 20 lines of code are a small test driver.
% You can delete or comment out this part when you are done validating the
% function to your satisfaction.
%
% Bill Davidson, quellen@yahoo.com
% 13 Nov 2005

function []=hurst_exponent()
disp('testing Hurst calculation');

n=100;
data=rand(1,n);
plot(data);

hurst=estimate_hurst_exponent(data);

[s,err]=sprintf('Hurst exponent = %.2f',hurst);disp(s);

%--------------------------------------------------------------------------
% This function does dispersional analysis on a data series, then does a
% Matlab polyfit to a log-log plot to estimate the Hurst exponent of the
% series.
%
% This algorithm is far faster than a full-blown implementation of Hurst's
% algorithm.  I got the idea from a 2000 PhD dissertation by Hendrik J
% Blok, and I make no guarantees whatsoever about the rigor of this approach
% or the accuracy of results.  Use it at your own risk.
%
% Bill Davidson
% 21 Oct 2003

function [hurst] = estimate_hurst_exponent(data0)   % data set

data=data0;         % make a local copy

[M,npoints]=size(data0);

yvals=zeros(1,npoints);
xvals=zeros(1,npoints);
data2=zeros(1,npoints);

index=0;
binsize=1;

while npoints>4

    y=std(data);
    index=index+1;
    xvals(index)=binsize;
    yvals(index)=binsize*y;

    npoints=fix(npoints/2);
    binsize=binsize*2;
    for ipoints=1:npoints % average adjacent points in pairs
        data2(ipoints)=(data(2*ipoints)+data((2*ipoints)-1))*0.5;
    end
    data=data2(1:npoints);

end % while

xvals=xvals(1:index);
yvals=yvals(1:index);

logx=log(xvals);
logy=log(yvals);

p2=polyfit(logx,logy,1);
hurst=p2(1); % Hurst exponent is the slope of the linear fit of log-log plot

return;


function p = predictOneVsAll(all_theta, X)
%PREDICT Predict the label for a trained one-vs-all classifier. The labels
%are in the range 1..K, where K = size(all_theta, 1).
%  p = PREDICTONEVSALL(all_theta, X) will return a vector of predictions
%  for each example in the matrix X. Note that X contains the examples in
%  rows. all_theta is a matrix where the i-th row is a trained logistic
%  regression theta vector for the i-th class. You should set p to a vector
%  of values from 1..K (e.g., p = [1; 3; 1; 2] predicts classes 1, 3, 1, 2
%  for 4 examples)

m = size(X, 1);
num_labels = size(all_theta, 1);

% You need to return the following variables correctly
p = zeros(size(X, 1), 1);

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

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned logistic regression parameters (one-vs-all).
%               You should set p to a vector of predictions (from 1 to
%               num_labels).
%
% Hint: This code can be done all vectorized using the max function.
%       In particular, the max function can also return the index of the
%       max element, for more information see 'help max'. If your examples
%       are in rows, then, you can use max(A, [], 2) to obtain the max
%       for each row.
%

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

[probability indices] = max(sigmoid(all_theta * X'));
p = indices';

end


function value = r4_modp ( x, y )

%*****************************************************************************80
%
%% R4_MODP returns the nonnegative remainder of R4 division.
%
%  Discussion:
%
%    If
%      REM = R4_MODP ( X, Y )
%      RMULT = ( X - REM ) / Y
%    then
%      X = Y * RMULT + REM
%    where REM is always nonnegative.
%
%    The MOD function computes a result with the same sign as the
%    quantity being divided.  Thus, suppose you had an angle A,
%    and you wanted to ensure that it was between 0 and 360.
%    Then mod(A,360.0) would do, if A was positive, but if A
%    was negative, your result would be between -360 and 0.
%
%    On the other hand, R4_MODP(A,360.0) is between 0 and 360, always.
%
%  Example:
%
%        I         J     MOD R4_MODP  R4_MODP Factorization
%
%      107        50       7       7    107 =  2 *  50 + 7
%      107       -50       7       7    107 = -2 * -50 + 7
%     -107        50      -7      43   -107 = -3 *  50 + 43
%     -107       -50      -7      43   -107 =  3 * -50 + 43
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 January 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the number to be divided.
%
%    Input, real Y, the number that divides X.
%
%    Output, real VALUE, the nonnegative remainder when X is divided by Y.
%
  if ( y == 0.0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R4_MODP - Fatal error!\n' );
    fprintf ( 1, '  R4_MODP ( X, Y ) called with Y = %f\n', y );
    error ( 'R4_MODP - Fatal error!' );
  end

  value = mod ( x, y );

  if ( value < 0.0 )
    value = value + abs ( y );
  end

  return
end


function [cCombo,dataRecur]=getNextRucksackFill(param1,N)
%%GETNEXTRUCKSACKFILL Get the next combination of items with given positive
%               weights that will fit into a rucksack (knapsack, backpack)
%               with a capacity of N. This goes through all feasible
%               combinations (starting with putting nothing in the bag).
%               Going through all feasible combinations is not an efficient
%               approach to determining the set of items that can be placed
%               into the bag to maximize its weight.
%
%INPUTS: param1 To generate the first combination (which will be the empty
%               set - put nothing in the bag) this is w, an nX1 vector
%               holding the weights of each of the items that can be placed
%               in the bag. All weights>0, but need not be integer.
%               Otherwise, this is the dadaRecur output from the previous
%               call to this function.
%             N The capacity of the rucksack. N>0.
%
%OUTPUTS: cCombo The tX1 vector of indices of the items in w that form the
%                current combination of elements that fit into the
%                rucksack. An empty matrix is the first set (out nothing
%                in) and is also returned when the final value has been
%                passed.
%      dataRecur A data structure that can be passed to this function on
%                subsequent calls to get the next value in the sequence. If
%                an empty matrix is reurned, then the final value in the
%                sequence has been passed.
%
%This function implements Algorithm F of Section 7.2.1.3 of [1].
%
%EXAMPLE:
%This displays all of the combination indices for a simple problem.
% w=[1;1.5;5;3;1.5];
% N=6;
% [cCombo,dataRecur]=getNextRucksackFill(w,N);
% while(~isempty(dataRecur))
%     cCombo
%     [cCombo,dataRecur]=getNextRucksackFill(dataRecur);
% end
%
%REFERENCES:
%[1] D. E. Knuth, The Art of Computer Programming. Vol. 4A: Combinatorial
%    Algorithms, Part I, Boston: Addison-Wesley, 2011.
%
%October 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%If we are getting the first filling possibility (the empty sack).
if(nargin==2)
    w=param1;%The set of all-positive weights.
    [w,idx]=sort(w,'ascend');

    n=length(w);
    deltaJ=w(2:n)-w(1:(n-1));

    %The extra one at the beginning is for unassigned weights.
    c=zeros(n+1,1);

    %Step F1, Initialize
    t=0;
    c(0+1)=n;
    r=N;
    %The initial combination is the empty set.
    cCombo=[];
    dataRecur.w=w;
    dataRecur.idx=idx;
    dataRecur.deltaJ=deltaJ;
    dataRecur.c=c;
    dataRecur.r=r;
    dataRecur.t=t;
    return;
else
    dataRecur=param1;
    w=dataRecur.w;
    idx=dataRecur.idx;
    deltaJ=dataRecur.deltaJ;
    c=dataRecur.c;
    r=dataRecur.r;
    t=dataRecur.t;
end

%Step F3, try to add w(0).
if(c(t+1)>0&&r>=w(0+1))
    t=t+1;
    c(t+1)=0;
    r=r-w(0+1);

    %Step F2, visit the current combination.
    cCombo=idx(c(2:(t+1))+1);
    dataRecur.t=t;
    dataRecur.c=c;
    dataRecur.r=r;
    return;
end

while(1)
    if(t==0)%We have passed the last combination.
        cCombo=[];
        dataRecur=[];
        return;
    end

    if(c(t-1+1)>c(t+1)+1&&r>=deltaJ(c(t+1)+1))
        %Step F4
        c(t+1)=c(t+1)+1;
        r=r-deltaJ(c(t+1));
        %Step F2, visit the current combination.
        cCombo=idx(c(2:(t+1))+1);
        dataRecur.t=t;
        dataRecur.c=c;
        dataRecur.r=r;
        return
    else
        %Step F5
        r=r+w(c(t+1)+1);
        t=t-1;
    end
end

end

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