function[varargout]=trajchunk(varargin)
%TRAJCHUNK  Chunks Lagrangian trajectories based on the Coriolis period.
%
%   TRAJCHUNK is used to split float or drifter data into chunks such that
%   the length of each chunk is a fixed multiple of one over the mean
%   Coriolis frequency. This can be useful in spectral analysis.
%
%   [NUMO,LATO]=TRAJCHUNK(NUM,LAT,P), where NUM and LAT are date number and
%   latitude for Lagangian float or drifter data, re-organizes these into
%   chunks such that the average Coriolis frequency f_C in each chunk is at
%   least P times the Rayleigh frequency f_R for that chunk.
%
%   The Rayleigh frequency is f_R=2*pi/(DT*N), in units of radians per unit
%   time, where DT is the sample interval and N is the number of samples.
%   The Rayleigh frequency decreases as the chunk length increases.
%
%   The input fields NUM and LAT may either be numerical arrays, or
%   cell arrays of numerical arrays, e.g. NUM{1}=NUM1, NUM{2}=NUM2, etc.
%
%   The output variables NUM and LAT are cell arrays of numerical arrays,
%   with each cell being just long enough such that f_C > P * f_R.
%
%   Trajectories that are not long enough to satisfy this criterion are
%   discarded, as are short residual segments at the end of trajectories.
%
%   Each input trajectory is thus split into zero, one, or more than one
%   cells in the output variables.
%
%   TRAJCHUNK(...,P,LMIN) additionally specifies a mininum number of points
%   LMIN for each chunk.
%   __________________________________________________________________
%
%   Multiple input / output arguments
%
%   [NUMO,LATO,Y1,Y2,...,YM]=TRAJCHUNK(NUM,LAT,X1,X2,...XM,P) chunks the M
%   input arrays X1, X2,... XM in the same manner, and returns these as Y1,
%   Y2,... YM.  The input variables may either all be numerical arrays of
%   all the same size, or cell arrays of numerical arrays.
%
%   In the case of cell array input, some of the XM may be numerical arrays
%   of the same length as the cells NUM and LAT.  The corresponding output
%   variable will then also be a numerical array.  An example of such a
%   field is the identification number used in FLOATS.MAT and DRIFTERS.MAT.
%
%   TRAJCHUNK with no output arguments overwrites the original named output
%   variables.
%   __________________________________________________________________
%
%   Optional behaviors
%
%   By default, any data in short trajectories for which f_C < P * f_R are
%   discarded, as are data segments at the end of the trajectories.
%
%   TRAJCHUNK(...,'keep') keeps these instead.  Short trajectories are
%   returned in their own chunks, and leftover segments are appended to
%   the end of the preceding chunk.
%
%   TRAJCHUNK(...,'full') instead ensures that the output cells span the
%   full duration of the input fields.  This is done by appending a final
%   cell having f_C > P * f_R, like the others, but that ends at the final
%   data point, regardless of the degree of overlap with the previous cell.
%   Data from cells shorter than the specified length are discarded.
%   __________________________________________________________________
%
%   Overlap
%
%   TRAJCHUNK(...,'overlap',PCT) outputs chunks with a percentage PCT
%   overlap.  For example, TRAJCHUNK(...,'overlap',50) outputs chunks that
%   overlap by 50%.  The default behavior gives chunks with no overlap.
%   __________________________________________________________________
%
%   See also CELLCHUNK.
%
%   'trajchunk --t' runs a test.
%
%   Usage: [num,lat]=trajchunk(num,lat,P);
%          [num,lat,lon,cv]=trajchunk(num,lat,lon,cv,P);
%          [num,lat,lon,cv]=trajchunk(num,lat,lon,cv,P,lmin);
%          [num,lat,lon,cv]=trajchunk(num,lat,lon,cv,P,'overlap',50);
%          trajchunk(num,lat,lon,cv,P);
%   __________________________________________________________________
%   This is part of JLAB --- type 'help jlab' for more information
%   (C) 2014--2019 J.M. Lilly --- type 'help jlab_license' for details

%   [...,II,KK]=TRAJCHUNK(...) in this case also outputs the indices of
%   the data locations within the input cells.  KK is not a cell array
%   like the other output arguments, but rather a row array of LENGTH(II).

%   [..,II]=TRAJCHUNK(...), with an extra final output argument,
%   outputs a cell array II of indices to the original time series.
%
%   As an example, LAT(II{1}) gives the latitudes of the data in the first
%   cell of the output, LATO{1}.

%   Equivalently, this means that the inertial period 2*pi/f_C is just less
%   than 1/M times the chunk duration DT*N, or 2*pi/f_C < (1/M) * (DT*N).
%   Thus M inertial oscillations fit into each chunk.
%   Not completely sure about the wording of this due to the definition of
%   'mean Coriolis frequency' etc.

if strcmpi(varargin{1}, '--t')
    trajchunk_test,return
end

factor=1;
opt='nokeep';     %What to do with leftover points

for i=1:2
    if ischar(varargin{end})
        if strcmpi(varargin{end}(1:3),'kee')||strcmpi(varargin{end}(1:3),'nok')||strcmpi(varargin{end}(1:3),'ful')
            opt=varargin{end};
            varargin=varargin(1:end-1);
        end
    end
    if ischar(varargin{end-1})
        if strcmpi(varargin{end-1}(1:3),'ove')
            factor=1-varargin{end}/100;
            varargin=varargin(1:end-2);
        end
    end
end

if ~iscell(varargin{end-1})&&length(varargin{end-1})==1
    N=varargin{end-1};
    M=varargin{end};
    varargin=varargin(1:end-2);
else
    N=varargin{end};
    M=0;
    varargin=varargin(1:end-1);
end

num=varargin{1};
lat=varargin{2};
%Note: leave num and lat as first two entries also
na=length(varargin);

%na,N,M,size(num),size(lat),str,opt
if ~iscell(lat)
    %Create ii index
    varargin{na+1}=[1:length(lat)]';
    index=trajchunk_index(num,lat,N,M,opt,factor);
    n=0;
    if ~isempty(index)
        for k=1:length(index)
            n=n+1;
            for j=1:na+1
                varargout{j}{n,1}=varargin{j}(index{k});
            end
        end
    end
else
    %/**************
    %Put numerical array input into cell arrays
    bid=false(size(varargin));
    for i=3:length(bid) %Lat and lon are not allowed to be arrays
        if ~iscell(varargin{i})
            bid(i)=true;
            varargin{i}=celladd(varargin{i},cellmult(0,varargin{1}));
        end
    end
    %\**************

%     %Create ii and kk indices
%     for i=1:length(lat)
%         varargin{na+1}{i}=[1:length(lat{i})]';
%         varargin{na+2}{i}=i+0*lat{i};
%     end
    index=[];
    for i=1:length(lat)
        if length(lat)>1000
            if res((i-1)/1000)==0
                disp(['TRAJCHUNK working on cells ' int2str(i) ' to ' int2str(min(i+1000,length(lat))) ' of ' int2str(length(lat)) '.'])
            end
        end
        index{i,1}=trajchunk_index(num{i},lat{i},N,M,opt,factor);
    end
    n=0;
    for i=1:length(lat)
        if ~isempty(index{i})
            for k=1:length(index{i})
                n=n+1;
                for j=1:na
                    varargout{j}{n,1}=varargin{j}{i}(index{i}{k});
                end
            end
        end
    end

    %Return numerical array input back to numerical arrays
    for i=1:length(bid)
        if bid(i)
            varargout{i}=cellfirst(varargout{i});
        end
    end

%     %i,j,k,n
%     %Convert cell array kk into numeric array
%     temp=varargout{na+2};
%     varargout{na+2}=zeros(size(varargout{na+1}));
%     for i=1:length(varargout{na+1})
%         varargout{na+2}(i)=temp{i}(1);
%     end
end

eval(to_overwrite(na));

function[index]=trajchunk_index(num,lat,N,M,opt,factor)
if length(num)<2
    index=[];
else
    dt=num(2)-num(1);

    fo=abs(corfreq(lat))*24;
    meanfo=frac(cumsum(fo),[1:length(fo)]');
    fr=frac(2*pi,dt*[1:length(fo)]');
    %aresame(meanfo(end),vmean(fo,1))

    bdone=false;
    n=0;

    x=[1:length(fo)]';
    index=[];
    while ~bdone
        ii=max(find(N*fr<meanfo,1,'first'),M);
        n=n+1;
        if isempty(ii)||ii>=length(x)
            bdone=1;
        else
            index{n}=x(1:ii);
            %N*fr(ii)<meanfo(ii)
            if ii<length(x)
                x=x(floor(ii*factor)+1:end);
                fo=fo(floor(ii*factor)+1:end);
                %fr=fr(ii+1:end)-fr(ii+1)+frac(2*pi,dt);
                meanfo=frac(cumsum(fo),[1:length(fo)]');
                fr=frac(2*pi,dt*[1:length(fo)]');
                %aresame(meanfo(end),vmean(fo,1))
            end
        end
    end

    % if ~isempty(index)
    %     if strcmpi(opt(1:3),'kee')
    %         index{end}=index{end}(1):x(end);
    %     end
    % end
    if strcmpi(opt(1:3),'kee')
        if ~isempty(index)
            index{end}=index{end}(1):x(end);  %Append leftovers
        else
            index{1}=x;  %Keep short segments
        end
    elseif strcmpi(opt(1:3),'ful')
        indexlast=trajchunk_index(num,flipud(lat),N,M,'nokeep',1);
        indexlast=length(lat)-flipud(indexlast{1})+1;
        index{end+1}=indexlast;
        %maxmax(indexlast),length(lat)
    end
end
function[]=trajchunk_test

load ebasnfloats

use ebasnfloats
dt=1;
trajchunk(num,lat,lon,32);
meanfo=vmean(abs(corfreq(col2mat(cell2col(lat)))),1)'*24*dt;
fr=frac(2*pi,dt*cellength(lat));
reporttest('TRAJCHUNK no overlap',allall(meanfo>32*fr))
%length(num),length(cell2col(num))

use ebasnfloats
dt=1;
trajchunk(num,lat,lon,32,'overlap',50);
meanfo=vmean(abs(corfreq(col2mat(cell2col(lat)))),1)'*24*dt;
fr=frac(2*pi,dt*cellength(lat));
reporttest('TRAJCHUNK overlap',allall(meanfo>32*fr))

% load drifterheyerdahl
% use drifterheyerdahl
%
% [numc,latc]=trajchunk(num,lat,60,'overlap',50);
% [~,latc2,numc2]=trajchunk(num,flipud(lat),flipud(num),60,'overlap',50);
%
% min(cellmin(numc))-min(num)
% max(cellmax(numc))-max(num)
%
% numc{end+1}=flipud(numc2{1});
% latc{end+1}=flipud(latc2{1});
%
% for i=1:length(numc)
%     P(i)=sum(abs(corfreq(latc{i}))*24.*(numc{i}-numc{i}(1))/2/pi/24);
% end
%
% plot(cellmax(numc)-cellmin(numc))
% plot(60*2*pi./(cellmean(cellabs(corfreq(latc)))*24))

%length(num),length(cell2col(num))

% with minimum length
%
%     trajchunk(num,lat,lon,32,35);
%
% load drifters
% use drifters
% %trajchunk(num,lat,lon,32,'overlap');
% trajchunk(num,lat,lon,128);
%
% %meanfo=zeros(length(num),1);
% %fr=zeros(length(num),1);
%
% %dt=1/4;
%
% %Same as below but faster
% tic
% meanfo=vmean(abs(corfreq(col2mat(cell2col(lat)))),1)'*24*dt;
% fr=frac(2*pi,dt*cellength(lat));
% toc
%
% % tic
% % for i=1:length(num)
% %     meanfo(i)=vmean(abs(corfreq(lat{i})),1)*24*dt;
% %     fr(i)=frac(2*pi,dt*length(lat{i}));
% % end
% % toc
%
% figure,plot(meanfo,'b.'),hold on,plot(32*fr,'ro')
% figure,plot(2*pi./(meanfo/32),'b.'),hold on,plot(2*pi./fr,'ro')
% figure,plot(2*pi./(meanfo/32),2*pi./fr,'ro'),axis equal


function timespvals(options, n, d)
% TIMESPVALS   Measure the performance of SPVALS
%    TIMESPVALS(OPTIONS)  Script file to test the performance of the
%    sparse grid interpolation routine SPVALS by measuring the
%    required time to compute the hierarchical surpluses. By default,
%    the Clenshaw-Curtis grid is used. Other grid types can be
%    selected using the SPSET method.
%
%    TIMESPVALS(OPTIONS, D)  argument D contains the dimension that
%    the performance should be measured and graphed for, N
%
% Note: This demo takes a couple of minutes to run.
%
%    See also SPSET, SPVALS, TESTFUNCTIONS.

% Author : Andreas Klimke, Universitaet Stuttgart
% Version: 1.6
% Date   : May 31, 2006

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

if nargin < 1, options = []; end
if nargin < 2, n = []; d = []; end

sparseIndices = spget(options, 'SparseIndices', 'auto');
gridtype = spget(options, 'GridType', 'Clenshaw-Curtis');
enableDCT = spget(options, 'EnableDCT', 'on');

plotasymptotic = 0;

% Set the problem dimensions and the maximum discretization levels
% for each dimension.
switch lower(gridtype)
 case 'clenshaw-curtis'
  if isempty(d)
    d = [1,2,4,8,16];
    n = [17,13,10,6,4];
  end
  if strcmpi(sparseIndices, 'off')
    plotasymptotic = 1;
  end
 case 'noboundary'
  if isempty(d)
    d = [1,2,4,8,16];
    n = [15,11,8,5,4];
  end
 case 'maximum'
	if isempty(d)
    d = [1,2,4,8];
    n = [16,12,7,2];
  end
 case 'chebyshev'
  if isempty(d)
    d = [1,2,4,8,16];
    if strcmpi(enableFFT, 'on')
      n = [17,13,10,6,4];
    else
      n = [15,13,10,6,4];
    end
  end
 otherwise
	error('Unknown grid type.');
end

ndims = length(n);
markers = ['s', '.', 'd', '+', 'o', 'x', '*', 'v', '^'];

%  Compute random constants w and c for Gerz' test functions.
w = rand(d(end),1);
c = rand(d(end),1);
sumc = sum(c,1);
sumw = sum(w,1);
c = 1.5.*c/sumc;
w = w/sumw;

time = NaN*ones(ndims,n(1)+1);
npoints = zeros(ndims,n(1)+1);

for m = 1:ndims
	disp(['Current dim: ' num2str(d(m))]);
	z = [];
	for l = 0:n(m)
		disp(['Current level n = ' num2str(l) '...']);
		options = spset('MinDepth',l,'MaxDepth',l,'Vectorized','on', ...
										'GridType', gridtype, 'EnableDCT', enableDCT, ...
										'SparseIndices', sparseIndices, 'PrevResults', z);
		z = spvals('testfunctions',d(m),[],options,1,c(1:d(m)),w(1: ...
																									d(m)));
		t = z.surplusCompTime;
		disp(['Computing sparse grid points and evaluating function took ' ...
					num2str(z.fevalTime) ' [s].']);
		time(m,l+1) = t;
		disp(['Computing hierarchical surpluses took ' num2str(t) ' [s].']);
		disp(' ');
		npoints(m,l+1) = z.nPoints;
	end
end

% Plot results
h = loglog(npoints(:,2:end)', time(:,2:end)', 'LineWidth', 1);
axis tight;
for k = 1:ndims
	set(h(k), 'Marker', markers(k));
	hold on;
end
axis manual;

% Plot assymtotic curves for two cases
if plotasymptotic
	for nd = [1 ndims]
		asymptotic = zeros(n(nd),1);
		for k = 0:n(nd)
			levelseq = double(spgetseq(k,d(nd))');
			seqpoints = prod((levelseq <= 1) .* 2.^levelseq + ...
											 (levelseq > 1) .* 2.^(levelseq-1));

			asymptotic(k+1) = sum((prod(levelseq+1)-1).*seqpoints)*min(n(nd),d(nd));
			if k > 0
				asymptotic(k+1) = asymptotic(k+1) + asymptotic(k);
			end
		end
		const = 1./asymptotic(end).*time(nd,n(nd)+1);
		plot(npoints(nd,1:n(nd)+1),asymptotic.*const,'k--');
	end
end

% Add legend and axis labels
hold off;
title(['Time to compute hierarchical surpluses for ' gridtype ' grid']);
ylabel('time [s]');
xlabel('number of nodes N');
s = {};
for k = 1:ndims
  s{k} = ['d = ' num2str(d(k))];
end

if plotasymptotic
	s{ndims+1} = 'asymptotic';
end
legend(s,2);


function h = heaviside(f)
%HEAVISIDE   Heaviside function of a CHEBFUN.
%   HEAVISIDE(F) returns a CHEBFUN which is 0 when F < 0, +1 when F > 0, and
%   0.5 when F == 0.
%
% See also DIRAC, SIGN.

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

% HEAVISIDE() is basically a wrapper for SIGN().
h = .5*(sign(f) + 1);

end


function kmph = ftps2kmph(ftps)
%FTPS2KMPH Convert speed from feet per second to kilometers per hour
%
%  kmph = FTPS2KMPH(ftps) converts speeds from feet per second to
%   kilometers per hour.
%
%  See also FTPS2KTS, FTPS2MPH, FTPS2MPS, KMPH2FTPS.

% Jonathan Sullivan
% Original: May 2011
% jonathan.sullivan@ll.mit.edu

kmph = ftps*1.09728;


function pass = test_parSimp(varargin)

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

S = loadtests;

pass = zeros(numel(S), 1);
for k = 1:numel(S)
    str = stringParser.parSimp(S{k}{1});
    pass(k) = strcmp(str,S{k}{2});
end

function S = loadtests
% BVPs
S{1} = {'((0.02.*diff(u,2)+diff(u))+u)',
    '0.02.*diff(u,2)+diff(u)+u'};
S{2} = {'((0.01.*diff(u,2)-x.*u)-1)',
    '0.01.*diff(u,2)-x.*u-1'};
S{3} = {'((x.^(2).*diff(u,2)+x.*diff(u))+(x.^(2)-3.^(2)).*u)',
    'x.^2.*diff(u,2)+x.*diff(u)+(x.^2-3.^2).*u'};
S{4} = {'(((0.01.*diff(u,2)+2.*(1-x.^(2)).*u)+u.^(2))-1)',
    '0.01.*diff(u,2)+2.*(1-x.^2).*u+u.^2-1'};
S{5} = {'((diff(u,2)+(1.2+sign((10-abs(x)))).*u)-1)',
    'diff(u,2)+(1.2+sign((10-abs(x)))).*u-1'};
S{6} = {'((diff(u,2)+u)-u.^(2))',
    'diff(u,2)+u-u.^2'};
S{7} = {'(diff(u,4)-(diff(u).*diff(u,2)-u.*diff(u,3)))',
    'diff(u,4)-diff(u).*diff(u,2)+u.*diff(u,3)'};
S{8} = {'(diff(u,2)+.87.*exp(u))',
    'diff(u,2)+.87.*exp(u)'};
S{9} = {'((.0005.*diff(u,2)+x.*(x.^(2)-0.5).*diff(u))+3.*(x.^(2)-0.5).*u)',
    '.0005.*diff(u,2)+x.*(x.^2-0.5).*diff(u)+3.*(x.^2-0.5).*u'};
S{10} = {'((.01.*diff(u,2)+u.*diff(u))-u)',
    '.01.*diff(u,2)+u.*diff(u)-u'};
S{11} = {'(diff(u,2)+sin(u))',
    'diff(u,2)+sin(u)'};
S{12} = {'((0.05.*diff(u,2)+diff(u).^(2))-1)',
    '0.05.*diff(u,2)+diff(u).^2-1'};
S{13} = {'(diff(u,2)-8.*sinh(8.*u))',
        'diff(u,2)-8.*sinh(8.*u)'};
S{14} = {'(diff(u,2)-(u-1).*(1+diff(u).^(2)).^(1.5))',
    'diff(u,2)-(u-1).*(1+diff(u).^2).^1.5'};
S{15} = {'((diff(u,2)-x.*sin(u))-1)',
    'diff(u,2)-x.*sin(u)-1'};
S{16} = {'((diff(u,2)-(1-u.^(2)).*diff(u))+u)',
    'diff(u,2)-(1-u.^2).*diff(u)+u'};
S{17} = {'(diff(u,2)-sin(v))',
    'diff(u,2)-sin(v)'};
S{18} = {'(diff(u,2)-sin(v))',
    'diff(u,2)-sin(v)'};
S{19} = {'(cos(u)+diff(v,2))',
    'cos(u)+diff(v,2)'};

% PDEs
S{20} = {'+(0.1.*diff(u,2)+diff(u))',
    '0.1.*diff(u,2)+diff(u)'};
S{21} = {'+((.01.*diff(u,2)+u)-u.^(3))',
    '.01.*diff(u,2)+u-u.^3'};
S{22} = {'+(-diff(u.^(2))+.02.*diff(u,2))',
    '-diff(u.^2)+.02.*diff(u,2)'};
S{23} = {'+(-.003.*diff(u,4)+diff((u.^(3)-u),2))',
    '-.003.*diff(u,4)+diff(u.^3-u,2)'};
S{24} = {'+0.1.*diff(u,2)',
    '0.1.*diff(u,2)'};
S{25} = {'+(.02.*diff(u,2)+cumsum(u).*sum(u))',
    '.02.*diff(u,2)+cumsum(u).*sum(u)'};
S{26} = {'+((u.*diff(u)-diff(u,2))-0.006.*diff(u,4))',
    'u.*diff(u)-diff(u,2)-0.006.*diff(u,4)'};

% Systems
S{27} = {'+((-u+(x+1).*v)+0.1.*diff(u,2))',
    '-u+(x+1).*v+0.1.*diff(u,2)'};
S{28} = {'+((u-(x+1).*v)+0.2.*diff(v,2))',
    'u-(x+1).*v+0.2.*diff(v,2)'};
S{29} = {'+(0.1.*diff(u,2)-100.*u.*v)',
    '0.1.*diff(u,2)-100.*u.*v'};
S{30} = {'+(.2.*diff(v,2)-100.*u.*v)',
    '.2.*diff(v,2)-100.*u.*v'};
S{31} = {'+(0.001.*diff(w,2)+200.*u.*v)',
    '0.001.*diff(w,2)+200.*u.*v'};
S{32} = {'+(diff(u,2)-v)',
    'diff(u,2)-v'};
S{33} = {'(diff(v,2)-u)',
    'diff(v,2)-u'};
S{34} = {'+(diff(u,2)+exp(-100.*x.^(2)).*sin(pi.*t))',
    'diff(u,2)+exp(-100.*x.^2).*sin(pi.*t)'};

% EIGs
S{35} = {'(diff(u,2)+diff(u))',
    'diff(u,2)+diff(u)'};
S{36} = {'(-diff(u,2)+1i.*x.^(2).*u)',
    '-diff(u,2)+1i.*x.^2.*u'};
S{37} = {'(-.1.*diff(u,2)+4.*(sign((x+1))-sign((x-1))).*u)',
    '-.1.*diff(u,2)+4.*(sign((x+1))-sign((x-1))).*u'};
S{38} = {'(-diff(u,2)+x.^(2).*u)',
    '-diff(u,2)+x.^2.*u'};
S{39} = {'(-diff(u,2)+5.*cos(2.*x).*u)',
    '-diff(u,2)+5.*cos(2.*x).*u'};
S{40} = {'((diff(u,2)+u.*x)+v)',
    'diff(u,2)+u.*x+v'};
S{41} = {'(diff(v,2)+sin(x).*u)',
    'diff(v,2)+sin(x).*u'};

% MISC

% Check exponential notation
S{42} = {'(diff(v,2)-1e-2*u)',
    'diff(v,2)-1e-2*u'};
S{43} = {'(diff(v,2)-1e+2*u)',
    'diff(v,2)-1e+2*u'};
S{44} = {'(diff(v,2)+1e-2*u)',
    'diff(v,2)+1e-2*u'};
S{45} = {'(diff(v,2)+1e+2*u)',
    'diff(v,2)+1e+2*u'};

% Check division (see GitHub #2357).
S{46} = {'diff(y)-(2/3)/4',
    'diff(y)-2/3/4'};
S{47} = {'diff(y)-2/(3/4)',
    'diff(y)-2/(3/4)'};
S{48} = {'diff(y)-1/(2*(y-1))',
    'diff(y)-1/(2*(y-1))'};


% StackExchange Signal Processing Q86094
% https://dsp.stackexchange.com/questions/86094
% Analyzing 2 2D Kernels Which Approximates a Gaussian Kernel
% References:
%   1.
% Remarks:
%   1.  B
% TODO:
% 	1.  C
% Release Notes Royi Avital RoyiAvital@yahoo.com
% - 1.0.000     10/01/2023
%   *   First release.

%% General Parameters

subStreamNumberDefault = 79;

run('InitScript.m');

figureIdx           = 0;
figureCounterSpec   = '%04d';

generateFigures = ON;

%% Constants

KERNEL_A = 1; %<! The 1st kernel
KERNEL_B = 2; %<! The 2nd Kernel

%% Parameters

mK1 = (1 / 16) * [1, 2, 1; 2, 4, 2; 1, 2, 1];
mK2 = (1 / 48) * [0, 1, 2, 1, 0; 1, 2, 4, 2, 1; 2, 4, 8, 4, 2; 1, 2, 4, 2, 1; 0, 1, 2, 1, 0];

%% Generate / Load Data

%% Analysis

% Padding the 1st array to have the same size as the 2nd
mK1 = padarray(mK1, [1, 1], 0, 'both');

% SVD Decomposition of the kernels
[mU1, mS1, mV1] = svd(mK1);
[mU2, mS2, mV2] = svd(mK2);

% Separable (Approximation)
mD1 = mS1(1, 1) * mU1(:, 1) * mV1(:, 1).';
mD2 = mS2(1, 1) * mU2(:, 1) * mV2(:, 1).';

vU1 = sqrt(mS1(1, 1)) * mU1(:, 1);
vU2 = sqrt(mS2(1, 1)) * mU2(:, 1);

vU1U2 = vU1 - vU2;
vU2U1 = vU2 - vU1;

%% Display Results

figureIdx = figureIdx + 1;

maxVal = max(max(mK1(:)), max(mK2(:)));

hF = figure('Position', [100, 100, 900, 400]);
hA   = subplot(1, 2, 1);
hImgObj = imagesc(mK1);
set(hA, 'CLim', [0, maxVal]);
set(hA, 'DataAspectRatio', [1, 1, 1]);
set(get(hA, 'Title'), 'String', {['Kernel A']}, ...
    'FontSize', fontSizeTitle);

hA   = subplot(1, 2, 2);
hImgObj = imagesc(mK2);
set(hA, 'CLim', [0, maxVal]);
set(hA, 'DataAspectRatio', [1, 1, 1]);
set(get(hA, 'Title'), 'String', {['Kernel B']}, ...
    'FontSize', fontSizeTitle);

if(generateFigures == ON)
    % saveas(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
    print(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png'], '-dpng', '-r0'); %<! Saves as Screen Resolution
end

figureIdx = figureIdx + 1;

maxVal = max(max(mD1(:)), max(mD2(:)));

hF = figure('Position', [100, 100, 900, 400]);
hA   = subplot(1, 2, 1);
hImgObj = imagesc(mD1);
set(hA, 'CLim', [0, maxVal]);
set(hA, 'DataAspectRatio', [1, 1, 1]);
set(get(hA, 'Title'), 'String', {['Separable Approximation of Kernel A']}, ...
    'FontSize', fontSizeTitle);

hA   = subplot(1, 2, 2);
hImgObj = imagesc(mD2);
set(hA, 'CLim', [0, maxVal]);
set(hA, 'DataAspectRatio', [1, 1, 1]);
set(get(hA, 'Title'), 'String', {['Separable Approximation of Kernel B']}, ...
    'FontSize', fontSizeTitle);

if(generateFigures == ON)
    % saveas(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
    print(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png'], '-dpng', '-r0'); %<! Saves as Screen Resolution
end

figureIdx = figureIdx + 1;

hF = figure('Position', figPosLarge);
hA   = axes(hF);
set(hA, 'NextPlot', 'add');
hLineObj = plot(-mU1(:, 1), 'DisplayName', 'Kernel A');
set(hLineObj, 'LineWidth', lineWidthNormal);
hLineObj = plot(-mU2(:, 1), 'DisplayName', 'Kernel B');
set(hLineObj, 'LineWidth', lineWidthNormal);
set(get(hA, 'Title'), 'String', {['Separable Filters of the Kernels']}, ...
    'FontSize', fontSizeTitle);
hLegend = ClickableLegend();

if(generateFigures == ON)
    % saveas(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
    print(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png'], '-dpng', '-r0'); %<! Saves as Screen Resolution
end

figureIdx = figureIdx + 1;

hF = figure('Position', [100, 100, 1200, 800]);
hA   = subplot(1, 2, 1);
[~, ~, hLineObj] = PlotDft(vU1U2, 1, 'plotTitle', 'DFT of Kernal A - Kernel B in 1D Seprable Approximation', 'numFreqBins', 100);
set(hLineObj, 'LineWidth', lineWidthNormal);

hA   = subplot(1, 2, 2);
[~, ~, hLineObj] = PlotDft(vU2U1, 1, 'plotTitle', 'DFT of Kernal B - Kernel A in 1D Seprable Approximation', 'numFreqBins', 100);
set(hLineObj, 'LineWidth', lineWidthNormal);

if(generateFigures == ON)
    % saveas(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
    print(hF, ['Figure', num2str(figureIdx, figureCounterSpec), '.png'], '-dpng', '-r0'); %<! Saves as Screen Resolution
end

% figureIdx = figureIdx + 1;
%
% hFigure = figure('Position', figPosLarge);
% hAxes   = axes(hFigure);
% set(hAxes, 'NextPlot', 'add');
% hLineObj = plot(vTheta, 10 * log10(abs(vM)));
% set(hLineObj, 'LineWidth', lineWidthNormal);
%
% set(get(hAxes, 'Title'), 'String', {['MUSIC Pseudo Spectrum']}, ...
%     'FontSize', fontSizeTitle);
% set(get(hAxes, 'XLabel'), 'String', {['Spatial Angle [Deg]']}, ...
%     'FontSize', fontSizeAxis);
% set(get(hAxes, 'YLabel'), 'String', {['Value [dB]']}, ...
%     'FontSize', fontSizeAxis);
%
% hLineObj = plot(vTheta(vPeakIdx(1:numSig)), 10 * log10(abs(vPeakVal(1:numSig))));
% set(hLineObj, 'LineStyle', 'none', 'LineWidth', lineWidthNormal, 'Marker', 'x', 'MarkerSize', markerSizeLarge, 'Color', 'r');
% for ii = 1:numSig
%     hLineObj = xline(vTheta(vPeakIdx(ii)), '-', {['Angle: ', num2str(vTheta(vPeakIdx(ii))), ' [Deg]']});
%     set(hLineObj, 'LineStyle', ':', 'LineWidth', lineWidthThin, 'Color', 'r');
% end
%
% % hLegend = ClickableLegend({['Ground Truth'], ['Input Noisy Samples'], ['TV Estimation']});
%
% if(generateFigures == ON)
%     % saveas(hFigure, ['Figure', num2str(figureIdx, figureCounterSpec), '.png']);
%     print(hFigure, ['Figure', num2str(figureIdx, figureCounterSpec), '.png'], '-dpng', '-r0'); %<! Saves as Screen Resolution
% end

%% Auxilizary Functions

%% Restore Defaults

% set(0, 'DefaultFigureWindowStyle', 'normal');
% set(0, 'DefaultAxesLooseInset', defaultLoosInset);


function [XX,H] = projectedGrid ( P1, P2, P3, P4 , nx, ny);

% new formalism using homographies

a00 = [P1;1];
a10 = [P2;1];
a11 = [P3;1];
a01 = [P4;1];

% Compute the planart collineation:

[H] = compute_collineation (a00, a10, a11, a01);

% Build the grid using the planar collineation:

x_l = ((0:(nx-1))'*ones(1,ny))/(nx-1);
y_l = (ones(nx,1)*(0:(ny-1)))/(ny-1);

pts = [x_l(:) y_l(:) ones(nx*ny,1)]';

XX = H*pts;

XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:));


function cond = diagonal_condition ( n, x )

%*****************************************************************************80
%
%% DIAGONAL_CONDITION returns the L1 condition of the DIAGONAL matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 January 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Input, real X(N), the diagonal entries of A.
%
%    Output, real COND, the L1 condition.
%
  cond = max ( abs ( x(1:n) ) ) / min ( abs ( x(1:n) ) );

  return
end


function [D]=d2a2(A,B)
%D2A2 Pairwise squared L2 distance along 2nd axis.
% D = D2A2(A,B) Computes squared L2 (Euclidean) distance
% between all pairs of d-dimensional points in A and B.
%
% Inputs:
% A - m-by-d matrix of m d-dimensional points;
% B - n-by-d matrix of n d-dimensional points.
%
% Outputs:
% D - m-by-n matrix of pairwise distances.
%
% See also D2A1.
if nargin < 2
D = full(A*A');
d = diag(D);
D = bsxfun(@minus, d, 2*D);
D = bsxfun(@plus, d', D);
D = max(D, 0);
else
D = full(A*B');
D = bsxfun(@minus, sum(B.^2,2)', 2*D);
D = bsxfun(@plus, sum(A.^2,2), D);
D = max(D, 0);
end


function FF = computeAllStatistics(fileName, win, step)

% This function computes the average and std values for the following audio
% features:
% - energy entropy
% - short time energy
% - spectral rolloff
% - spectral centroid
% - spectral flux
%
% ARGUMENTS:
% fileName: the name of the .wav file in which the signal is stored
% win: the processing window (in seconds)
% step: the processing step (in seconds)
%
% RETURN VALUE:
% F: a 12x1 array containing the 12 feature statistics
%

[x, fs] = wavread(fileName);

EE = Energy_Entropy_Block(x, win*fs, step*fs, 10);
E = ShortTimeEnergy(x, win*fs, step*fs);
Z = zcr(x, win*fs, step*fs, fs);
R = SpectralRollOff(x, win*fs, step*fs, 0.80, fs);
C = SpectralCentroid(x, win*fs, step*fs, fs);
F = SpectralFlux(x, win*fs, step*fs, fs);

FF(1) = statistic(EE, 1, length(EE), 'std');
FF(2) = statistic(Z, 1, length(Z), 'stdbymean');
FF(3) = statistic(R, 1, length(R), 'std');
FF(4) = statistic(C, 1, length(C), 'std');
FF(5) = statistic(F, 1, length(F), 'std');
FF(6) = statistic(E, 1, length(E), 'stdbymean');


function dt = DistanceTransform(b)

%DistanceTransform - Compute distance transform of a binary matrix (distance to nearest 1 value).
%
%  This function assigns to every point (x,y) in a binary matrix B the distance
%  to the nearest point in B with value 1. It uses the Euclidean metric for
%  computing distances. The code is based on the algorithm by Meijster et al.
%  (2000).
%
%  USAGE
%
%    dt = DistanceTransform(b)
%
%    b              binary matrix
%

% Copyright (C) 2014 by Michaël Zugaro
%
% 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 3 of the License, or
% (at your option) any later version.

% The code is not self explanatory, but is a direct transcription of the algorithms provided
% in Meijster et al. (2000)

[m,n] = size(b);
g = nan(m,n);

for x = 1:n,
	% Scan 1
	if b(1,x),
		g(1,x) = 0;
	else
		g(1,x) = m + n;
	end
	for y = 2:m,
		if b(y,x),
			g(y,x) = 0;
		else
			g(y,x) = 1 + g(y-1,x);
		end
	end
	% Scan 2
	for y = m-1:-1:1,
		if g(y+1,x) < g(y,x),
			g(y,x) = 1 + g(y+1,x);
		end
	end
end

for y = 1:n,
	q = 1;
	s(1) = 1;
	t(1) = 1;
	for u = 2:n,
		% Scan 3
		while true,
			x = t(q);
			i = s(q);
			f1 = (x-i)^2 + g(y,i)^2;
			i = u;
			f2 = (x-i)^2 + g(y,i)^2;
			if f1 <= f2, break; end
			q = q - 1;
			if q < 1, break; end
		end
		if q < 1,
			q = 1;
			s(1) = u;
		else
			i = s(q);
			a = (u^2-i^2+g(y,u)^2-g(y,i)^2);
			b = 2*(u-i);
			w = 1 + floor(a/b);
			if w <= n,
				q = q + 1;
				s(q) = u;
				t(q) = w;
			end
		end
	end
	for u = n:-1:1,
		% Scan 4
		x = u;
		i = s(q);
		dt(y,u) = sqrt((x-i)^2 + g(y,i)^2);
		if u == t(q),
			q = q - 1;
		end
	end
end


% This script demonstrates how to use the frequency response function.

% Initialization
clear all; close all; clc;
% We prepare the Blackman filter.
% Number of signal samples
N = 10;
% FFT length
L = 1024;
% Blackman window coefficients
w = 0.42 - 0.5*cos(2*pi*(0:N-1)/N) + 0.08 * cos (4*pi*(0:N-1)/N);
% Alternatively w = blackman(N);
% Gain normalization
w = w / sum(w);
% Spectrum of Blackman window
Wf = fft(w, L);
f = (0:L-1)/L;
% Plot the filter
options.title = 'Blackman window';
options.ylabel = 'w(n)';
options.xstep = 1;
spx.graphics.plot.discrete_signal(w, options);
% Plot the frequency response of the Blackman window
options.decibels = true;
spx.graphics.plot.frequency_response(Wf, options);


function point_num = cfn_e_size ( dim_num, level_max )

%*****************************************************************************80
%
%% CFN_E_SIZE: Closed Fully Nested, Exponential Growth.
%
%  Discussion:
%
%    This calculation assumes that an exponential growth rule is being used,
%    that is, that the 1D rules have orders 1, 3, 7, 15, 31, and so on.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 January 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Fabio Nobile, Raul Tempone, Clayton Webster,
%    A Sparse Grid Stochastic Collocation Method for Partial Differential
%    Equations with Random Input Data,
%    SIAM Journal on Numerical Analysis,
%    Volume 46, Number 5, 2008, pages 2309-2345.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer LEVEL_MAX, the maximum value of LEVEL.
%
%    Output, integer POINT_NUM, the total number of unique
%    points in the grids.
%

%
%  Special case.
%
  if ( level_max < 0 )
    point_num = 0;
    return
  end

  if ( level_max == 0 )
    point_num = 1;
    return
  end
%
%  Construct the vector that counts the new points in the 1D rule.
%
  new_1d = zeros ( level_max+1, 1 );

  new_1d(0+1) = 1;
  new_1d(1+1) = 2;

  j = 1;
  for l = 2 : level_max
    j = j * 2;
    new_1d(l+1) = j;
  end
%
%  Count the number of points by counting the number of new points
%  associated with each level vector.
%
  level_1d = zeros ( dim_num, 1 );

  point_num = 0;

  for level = 0 : level_max

    more = 0;
    h = 0;
    t = 0;

    while ( 1 )

      [ level_1d, more, h, t ] = comp_next ( level, dim_num, level_1d, more, h, t );

      point_num = point_num + prod ( new_1d(level_1d(1:dim_num)+1) );

      if ( ~more )
        break
      end

    end

  end

  return
end


function pcomb = stat_stouffer_pcomb(p)
% Stouffer et al's (1949) unweighted method for combination of
% independent p-values via z's
% From: http://imaging.mrc-cbu.cam.ac.uk/statswiki/FAQ/CombiningPvalues

if isempty(p)
    error('pfast was passed an empty array of p-values')
    pcomb=1;
else
    pcomb = (1-erf(sum(sqrt(2) * erfinv(1-2*p))/sqrt(2*length(p))))/2;
end


function [c, mass] = masscenter(F)
%------------------------------------------------------------------------------
%
% This function computes the center of mass of gridfunction F (seen as a
% density distribution) .
%
% Beware if F assumes not mere positive values, does it make sense?
%
% See also: m00, m10, m01, mu10, mu01
%
% Design and implementation by:
% Dr. Paul M. de Zeeuw <Paul.de.Zeeuw@cwi.nl>  http://homepages.cwi.nl/~pauldz/
% Last Revision: December 11, 2000.
%  2000 Stichting CWI, Amsterdam
%------------------------------------------------------------------------------
denomina = m00(F);
if denomina == 0
  error(' masscenter - demoninator vanishes ')
else
  cx = m10(F)/denomina;
  cy = m01(F)/denomina;
end
% whether cx, cy < 0 etc. could be checked here (see above warning).
if nargout == 1
  c = [cx cy];
elseif nargout == 2
  c = [cx cy];
  mass = denomina;
else
  error(' masscenter - wrong number of output arguments ')
end
%------------------------------------------------------------------------------


%% Testing OOQP
clc
clear

%% QP1 -2.83333333301227;
H = speye(3);
f = -[2 3 1]';
A = sparse([1 1 1;3 -2 -3; 1 -3 2]);
b = [1;1;1];

opts = [];
opts.display = 2;

[x,fval,e,i,l] = ooqp(H,f,A,-Inf(size(b)),b,[],[],[],[],opts)

%% QP2 -8.22222220552525
clc
H = (sparse([1 -1; -1 2]));
f = -[2 6]';
A = sparse([1 1; -1 2; 2 1]);
b = [2; 2; 3];
lb = [0;0];

opts = [];
opts.display = 2;

[~,fval,e,i] = ooqp(tril(H),f,A,-Inf(size(b)),b,[],[],lb,[],opts)

%% QP3 -6.41379310344827
H = tril(sparse([1 -1; -1 2]));
f = -[2 6]';
A = sparse([1 1; -1 2; 2 1]);
b = [2; 2; 3];
Aeq = sparse([1 1.5]);
beq = 2;
lb = [0;0];
ub = [10;10];

opts = [];
opts.display = 2;
opts.linear_solver = 'pardiso';
[x,f,e,i] = ooqp(H,f,A,-Inf(size(b)),b,Aeq,beq,lb,ub,opts)

%% LP1 -3.75
clc
H = [];
f = -[-1, 2]';
A = sparse([2, 1;-4, 4]);
b = [5, 5]';

opts = [];
opts.display = 2;
[x,f,e,i] = ooqp(H,f,A,-Inf(size(b)),b,[],[],[],[],opts)

%% LP2 3
clc
H = [];
f = [1, 2, 3, 7, 8, 8];
A = -sparse([5, -3, 2, -3, -1, 2; -1, 0, 2, 1, 3, -3;1, 2, -1, 0, 5, -1]);
b = -[-5, -1, 3]';
lb = zeros(6,1);
ub = 10*ones(6,1);

opts = [];
opts.display = 2;
[x,f,e,i,l] = ooqp(H,f,-A,-Inf(size(b)),-b,[],[],lb,ub,opts)

%% LP3 4
clc
n = 40;
t = (0:n-1)';
y = 3.5 -.2*t;
b = y + 0.5*ones(size(y));
m = [ones(n,1),t(:)];
A = sparse([m,-m,eye(n)]);
H = [];spalloc(44,44,0);
f = [sum(m),sum(-m),2*ones(1,n)];
lb = zeros(n+4,1);
ub = [10, 10, 10, 10, 5*ones(1,n)];

opts = [];
opts.display = 2;
[~,f,e,i,l] = ooqp(H,f,-A,-Inf(size(b)),-b,[],[],lb,ub,opts)

%% LARGE LP
clc
prob = coinRead('maros-r7.mps');
opts = optiset('solver','ooqp','display','iter');
Opt = opti(prob,opts);
%Solve
[~,f,e,i] = solve(Opt)

%%
qp1 = qp_prob(1);
opts = optiset('solver','ooqp','display','iter');
Opt = opti(qp1,opts);
%Solve
[~,f,e,i] = solve(Opt)


function [nu, U, llh, Ezz, Ezy] = kalmanSmoother(model, X)
% Kalman smoother (forward-backward algorithm for linear dynamic system)
% NOTE: This is the exact implementation of the Kalman smoother algorithm in PRML.
% However, this algorithm is not practical. It is numerical unstable.
% Input:
%   X: d x n data matrix
%   model: model structure
% Output:
%   nu: q x n matrix of latent mean mu_t=E[z_t] w.r.t p(z_t|x_{1:T})
%   U: q x q x n latent covariance U_t=cov[z_t] w.r.t p(z_t|x_{1:T})
%   Ezz: q x q matrix E[z_tz_t^T]
%   Ezy: q x q matrix E[z_tz_{t-1}^T]
%   llh: loglikelihood
% Written by Mo Chen (sth4nth@gmail.com).
A = model.A; % transition matrix
G = model.G; % transition covariance
C = model.C; % emission matrix
S = model.S;  % emision covariance
mu0 = model.mu0; % prior mean
P0 = model.P0;  % prior covairance

n = size(X,2);
q = size(mu0,1);
mu = zeros(q,n);
V = zeros(q,q,n);
P = zeros(q,q,n); % C_{t+1|t}
Amu = zeros(q,n); % u_{t+1|t}
llh = zeros(1,n);

% forward
PC = P0*C';
R = C*PC+S;
K = PC/R;
mu(:,1) = mu0+K*(X(:,1)-C*mu0);
V(:,:,1) = (eye(q)-K*C)*P0;
P(:,:,1) = P0;  % useless, just make a point
Amu(:,1) = mu0; % useless, just make a point
llh(1) = logGauss(X(:,1),C*mu0,R);
for i = 2:n
    [mu(:,i), V(:,:,i), Amu(:,i), P(:,:,i), llh(i)] = ...
        forwardUpdate(X(:,i), mu(:,i-1), V(:,:,i-1), A, G, C, S);
end
llh = sum(llh);
% backward
nu = zeros(q,n);
U = zeros(q,q,n);
Ezz = zeros(q,q,n);
Ezy = zeros(q,q,n-1);

nu(:,n) = mu(:,n);
U(:,:,n) = V(:,:,n);
Ezz(:,:,n) = U(:,:,n)+nu(:,n)*nu(:,n)';
for i = n-1:-1:1
    [nu(:,i), U(:,:,i), Ezz(:,:,i), Ezy(:,:,i)] = ...
        backwardUpdate(nu(:,i+1), U(:,:,i+1), mu(:,i), V(:,:,i), Amu(:,i+1), P(:,:,i+1), A);
end

function [mu1, V1, Amu, P, llh] = forwardUpdate(x, mu0, V0, A, G, C, S)
k = numel(mu0);
P = A*V0*A'+G;                                               % 13.88
PC = P*C';
R = C*PC+S;
K = PC/R;                                                    % 13.92
Amu = A*mu0;
CAmu = C*Amu;
mu1 = Amu+K*(x-CAmu);                                        % 13.89
V1 = (eye(k)-K*C)*P;                                         % 13.90
llh = logGauss(x,CAmu,R);                                    % 13.91

function [nu0, U0, E00, E10] = backwardUpdate(nu1, U1, mu, V, Amu, P, A)
J = V*A'/P;                                                  % 13.102
nu0 = mu+J*(nu1-Amu);                                        % 13.100
U0 = V+J*(U1-P)*J';                                          % 13.101
E00 = U0+nu0*nu0';                                           % 13.107
E10 = U1*J'+nu1*nu0';                                        % 13.106


function K = compute_cubic_spline_kernel(x,y);
nx = size(x,1);
ny = size(y,1);
Kmax = max(repmat(abs(x),1,ny),repmat(abs(y)',nx,1) );
Kmin = min(repmat(abs(x),1,ny),repmat(abs(y)',nx,1) );
K = Kmin .* Kmin .* ( 3 * Kmax - Kmin );
K = K .* (  x*y' > 0 );


% Degree-preserving random rewiring.
% Every rewiring decreases the assortativity (pearson coefficient).
%
% Note 1: There are rare cases of neutral rewiring (pearson coefficient stays the same within numerical error).
% Note 2: Assume unweighted undirected graph.
%
% INPUTS: edge list, el and number of rewirings, k (integer)
% OUTPUTS: rewired edge list
%
% Other routines used: degrees.m, edgeL2adj.m
% GB: last updated, Sep 27 2012

function el = rewireDisassort(el,k)

[deg,~,~]=degrees(edgeL2adj(el));

rew=0;

while rew<k

    % pick two random edges
    ind = randi(length(el),1,2);
    edge1=el(ind(1),:); edge2=el(ind(2),:);

    if length(intersect(edge1(1:2),edge2(1:2)))>0; continue; end % the two edges cannot overlap

    nodes=[edge1(1) edge1(2) edge2(1) edge2(2)];
    [~,Y]=sort(deg(nodes));

    % connect nodes(Y(1))-nodes(Y(4)) and nodes(Y(2))-nodes(Y(3))
    if ismember([nodes(Y(1)),nodes(Y(4)),1],el,'rows') || ismember([nodes(Y(2)),nodes(Y(3)),1],el,'rows'); continue; end

    el(ind(1),:)=[nodes(Y(1)),nodes(Y(4)),1];
    el(ind(2),:)=[nodes(Y(2)),nodes(Y(3)),1];

    [~,inds1] = ismember([edge1(2),edge1(1),1],el,'rows');
    el(inds1,:)=[nodes(Y(4)),nodes(Y(1)),1];

    [~,inds2] = ismember([edge2(2),edge2(1),1],el,'rows');
    el(inds2,:)=[nodes(Y(3)),nodes(Y(2)),1];

    rew=rew+1;

end


function [s_true,e_spat,e_interf,e_artif]=bss_decomp_mtifilt(se,S,j,L)

% BSS_DECOMP_MTIFILT Decomposition of an estimated source image into four
% components representing respectively the true source image, spatial (or
% filtering) distortion, interference and artifacts, derived from the true
% source images using multichannel time-invariant filters.
%
% [s_true,e_spat,e_interf,e_artif]=bss_decomp_mtifilt(se,S,j,L)
%
% Inputs:
% se: I x T matrix containing the estimated source image (one row per channel)
% S: I x T x J matrix containing the true source images
% j: source index corresponding to the estimated source image in S
% L: length of the multichannel time-invariant filters in samples
%
% Outputs:
% s_true: I x T matrix containing the true source image, i.e. S(:,:,j) (one row per channel)
% e_spat: I x T matrix containing the spatial (or filtering) distortion component
% e_interf: I x T matrix containing the interference component
% e_artif: I x T matrix containing the artifacts component

%%% Errors %%%
if nargin<4, error('Not enough input arguments.'); end
[Ie,Te]=size(se);
[I,T,J]=size(S);
if I~=Ie, error('The number of channels of the true source images and the estimated source image must be equal.'); end
if T~=Te, error('The duration of the true source images and the estimated source image must be equal.'); end

%%% Decomposition %%%
% True source image
s_true=[S(:,:,j),zeros(I,L-1)];
% Spatial (or filtering) distortion
e_spat=project(se,S(:,:,j),L)-s_true;
% Interference
e_interf=project(se,S,L)-s_true-e_spat;
% Artifacts
e_artif=[se,zeros(I,L-1)]-s_true-e_spat-e_interf;

return;

function sproj=project(se,S,L)

% Least-squares projection of each channel of se on the subspace spanned by
% delayed versions of the channels of S, with delays between 0 and L-1

[I,T,J]=size(S);
S=reshape(permute(S,[1 3 2]),I*J,T);

%%% Computing coefficients of least squares problem via FFT %%%
% Zero padding and FFT of input data
S=[S,zeros(I*J,L-1)];
se=[se,zeros(I,L-1)];
N=2^nextpow2(T+L-1);
Sf=fft(S,N,2);
sef=fft(se,N,2);
% Inner products between delayed versions of S
G=zeros(I*J*L);
for k1=0:I*J-1
    for k2=0:k1
        SSf=Sf(k1+1,:).*conj(Sf(k2+1,:));
        SSf=real(ifft(SSf));
        SS=toeplitz(SSf([1 N:-1:N-L+2]),SSf(1:L));
        G(k1*L+1:k1*L+L,k2*L+1:k2*L+L)=SS;
        G(k2*L+1:k2*L+L,k1*L+1:k1*L+L)=SS.';
    end
end
% Inner products between se and delayed versions of S
D=zeros(I*J*L,I);
for k=0:I*J-1
    for i=1:I
        Ssef=Sf(k+1,:).*conj(sef(i,:));
        Ssef=real(ifft(Ssef,[],2));
        D(k*L+1:k*L+L,i)=Ssef(:,[1 N:-1:N-L+2]).';
    end
end

%%% Computing projection %%%
% Distortion filters
C=G\D;
C=reshape(C,L,I*J,I);
% Filtering
sproj=zeros(I,T+L-1);
for k=1:I*J
    for i=1:I
        sproj(i,:)=sproj(i,:)+fftfilt(C(:,k,i).',S(k,:));
    end
end

return;


function [steep] = steep(B,V,C,s,o,d)
%Steepest ascent/descent is a simple and efficient optimization method based on
% statistical design of experiments.
%  In order to optimize a response with respect to a set of quantitative variables,
%  often by using sequential experimentation, we use polynomial models to approximate
%  the response surface. The process often begins by using a 2^p factorial design with
%  additional center points, then fitting a first-order model. If curvature is detected
%  (lack of fit to the first-order model), then we conclude that we are near the optimum
%  and add points to obtain a second-order design. If curvature is not detected, we are
%  far from the optimum and use the method of steepest ascent/descent to get points
%  headed (hopefully) toward to optimum. As we recognize that we are near the optimum,
%  we use a second-order design.
%  If there is no lack-of-fit then the linear model seems to approximate the response
%  surface in this region, which means we are far from an optimum. In this case we want
%  to obtain additional responses (design points) that go closer to the optimum. To do
%  this we use the method of steepest ascent/descent, which just means that future design
%  points should increase/decrease the levels of IV's (factors) in proportion to b's until
%  we are near the optimum response (maximum or minimum).
%  We know that to maximize/minimize a response, the movement of the design center must
%  be in the direction of the directional derivatives of the response function, that is,
%  in the direction of
%
%            df/dx = df/dx_1, . . .,df/dx_p .
%
%  We then multiply by a constant A so that
%
%            Dx = A*df/dx,
%  where
%
%            A = R/sqrt(Sum(df/dx_i)^2) .
%
%  Thus,
%
%            Sum(Dx_i^2) = R^2 .
%
%  For a first order model,
%
%            df/dx_i = b_i .
%
%  So,
%
%            Dx_i = A*b_i    and     A = R/sqrt(Sum(b_i^2)) .
%
%  From this we see that the movement of x_i up the path of steepest ascent/descent
%  is proportional to b_i. Since this is the case it is easier not to pick particular
%  values of R but rather fix a value of b_i and make the other changes proportional
%  to it.
%
%                               Gradient vector
%                  |                ^
%                  |    \    \    \/   O
%                  |\    \    \   /\ New\
%                  | \    \    \ /  O trials
%              x_2 |  \    \    /    \    \
%                  |   \ O--\----\O   \    \
%                  |    \| Start  |    \    \
%                  |     | design |\    \    \
%                  |     O\----\--O \    \    \
%                  |_ _ _ _\_ _ \_ _ \_ _ \_ _ \_ _
%                                 x_1
%
%      First-order response surface and path of steepest ascent.
%
%  Thus, the goal is to optimize the response variable Y. It is assumed that the
%  factors are continuous and controllable by the experimenter with negligible error.
%  If b_1, b_2,...,b_p are the parameters and observed response is Y then the parameter
%  of the polynomial is estimated by method of least squares.
%  The method of steepest ascent/descent is followed to reach the optimun point where
%  best surface is obtained. That is direction of the maximum increase/minimum decrease
%  of the response in the case of surface finish cosiderations. Direction of steep Y is
%  increasing/decreasing. Experiments are conducted along the path of steepest
%  ascent/descent until no further decrease in response is observed. Then a new
%  first-order model may be fit, a new path of steepest ascent/descent determined the
%  procedure continues. Eventually the vicinity of optimum is arrived.
%
%  Syntax: steep(B,V,C,s,o,d)
%
%  Inputs:
%       B - vector of regression coefficients (parameters) of the fitted linear equation
%           (first order): [intercept (1), linear (p)]. It must to be enter in that
%           strictly order.
%       V - vector of the factor values at starting point (current factor setting).
%       C - vector of units increment chosen between the low and medium levels and
%           between the medium and high levels for each parameter.
%       s - number of interested steps.
%       o - change relative to one unit change regarding to the maximum absolute
%           parameter [o = 1 (default)] or parameter choice by experimenter (o = 2).
%       d - steepest ascent [d = 1 (default)] or descent (d = 2) procedure.
%
%  Outputs:
%       A complete summary of the estimation of the selected direction of the
%       selected steepest method.
%
%  To see the procedure consider the following example taken from Montgomery DOX 5E
%  (Example 11-1, pg. 431). Based on the fitted first-order model,
%                     y = 40.44 + 0.775*x1 + 0.325*x2
%  with actual factor-values on the origin of 35 and 155 for time-reaction (min) and
%  temperature (oF) and step size of 5 and 5, respectively. We are interested to obtain
%  the predicted response by the steepest ascent metod for 12 steps.
%
%  Input data must be:
%  B=[40.44 0.775 0.325];
%  V=[35 155];
%  C=[5 2];
%  s = 12;
%  o = 1;
%  d = 1;
%
%  Calling on Matlab the function:
%             steep(B,V,C,s,o,d)
%
%  Answer is:
%
%  Estimation of the selected direction of steepest ascent.
%  The interested steps were 12
%  Leading from the center of the design region the operating point for the IV, 2
%  --------------------------------------------------------------------------------------------------------------
%   Run          Operating point        Predicted response
%  --------------------------------------------------------------------------------------------------------------
%     0        35.000      155.000            40.440
%     1        40.000      157.097            41.351
%     2        45.000      159.194            42.263
%     3        50.000      161.290            43.174
%     4        55.000      163.387            44.085
%     5        60.000      165.484            44.996
%     6        65.000      167.581            45.908
%     7        70.000      169.677            46.819
%     8        75.000      171.774            47.730
%     9        80.000      173.871            48.642
%    10        85.000      175.968            49.553
%    11        90.000      178.065            50.464
%    12        95.000      180.161            51.375
%  --------------------------------------------------------------------------------------------------------------
%
%  Created by A. Trujillo-Ortiz, R. Hernandez-Walls, A. Castro-Perez and
%             F.J. Marquez-Rocha
%             Facultad de Ciencias Marinas
%             Universidad Autonoma de Baja California
%             Apdo. Postal 453
%             Ensenada, Baja California
%             Mexico.
%             atrujo@uabc.mx
%             And the special collaboration of the post-graduate students of the 2005:1
%             Multivariate Statistics Course: Cesar Orlando Chavira-Ortega, Alfredo Frias-Velasco,
%             and Herlinda Gomez-Villa.
%  Copyright (C) May 20, 2005.
%
%  To cite this file, this would be an appropriate format:
%  Trujillo-Ortiz, A., R. Hernandez-Walls, A. Castro-Perez, F.J Marquez-Rocha,
%    C.O. Chavira-Ortega, A. Frias-Velasco and H. Gomez-Villa. (2005). steep:
%    Steepest ascent/descent as a simple and efficient optimization method based
%    on statistical design of experiments. A MATLAB file. [WWW document]. URL
%    http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=7737
%
%  References:
%
%  Box, G. E. P. and Draper, N. R. (1987), Empirical Model-Building and Response Surfaces.
%          John Wiley & Sons: New York.
%  Box, G. E. P. and Wilson, K. B. (1951), On the Experimental Attainment of Optimum
%          Conditions. J. Royal Stat. Soc. Ser. B., 13:1-45.
%  Montgomery, D. C. (2001), Design and Analysis of Experiments, 5th Ed., John Wiley & Sons: New York.
%  Myers, R. H. and Montgomery, D. C. (2002),  Response Surface Methodology: Process and
%          Product Optimization Using Designed Experiments. 2nd. Ed., John Wiley & Sons: New York.
%

if nargin < 6,
   d = 1 %(deafault);
end;

if nargin < 5,
   o = 1 %(deafault);
end;

b = B(2:end);
b = b(:);  %vector of  from coded regression model
V = V(:);  %base level (center point)
C = C(:);  %unit change
s = s;     %
v = length(B)-1; %number of independent variables

if o == 1,
   f = max(abs(b));
else (o == 2),
   l = input('Give me the interested factor: ');
   f = b(l);
end;

S = [];
for i = 0:s,
    if d == 1;      %steepest ascent
        x = [V + i*diag(b./f*C')];
    else (d == 2);  %steepest descent
        x = [V - i*diag(b./f*C')];
    end;
    S = [S x];
end;

S = S';
V = V';
[m n] = size(S);
O  = (S - repmat(V,m,1))./repmat(C',m,1);

Y = B(1)+O*b;

T = [];
for i = 0:s,
   T = [T;i];
end;

if d == 1;
    d = 'ascent.';
else (d == 2);
    d = 'descent.';
end;

[nul,fs] = size(S);
form = ['%12.3f '];
form2 = [' Run '];
form3 = [' Predicted response '];
for k = 2:fs,
    form = [form '%12.3f '];
    form2 = [form2 '       '];
    form3 = ['      ' form3];
end;
RR = [T S Y];

disp(' ')
fprintf('Estimation of the selected direction of steepest %s\n',d);
fprintf('The interested steps were %i\n',s);
fprintf('Leading from the center of the design region the operating point for the IV, %i\n',v);
fprintf('--------------------------------------------------------------------------------------------------------------\n');
disp([form2 '  Operating point '  form3])
fprintf('--------------------------------------------------------------------------------------------------------------\n');
ffa=['%4i  ' form  ' %16.3f\n'];
fprintf(ffa,RR');
fprintf('--------------------------------------------------------------------------------------------------------------\n');
disp(' ')

return,


% This is a demo for segmentation using local gaussian distribution (LGD)
% fitting energy
%
% Reference: <Li Wang, Lei He, Arabinda Mishra, Chunming Li.
% Active Contours Driven by Local Gaussian Distribution Fitting Energy.
% Signal Processing, 89(12), 2009,p. 2435-2447>
%
% Please DO NOT distribute this code to anybody.
% Copyright (c) by Li Wang
%
% Author:       Li Wang
% E-mail:       li_wang@med.unc.edu
% URL:          http://www.unc.edu/~liwa/
%
% 2010-01-02 PM

clc;clear all;close all;

Img=imread('2.bmp');
Img = double(Img(:,:,1));

NumIter = 1000; %iterations
timestep=0.1; %time step
mu=0.1/timestep;% level set regularization term, please refer to "Chunming Li and et al. Level Set Evolution Without Re-initialization: A New Variational Formulation, CVPR 2005"
sigma = 5;%size of kernel
epsilon = 1;
c0 = 2; % the constant value
lambda1=1.05;%outer weight, please refer to "Chunming Li and et al,  Minimization of Region-Scalable Fitting Energy for Image Segmentation, IEEE Trans. Image Processing, vol. 17 (10), pp. 1940-1949, 2008"
lambda2=1.0;%inner weight
%if lambda1>lambda2; tend to inflate
%if lambda1<lambda2; tend to deflate
nu = 0.001*255*255;%length term
alf = 20;%data term weight

figure,imagesc(uint8(Img),[0 255]),colormap(gray),axis off;axis equal
[Height Wide] = size(Img);
[xx yy] = meshgrid(1:Wide,1:Height);
phi = (sqrt(((xx - 64).^2 + (yy - 65).^2 )) - 17);
phi = sign(phi).*c0;

Ksigma=fspecial('gaussian',round(2*sigma)*2 + 1,sigma); %  kernel
ONE=ones(size(Img));
KONE = imfilter(ONE,Ksigma,'replicate');
KI = imfilter(Img,Ksigma,'replicate');
KI2 = imfilter(Img.^2,Ksigma,'replicate');

figure,imagesc(uint8(Img),[0 255]),colormap(gray),axis off;axis equal,
hold on,[c,h] = contour(phi,[0 0],'r','linewidth',1); hold off
pause(0.5)

tic
for iter = 1:NumIter
    phi =evolution_LGD(Img,phi,epsilon,Ksigma,KONE,KI,KI2,mu,nu,lambda1,lambda2,timestep,alf);

    if(mod(iter,100) == 0)
        figure(2),
        imagesc(uint8(Img),[0 255]),colormap(gray),axis off;axis equal,title(num2str(iter))
        hold on,[c,h] = contour(phi,[0 0],'r','linewidth',1); hold off
        pause(0.02);
    end

end
toc


function at = auct(crit,y,z,tt)
%AUCS Compute area under curve for survival model at given time
%
%  Description
%    A = AUCT(CRIT,Z) Compute are under curve for survival model at
%    given time using criteria vector CRIT (where larger value
%    means larger risk of incidence), observed time vector Y,
%    censoring indicator matrix Z at times TT (0=event, 1=censored)
%    and a time vector TT.
%
%  Reference
%    L. E. Chambless, C. P. Cummiskey, and G. Cui (2011). Several
%    methods to assess improvement in risk prediction models:
%    Extension to survival analysis. Statistics in Medicine
%    30(1):22-38.

% Copyright (C) 2012 Ernesto Ulloa, Aki Vehtari

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

ip=inputParser;
ip.addRequired('crit',@(x) ~isempty(x) && isreal(x) && all(isfinite(x(:))))
ip.addRequired('y', @(x) isreal(x) && all(isfinite(x(:))))
ip.addRequired('z', @(x) isreal(x) && all(isfinite(x(:))))
ip.addRequired('tt', @(x) isreal(x) && all(isfinite(x(:))))
ip.parse(crit,y,z,tt)

for i=1:size(tt,2)
  comp=bsxfun(@times,bsxfun(@and,y(:,i)<=tt(i),1-z(:,i)),bsxfun(@or,bsxfun(@and,y(:,i)<=tt(i),z(:,i)),y(:,i)>=tt(i))');
  conc=bsxfun(@times,bsxfun(@gt,crit(:,i),crit(:,i)'),comp);
  at(i,1)=sum(conc(:))./sum(comp(:));
end

end


close all;
clear all;
clc;

load('bin/omp_vs_gomp_comparison.mat');

mf = spx.graphics.Figures();

mf.new_figure('Iterations');

lengends = cell(5, 1);
lengends{1} = 'OMP';
for nl=1:num_ls
    lengends{nl+1} = sprintf('GOMP-%d', Ls(nl));
end
hold all;

plot(Ks, omp_average_iterations_with_k(Ks));
for nl=1:num_ls
    plot(Ks, gomp_average_iterations_with_k(Ks, nl));
end
xlabel('Sparsity level');
ylabel('Average iterations');
legend(lengends);
grid on;

mf.new_figure('Success rate');
hold all;
plot(Ks, omp_success_rates_with_k(Ks));
for nl=1:num_ls
    plot(Ks, gomp_success_rates_with_k(Ks, nl));
end
xlabel('Sparsity level');
ylabel('Success rates');
legend(lengends);
grid on;


function len = edgeLength3d(edge, varargin)
%EDGELENGTH3D Return the length of a 3D edge.
%
%   L = edgeLength3D(EDGE);
%   Returns the length of a 3D edge, with following representation:
%   [x1 y1 z1 x2 y2 z2].
%
%   Example
%     p1 = [1 1 1];
%     p2 = [3 4 5];
%     edge = createEdge3d(p1, p2);
%     edgeLength3d(edge)
%     ans =
%         5.3852
%
%   See also
%     edges3d, createEdge3d, drawEdge3d

% ------
% Author: David Legland
% e-mail: david.legland@inra.fr
% Created: 2018-08-29,    using Matlab 9.4.0.813654 (R2018a)
% Copyright 2018 INRA - Cepia Software Platform.

if nargin == 1
    dp = edge(:, 4:6) - edge(:, 1:3);
else
    dp = varargin{1} - edge;
end

len = hypot(hypot(dp(:,1), dp(:,2)), dp(:,3));


function checkNNGradients(lambda)
%CHECKNNGRADIENTS Creates a small neural network to check the
%backpropagation gradients
%   CHECKNNGRADIENTS(lambda) Creates a small neural network to check the
%   backpropagation gradients, it will output the analytical gradients
%   produced by your backprop code and the numerical gradients (computed
%   using computeNumericalGradient). These two gradient computations should
%   result in very similar values.
%

if ~exist('lambda', 'var') || isempty(lambda)
    lambda = 0;
end

input_layer_size = 3;
hidden_layer_size = 5;
num_labels = 3;
m = 5;

% We generate some 'random' test data
Theta1 = debugInitializeWeights(hidden_layer_size, input_layer_size);
Theta2 = debugInitializeWeights(num_labels, hidden_layer_size);
% Reusing debugInitializeWeights to generate X
X  = debugInitializeWeights(m, input_layer_size - 1);
y  = 1 + mod(1:m, num_labels)';

% Unroll parameters
nn_params = [Theta1(:) ; Theta2(:)];

% Short hand for cost function
costFunc = @(p) nnCostFunction(X,y,p,input_layer_size, hidden_layer_size, ...
                               num_labels,lambda);

[cost, grad] = costFunc(nn_params);
numgrad = computeNumericalGradient(costFunc, nn_params);

% Visually examine the two gradient computations.  The two columns
% you get should be very similar.
disp([numgrad grad]);
fprintf(['The above two columns you get should be very similar.\n' ...
         '(Left-Your Numerical Gradient, Right-Analytical Gradient)\n\n']);

% Evaluate the norm of the difference between two solutions.
% If you have a correct implementation, and assuming you used EPSILON = 0.0001
% in computeNumericalGradient.m, then diff below should be less than 1e-9
diff = norm(numgrad-grad)/norm(numgrad+grad);

fprintf(['If your backpropagation implementation is correct, then \n' ...
         'the relative difference will be small (less than 1e-9). \n' ...
         '\nRelative Difference: %g\n'], diff);

end


function linplus_test48 ( )

%*****************************************************************************80
%
%% TEST48 tests R8PBU_ML.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  n = 10;
  mu = 3;
  seed = 123456789;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST48\n' );
  fprintf ( 1, '  R8PBU_ML computes A*x\n' );
  fprintf ( 1, '    where A has been factored by R8PBU_FA.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Matrix order N = %d\n', n );
  fprintf ( 1, '  Upper bandwidth MU = %d\n', mu );
%
%  Set the matrix.
%
  [ a, seed ] = r8pbu_random ( n, mu, seed );
%
%  Set the desired solution.
%
  x = r8vec_indicator ( n );
%
%  Compute the corresponding right hand side.
%
  b = r8pbu_mxv ( n, mu, a, x );
%
%  Factor the matrix.
%
  [ a_lu, info ] = r8pbu_fa ( n, mu, a );

  if ( info ~= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Fatal error!\n' );
    fprintf ( 1, '  R8PBU_FA declares the matrix is singular!\n' );
    fprintf ( 1, '  The value of INFO is %d\n', info );
    return
  end
%
%  Now multiply factored matrix times solution to get right hand side again.
%
  b2 = r8pbu_ml ( n, mu, a_lu, x );

  r8vec2_print_some ( n, b, b2, 10, '  A*x and PLU*x' );

  return
end


function fem2d_scalar_display ( prefix )

%*****************************************************************************80
%
%% FEM2D_SCALAR_DISPLAY creates surface plots of 2D FEM scalar data.
%
%  Discussion:
%
%    This program assumes that you have computed the value of some scalar
%    quantity (such as pressure or temperature) at a set of nodes.
%
%    You may have determined an order 3 triangulation of these nodes,
%    but if you have not, the program will work that out internally.
%
%    This program can read that data, and display a color contour of the
%    solution data.
%
%  Usage:
%
%    fem2d_scalar_display ( 'prefix' )
%
%    where
%
%    * 'prefix'_nodes.txt contains the node coordinates;
%    * 'prefix'_elements.txt contains the element definitions
%      (this file is optional, and if missing, the elements will be generated
%      by the program);
%    * 'prefix'_values.txt contains the nodal values.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 November 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string PREFIX, the common file prefix.
%
  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FEM2D_SCALAR_DISPLAY:\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Surface plot of a scalar U(X,Y) on a triangulated region.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This program expects three input files:\n' );
  fprintf ( 1, '  * a node file,      the node coordinates,\n' );
  fprintf ( 1, '  * an element file,  triples of nodes that form elements,\n' );
  fprintf ( 1, '  * a value file,     solution values.\n' );
%
%  The command line argument is the common filename prefix.
%
  if ( nargin < 1 )

    fprintf ( 1, '\n' );

    prefix = input ( ...
      'Please enter the filename prefix:' );

  end
%
%  Create the filenames.
%
  node_filename = strcat ( prefix, '_nodes.txt' );
  element_filename = strcat ( prefix, '_elements.txt' );
  value_filename = strcat ( prefix, '_values.txt' );
%
%  Read the node data.
%
  [ dim_num, node_num ] = r8mat_header_read ( node_filename );

% fprintf ( 1, '\n' );
% fprintf ( 1, '  Read the header of "%s".', node_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension DIM_NUM = %d\n', dim_num );
  fprintf ( 1, '  Number of points NODE_NUM = %d\n', node_num );

  if ( dim_num ~= 2 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FEM2D_SCALAR_DISPLAY - Fatal error!\n' );
    fprintf ( 1, '  Dataset must have spatial dimension 2.\n' );
    error ( 'FEM2D_SCALAR_DISPLAY - Fatal error!' );
  end

  node_xy = r8mat_data_read ( node_filename, dim_num, node_num );

% fprintf ( 1, '\n' );
% fprintf ( 1, '  Read the data in "%s".\n', node_filename );

% r8mat_transpose_print_some ( dim_num, node_num, node_xy, 1, 1, dim_num, 5, ...
%   '  First 5 nodes:' );
%
%  Read or create the element data.
%
  if ( file_exist ( element_filename ) )

    [ element_order, element_num ] = i4mat_header_read ( ...
      element_filename );

    if ( element_order ~= 3 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'FEM2D_SCALAR_DISPLAY - Fatal error!\n' );
      fprintf ( 1, '  Data is not for a 3-node triangulation.\n' );
      error ( 'FEM2D_SCALAR_DISPLAY - Fatal error!' );
    end

%   fprintf ( 1, '\n' );
%   fprintf ( 1, '  Read the header of "%s".\n', ...
%     element_filename );
%   fprintf ( 1, '\n' );
    fprintf ( 1, '  Element order = %d\n', element_order );
    fprintf ( 1, '  Number of elements ELEMENT_NUM  = %d\n', ...
      element_num );

    element_node = i4mat_data_read ( element_filename, ...
      element_order, element_num );

%   fprintf ( 1, '\n' );
%   fprintf ( 1, '  Read the data in "%s".\n', element_filename );

  else

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Creating triangulation for data.\n' );
    element_node = delaunayn ( node_xy' );
    element_node = element_node';
    [ element_order, element_num ] = size ( element_node );
    i4mat_write ( element_filename, element_order, element_num, element_node );
    fprintf ( 1, '  Triangulation data written to "%s".\n', element_filename );
  end

% i4mat_transpose_print_some ( element_order, element_num, ...
%   element_node, 1, 1, element_order, 10, ...
%   '  First 10 elements:' );
%
%  Detect and correct 0-based indexing.
%
  element_node = mesh_base_one ( node_num, element_order, element_num, ...
    element_node );
%
%  Read the values.
%
  [ value_dim, value_num ] = r8mat_header_read ( value_filename );

% fprintf ( 1, '\n' );
% fprintf ( 1, '  Read the header of "%s".', value_filename );
% fprintf ( 1, '\n' );
% fprintf ( 1, '  Spatial dimension = %d\n', value_dim );
% fprintf ( 1, '  Number of values  = %d\n', value_num );

  if ( value_dim ~= 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FEM2D_SCALAR_DISPLAY - Fatal error!\n' );
    fprintf ( 1, '  VALUE data must be scalar.\n' );
    error ( 'FEM2D_SCALAR_DISPLAY - Fatal error!' );
  end

  value = r8mat_data_read ( value_filename, value_dim, value_num );
%
%  Call TRISURF to plot the data.
%
  trisurf ( element_node', node_xy(1,:)', node_xy(2,:)', value', ...
    'Edgecolor', 'None' )

  xlabel ( '<---X--->', 'Fontsize', 16 );
  ylabel ( '<---Y--->', 'Fontsize', 16 );
  zlabel ( '<---U(X,Y)--->', 'Fontsize', 16 );
  title ( prefix, 'Fontsize', 24 );
%
%  Save it as a PNG file.
%
  png_filename = strcat ( prefix, '.png' );
  print ( '-dpng', png_filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Saving a PNG version of plot as "%s"\n', png_filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'FEM2D_SCALAR_DISPLAY:\n' );
  fprintf ( 1, '  Normal end of execution.\n' );
  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function column_num = file_column_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_COLUMN_COUNT counts the columns in the first line of a file.
%
%  Discussion:
%
%    The file is assumed to be a simple text file.
%
%    Most lines of the file are presumed to consist of COLUMN_NUM words,
%    separated by spaces.  There may also be some blank lines, and some
%    comment lines, which have a "#" in column 1.
%
%    The routine tries to find the first non-comment non-blank line and
%    counts the number of words in that line.
%
%    If all lines are blanks or comments, it goes back and tries to analyze
%    a comment line.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 February 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the file.
%
%    Output, integer COLUMN_NUM, the number of columns in the file.
%
  FALSE = 0;
  TRUE = 1;
%
%  Open the file.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_COLUMN_COUNT - Error!' );
  end
%
%  Read one line, but skip blank lines and comment lines.
%  Use FGETL so we drop the newline character!
%
  got_one = FALSE;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( s_len_trim ( line ) == 0 )

    elseif ( line(1) == '#' )

    else
      got_one = TRUE;
      break;
    end

  end

  fclose ( input_unit );

  if ( got_one == FALSE )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_COLUMN_COUNT - Warning!\n' );
    fprintf ( 1, '  The file does not seem to contain any data.\n' );
    column_num = -1;
    return;
  end

  column_num = s_word_count ( line );

  return
end
function value = file_exist ( file_name )

%*****************************************************************************80
%
%% FILE_EXIST reports whether a file exists.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, character FILE_NAME, the name of the file.
%
%    Output, logical FILE_EXIST, is TRUE if the file exists.
%
  fid = fopen ( file_name );

  if ( fid == -1 )
    value = 0;
  else
    fclose ( fid );
    value = 1;
  end

  return
end
function row_num = file_row_count ( input_file_name )

%*****************************************************************************80
%
%% FILE_ROW_COUNT counts the number of row records in a file.
%
%  Discussion:
%
%    Each input line is a "RECORD".
%
%    The records are divided into three groups:
%
%    * BLANK LINES (nothing but blanks)
%    * COMMENT LINES (begin with a '#')
%    * DATA RECORDS (anything else)
%
%    The value returned by the function is the number of data records.
%
%    By the way, if the MATLAB routine FGETS is used, instead of
%    FGETL, then the variable LINE will include line termination
%    characters, which means that a blank line would not actually
%    have zero characters.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 December 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILE_NAME, the name of the input file.
%
%    Output, integer ROW_NUM, the number of rows found.
%
  input_unit = fopen ( input_file_name );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'FILE_ROW_COUNT - Error!\n' );
    fprintf ( 1, '  Could not open the file "%s".\n', input_file_name );
    error ( 'FILE_ROW_COUNT - Error!' );
  end

  blank_num = 0;
  comment_num = 0;
  row_num = 0;

  record_num = 0;

  while ( 1 )

    line = fgetl ( input_unit );

    if ( line == -1 )
      break;
    end

    record_num = record_num + 1;
    record_length = s_len_trim ( line );

    if ( record_length <= 0 )
      blank_num = blank_num + 1;
    elseif ( line(1) == '#' )
      comment_num = comment_num + 1;
    else
      row_num = row_num + 1;
    end

  end

  fclose ( input_unit );

  return
end
function table = i4mat_data_read ( input_filename, m, n )

%*****************************************************************************80
%
%% I4MAT_DATA_READ reads data from an I4MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Input, integer M, N, the number of rows and columns in the data.
%
%    Output, integer TABLE(M,N), the point coordinates.
%
  table = zeros ( m, n );
%
%  Build up the format string for reading M real numbers.
%
  string = ' ';

  for i = 0 : m
    string = strcat ( string, ' %d' );
  end

  input_unit = fopen ( input_filename );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the input file.\n' );
    error ( 'I4MAT_DATA_READ - Error!' );
  end

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'I4MAT_DATA_READ - Error!\n' );
      fprintf ( 1, '  End of input while reading data.\n' );
      error ( 'I4MAT_DATA_READ - Error!' );
    end

    if ( line(1) == '#' )

    elseif ( s_len_trim ( line ) == 0 )

    else

      [ x, count ] = sscanf ( line, string );

      if ( count == m )
        i = i + 1;
        table(1:m,i) = x(1:m);
      end

    end

  end

  fclose ( input_unit );

  return
end
function [ m, n ] = i4mat_header_read ( input_filename )

%*****************************************************************************80
%
%% I4MAT_HEADER_READ reads the header from an I4MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Output, integer M, the spatial dimension.
%
%    Output, integer N, the number of points.
%
  m = file_column_count ( input_filename );

  if ( m <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data columns in\n' );
    fprintf ( 1, '  the file %s.\n', input_filename );
  end

  n = file_row_count ( input_filename );

  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data rows in\n' );
    fprintf ( 1, '  the file %s\n', input_filename );
  end

  return
end
function i4mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% I4MAT_TRANSPOSE_PRINT_SOME prints some of an I4MAT, transposed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 June 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns.
%
%    Input, integer A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, a title.
%
  incx = 10;

  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );

  for i2lo = max ( ilo, 1 ) : incx : min ( ihi, m )

    i2hi = i2lo + incx - 1;
    i2hi = min ( i2hi, m );
    i2hi = min ( i2hi, ihi );

    inc = i2hi + 1 - i2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row: ' );
    for i = i2lo : i2hi
      fprintf ( 1, '%7d  ', i );
    end
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col\n' );
    fprintf ( 1, '\n' );

    j2lo = max ( jlo, 1 );
    j2hi = min ( jhi, n );

    for j = j2lo : j2hi

      fprintf ( 1, '%5d  ', j );
      for i2 = 1 : inc
        i = i2lo - 1 + i2;
        fprintf ( 1, '%7d  ', a(i,j) );
      end
      fprintf ( 1, '\n' );

    end

  end

  return
end
function i4mat_write ( output_filename, m, n, table )

%*****************************************************************************80
%
%% I4MAT_WRITE writes an I4MAT file.
%
%  Discussion:
%
%    An I4MAT is an array of I4's.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 August 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string OUTPUT_FILENAME, the output filename.
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, integer TABLE(M,N), the points.
%
%    Input, logical HEADER, is TRUE if the header is to be included.
%

%
%  Open the file.
%
  output_unit = fopen ( output_filename, 'wt' );

  if ( output_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'I4MAT_WRITE - Error!\n' );
    fprintf ( 1, '  Could not open the output file.\n' );
    error ( 'I4MAT_WRITE - Error!' );
  end
%
%  Write the data.
%
  for j = 1 : n
    for i = 1 : m
      fprintf ( output_unit, '  %12d', round ( table(i,j) ) );
    end
    fprintf ( output_unit, '\n' );
  end
%
%  Close the file.
%
  fclose ( output_unit );

  return
end
function element_node = mesh_base_one ( node_num, element_order, ...
  element_num, element_node )

%*****************************************************************************80
%
%% MESH_BASE_ONE ensures that the element definition is one-based.
%
%  Discussion:
%
%    The ELEMENT_NODE array contains nodes indices that form elements.
%    The convention for node indexing might start at 0 or at 1.
%    Since a MATLAB program will naturally assume a 1-based indexing, it is
%    necessary to check a given element definition and, if it is actually
%    0-based, to convert it.
%
%    This function attempts to detect 0-based node indexing and correct it.
%
%    Thanks to Feifei Xu for pointing out that I was subtracting 1 when I
%    should have been adding 1!  29 November 2012.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 November 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NODE_NUM, the number of nodes.
%
%    Input, integer ELEMENT_ORDER, the order of the elements.
%
%    Input, integer ELEMENT_NUM, the number of elements.
%
%    Input/output, integer ELEMENT_NODE(ELEMENT_ORDE,ELEMENT_NUM), the element
%    definitions.
%
  node_min = min ( min ( element_node(1:element_order,1:element_num) ) );
  node_max = max ( max ( element_node(1:element_order,1:element_num) ) );

  if ( node_min == 0 && node_max == node_num - 1 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MESH_BASE_ONE:\n' );
    fprintf ( 1, '  The element indexing appears to be 0-based!\n' );
    fprintf ( 1, '  This will be converted to 1-based.\n' );
    element_node(1:element_order,1:element_num) = ...
      element_node(1:element_order,1:element_num) + 1;
  elseif ( node_min == 1 && node_max == node_num )
%   fprintf ( 1, '\n' );
%   fprintf ( 1, 'MESH_BASE_ONE:\n' );
%   fprintf ( 1, '  The element indexing appears to be 1-based!\n' );
%   fprintf ( 1, '  No conversion is necessary.\n' );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'MESH_BASE_ONE - Warning!\n' );
    fprintf ( 1, '  The element indexing is not of a recognized type.\n' );
    fprintf ( 1, '  NODE_MIN = %d\n', node_min );
    fprintf ( 1, '  NODE_MAX = %d\n', node_max );
    fprintf ( 1, '  NODE_NUM = %d\n', node_num );
  end

  return
end
function table = r8mat_data_read ( input_filename, m, n )

%*****************************************************************************80
%
%% R8MAT_DATA_READ reads data from an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Input, integer M, N, the number of rows and columns of data.
%
%    Output, real TABLE(M,N), the point coordinates.
%
  table = zeros ( m, n );
%
%  Build up the format string for reading M real numbers.
%
  string = ' ';

  for i = 0 : m
    string = strcat ( string, ' %f' );
  end

  input_unit = fopen ( input_filename );

  if ( input_unit < 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_DATA_READ - Error!\n' );
    fprintf ( 1, '  Could not open the file.\n' );
    error ( 'R8MAT_DATA_READ - Error!' );
  end

  i = 0;

  while ( i < n )

    line = fgets ( input_unit );

    if ( line == -1 )
      break;
    end

    if ( line(1) == '#' )

    elseif ( s_len_trim ( line ) == 0 )

    else

      [ x, count ] = sscanf ( line, string );

      if ( count == m )
        i = i + 1;
        table(1:m,i) = x(1:m);
      end

    end

  end

  fclose ( input_unit );

  return
end
function [ m, n ] = r8mat_header_read ( input_filename )

%*****************************************************************************80
%
%% R8MAT_HEADER_READ reads the header from an R8MAT file.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    22 October 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string INPUT_FILENAME, the name of the input file.
%
%    Output, integer M, the spatial dimension.
%
%    Output, integer N, the number of points.
%
  m = file_column_count ( input_filename );

  if ( m <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data columns in\n' );
    fprintf ( 1, '  the file %s.\n', input_filename );
  end

  n = file_row_count ( input_filename );

  if ( n <= 0 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'R8MAT_HEADER_READ - Fatal error!\n' );
    fprintf ( 1, '  There was some kind of I/O problem while trying\n' );
    fprintf ( 1, '  to count the number of data rows in\n' );
    fprintf ( 1, '  the file %s\n', input_filename );
  end

  return
end
function r8mat_transpose_print_some ( m, n, a, ilo, jlo, ihi, jhi, title )

%*****************************************************************************80
%
%% R8MAT_TRANSPOSE_PRINT_SOME prints some of an R8MAT, transposed.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, N, the number of rows and columns.
%
%    Input, real A(M,N), an M by N matrix to be printed.
%
%    Input, integer ILO, JLO, the first row and column to print.
%
%    Input, integer IHI, JHI, the last row and column to print.
%
%    Input, string TITLE, an optional title.
%
  incx = 5;

  if ( 0 < s_len_trim ( title ) )
    fprintf ( 1, '\n' );
    fprintf ( 1, '%s\n', title );
  end

  for i2lo = max ( ilo, 1 ) : incx : min ( ihi, m )

    i2hi = i2lo + incx - 1;
    i2hi = min ( i2hi, m );
    i2hi = min ( i2hi, ihi );

    inc = i2hi + 1 - i2lo;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Row: ' );
    for i = i2lo : i2hi
      fprintf ( 1, '%7d       ', i );
    end
    fprintf ( 1, '\n' );
    fprintf ( 1, '  Col\n' );

    j2lo = max ( jlo, 1 );
    j2hi = min ( jhi, n );

    for j = j2lo : j2hi

      fprintf ( 1, '%5d ', j );
      for i2 = 1 : inc
        i = i2lo - 1 + i2;
        fprintf ( 1, '%12f', a(i,j) );
      end
      fprintf ( 1, '\n' );

    end

  end

  return
end
function len = s_len_trim ( s )

%*****************************************************************************80
%
%% S_LEN_TRIM returns the length of a character string to the last nonblank.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 June 2003
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be measured.
%
%    Output, integer LEN, the length of the string up to the last nonblank.
%
  len = length ( s );

  while ( 0 < len )
    if ( s(len) ~= ' ' )
      return
    end
    len = len - 1;
  end

  return
end
function word_num = s_word_count ( s )

%*****************************************************************************80
%
%% S_WORD_COUNT counts the number of "words" in a string.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 January 2006
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, string S, the string to be examined.
%
%    Output, integer WORD_NUM, the number of "words" in the string.
%    Words are presumed to be separated by one or more blanks.
%
  FALSE = 0;
  TRUE = 1;

  word_num = 0;
  s_length = length ( s );

  if ( s_length <= 0 )
    return;
  end

  blank = TRUE;

  for i = 1 : s_length

    if ( s(i) == ' ' )
      blank = TRUE;
    elseif ( blank == TRUE )
      word_num = word_num + 1;
      blank = FALSE;
    end

  end

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end


function [J,lambdaOpt,T] = ridgeSVD(Y,Ut, s2,V,nlambda,plotGCV,verb)
%[J,lambdaOpt,T] = ridgeSVD(Y,Ut, s2,V,nlambda,plotGCV)
%
% Estimates a ridge regression model, also know as Tikhonov regularization,
% or minimum norm with L2 prior (or Loreta in the EEG inverse solution literature).
% For an implementation of sLORETA model see the function inverseSolutionLoreta.
%
% Y: measurements (Nsensors X 1)
% Ut, s2,V are defined as the SVD decomposition of the standardized lead field matrix
% nlambda: maximum size of the grid for the hyperparameter lambda, default: 100
% plotGCV: plot the GCV curve (true/false), default: false
% Jest: estimated parapeters
% T: estimated inverse operatormaximum size of the grid for the hyperparameter lambda, default: 100
%
% Jest = argmin(J) ||Y-K*J||^2 + lambda*||L*J||^2 == argmin(J) ||Y-K/L*Jst||^2 + lambda*||I||^2, s.t. J = L/Jst
% and lambda > 0
%
% This code is based on a previous implementation used in Valdes-Hernandez
% et al. (2009), written by Alejandro Ojeda and Pedro Valdez-Hernandez at
% the Cuban Neuroscience Center in 2009.
%
% Author: Alejandro Ojeda, SCCN/INC/UCSD, Jul-2012
%
% References:
%   Pedro A. Valdés-Hernández, Alejandro Ojeda, Eduardo Martínez-Montes, Agustín
%       Lage-Castellanos, Trinidad Virués-Alba, Lourdes Valdés-Urrutia, Pedro A.
%       Valdes-Sosa, 2009. White matter White matter architecture rather than
%       cortical surface area correlates with the EEG alpha rhythm. NeuroImage 49
%       (2010) 2328–2339

if nargin < 4, error('Not enough input arguments.'); end
if nargin < 5 || isempty(nlambda) nlambda = 100; end
if nargin < 6 || isempty(plotGCV) plotGCV = false; end
if nargin < 7 || isempty(verb) verb = false; end

n = size(Ut,1);
p = size(V,1);
s = sqrt(s2);
UtY = Ut*Y;

tol = max([n p])*eps(max(s));
lambda = logspace(log10(tol),log10(max(s)),nlambda);
gcv = zeros(nlambda,1);

beta2 = mean(norms(Y).^2 - norms(UtY).^2);
[n,m] = size(Ut);
delta0 = 0;
  if (m > n && beta2 > 0)
      if verb
        fprintf('m>n criterion met\n');
        fprintf('m=%d, n=%d\n',m,n);
      end
      delta0 = beta2;
  end
for it=1:nlambda
    gcv(it) = gcvfun2(lambda(it),s2,UtY,delta0,m-n);
end

loc = getMinima(gcv);
if verb
    fprintf('GCV min found at loc=%d | lambda=%0.5g\n',loc,lambda(loc)); end
if isempty(loc),
    fprintf('GCV did not find a minimum.\n');
    loc = length(lambda);
end
loc = loc(end);
lambdaOpt = lambda(loc);

T = V*diag(s./(s2+lambdaOpt.^2))*Ut;
J = T*Y;                            % J = (K'*K+lambda*L'*L)\K'*Y

% J = bsxfun(@minus,J,median(J));
% J = bsxfun(@rdivide,J,(std(J)+eps));

if plotGCV
    figure;
    semilogx(lambda,gcv)
    xlabel('log-lambda');
    ylabel('GCV');
    hold on;
    plot(lambdaOpt,gcv(loc),'rx','linewidth',2)
    grid on;
end

%---
function indmin = getMinima(x)
fminor = diff(x)>=0;
fminor = ~fminor(1:end-1) & fminor(2:end);
fminor = [0; fminor; 0];
indmin = find(fminor);

function G = gcvfun2(lambda,s2,beta,delta0,mn,dsvd)

% Auxiliary routine for gcv.  PCH, IMM, Feb. 24, 2008.

% Note: f = 1 - filter-factors.
if (nargin==5)
   f = (lambda^2)./(s2 + lambda^2);
else
   f = lambda./(s2 + lambda);
end
G = mean((norms(bsxfun(@times,f,beta)).^2 + delta0)/(mn + sum(f))^2);


function TFM = createRotationVectorPoint3d(A,B,P)
%CREATEROTATIONVECTORPOINT3D Calculates the rotation between two vectors.
%   around a point
%
%   TFM = createRotationVectorPoint3d(A,B,P) returns the transformation
%   to rotate the vector A in the direction of vector B around point P
%
%   Example
%     A=-5+10.*rand(1,3);
%     B=-10+20.*rand(1,3);
%     P=-50+100.*rand(1,3);
%     ROT = createRotationVectorPoint3d(A,B,P);
%     C = transformVector3d(A,ROT);
%     figure('color','w'); hold on; view(3)
%     drawPoint3d(P,'k')
%     drawVector3d(P, A,'r')
%     drawVector3d(P, B,'g')
%     drawVector3d(P, C,'r')
%
%   See also
%   transformPoint3d, createRotationVector3d
%
% ---------
% Author: oqilipo
% Created: 2017-08-07
% Copyright 2017

P = reshape(P,3,1);

% Translation from P to origin
invtrans = [eye(3),-P; [0 0 0 1]];

% Rotation from A to B
rot = createRotationVector3d(A, B);

% Translation from origin to P
trans = [eye(3),P; [0 0 0 1]];

% Combine
TFM = trans*rot*invtrans;

end


clear all, close all, clc

% J = @(u,t)(25-(5-(u-t))^2);

J = @(u,t)(25-(5-(u)).^2);
y0 = J(0,0);  % u = 0

% Extremum Seeking Control Parameters
freq = 10*2*pi; % sample frequency
dt = 1/freq;
T = 10; % total period of simulation (in seconds)
A = .2;  % amplitude
omega = 10*2*pi; % 10 Hz
phase = 0;
K = 5;   % integration gain

% High pass filter (Butterworth filter)
butterorder=1;
butterfreq=2;  % in Hz for 'high'
[b,a] = butter(butterorder,butterfreq*dt*2,'high')
ys = zeros(1,butterorder+1)+y0;
HPF=zeros(1,butterorder+1);

uhat=u;
for i=1:T/dt
    t = (i-1)*dt;
    yvals(i)=J(u,t);

    for k=1:butterorder
        ys(k) = ys(k+1);
        HPF(k) = HPF(k+1);
    end
    ys(butterorder+1) = yvals(i);
    HPFnew = 0;
    for k=1:butterorder+1
        HPFnew = HPFnew + b(k)*ys(butterorder+2-k);
    end
    for k=2:butterorder+1
        HPFnew = HPFnew - a(k)*HPF(butterorder+2-k);
    end
    HPF(butterorder+1) = HPFnew;

    xi = HPFnew*sin(omega*t + phase);
    uhat = uhat + xi*K*dt;
    u = uhat + A*sin(omega*t + phase);
    uhats(i) = uhat;
    uvals(i) = u;
end

%%
figure
subplot(2,1,1)
plot(t,uvals,t,uhats,'LineWidth',1.2)
l1=legend('$u$','$\hat{u}$')
set(l1,'interpreter','latex','Location','NorthWest')
grid on
subplot(2,1,2)
plot(t,yvals,'LineWidth',1.2)
ylim([-1 26])
grid on

set(gcf,'Position',[100 100 500 350])
set(gcf,'PaperPositionMode','auto')
% print('-depsc2', '-loose', '../../../figures/ESC_Response');


function [ TreeMatric,Cost ] = DirectedMaximumSpanningTree( OriginalCostMatric,Root )
% MST on a directed graph
% Chu-Liu/Edmonds Algorithm:
%1 Discard the arcs entering the root if any; For each node other than the root, select the entering arc with the highest cost; Let the selected n-1 arcs be the set S.
%  If no cycle is formed, G( N,S ) is a MST. Otherwise, continue.
%2 For each cycle formed, contract the nodes in the cycle into a pseudo-node (k), and modify the cost of each arc which enters a node (j) in the cycle from some node (i)
%  outside the cycle according to the following equation.  c(i,k)=c(i,j)-(c(x(j),j)-min_{j}(c(x(j),j)) where c(x(j),j) is the cost of the arc in the cycle which enters j.
%3 For each pseudo-node, select the entering arc which has the smallest modified cost; Replace the arc which enters the same real node in S by the new selected arc.
%4 Go to step 2 with the contracted graph.

% This code is written by Lowell Guangdi, Email: lowellli121@gmail.com
Dim = size( OriginalCostMatric,2 );
for p = 1:Dim, OriginalCostMatric( p,p ) = 0;end

Min = min(min(OriginalCostMatric));
OriginalCostMatric = OriginalCostMatric - Min;

CostMatric = OriginalCostMatric;
CostMatric( :,Root )= zeros( Dim,1 );
while 1
     TreeMatric = CostMatric;
     % select out the maximal weights of arcs upon each node.
     for p = 1 : Dim
         if p ~= Root
            [ LocalMax,Index ] = max( TreeMatric( :,p ) );
            TreeMatric( :,p ) = zeros( Dim,1 );
            TreeMatric( Index,p ) = LocalMax;
         end
     end
     % test the existence of cycle
     [ CNumber, Component ] = conncomp( biograph( TreeMatric ),'Weak', true );
     if CNumber == 1,break; end
     % Cycle exists
     RootCluster = Component( Root );
     RootSharedNode = find( Component == RootCluster );
     if RootCluster == 1
        CaredCluster = 2;
     elseif RootCluster > 1
        CaredCluster = 1;
     end
     % change the weight here
     ClusterNode = find( Component == CaredCluster );
     CostMatric = SearchCycleNode(ClusterNode,TreeMatric, CostMatric,OriginalCostMatric,RootSharedNode);
end
TreeMatric = CostMatric;
Cost = sum(sum( TreeMatric ));
end