function [position0,position,messages]= delineate3D(w1,w2,w3,intreg,timenew,position0,position,intervalo,position1,position2,position3,indexes,samp,sig,messages)
%
%
% [position0,position,A,V,A2,V2]= delineate3D(w1,w2,w3,intreg,scale,timenew,position0,position,intervalo,position1,samp)
% 3D multilead delineation of T wave
%
% Input Parameters:
%   w1: matrix with WT scales 1 to 5 for lead 1
%   w2: matrix with WT scales 1 to 5 for lead 2
%   w3: matrix with WT scales 1 to 5 for lead 1
%  intreg: interval to be considered in fitting the optimal direction
%  scale to use in delineation
%   timenew:  QRS times in inedexes refering the interval included in the current excerpt (borders excluded)
%   position0: struct vector with the detected points for 3D multilead  step1
%   position: struct vector with the detected points for 3D multilead  step2
%   position1: struct vector with the detected points for lead1 - to be replaced for multilead marks
%   samp: samples included in the current excerpt (borders excluded)
%   intervalo: numeration of the beats processed in this segment
%
%Output Parameters:
%   actualized parameters: position, position0
% A - points of fitted lines in step 1
% A2 - points of fitted lines in step 2
%  V- vectors director to the fitted line
%  V2- vectors director to the fitted line
%
% Rute Almeida: trabalho de doutoramento 2.Dec.2004
% Last update: 05AGO2011
%
% MATLAB Version 6.5.0.180913a (R13)

global recursioncount OPT
A=[];A2=[];
V=[];V2=[];
if isempty(sig)

end
% Aon=[];Von=[];
% Vg=[];
% if nargin==15
% messages = new_empty_mesg;
% end
if ~isfield(messages.setup.wavedet,'rrant_mintol')
    messages.setup.wavedet.rrant_mintol  =  0.5;    % minimum time in sec admited for current RR to be used in T wave delineation or in Exponentially averaged RR
end
if ~isfield(messages.setup.wavedet,'rrant_maxtol')
    messages.setup.wavedet.rrant_maxtol  =  1.5;    % max time in sec admited for current RR to be used in Exponentially averaged RR
end
if ~isfield(messages.setup.wavedet,'rrant_average')
    messages.setup.wavedet.rrant_average  =  [0.8 0.2];    % Exponentially averaged RR weights
end
if ~isfield(messages.setup.wavedet,'scale')
    messages.setup.wavedet.scale=4;
end
if ~isfield(messages.setup.wavedet,'scale2')
    messages.setup.wavedet.scale2=5;
end
if ~isfield(messages.setup.wavedet,'T_CSE_tol')
    messages.setup.wavedet.T_CSE_tol=30.6*2/1000; % based on CSE tolerance
end
if ~isfield(messages.setup.wavedet,'Tconvergence_crit')
    messages.setup.wavedet.Tconvergence_crit=1; % 1 maks are acepted as the same if they difer by Tconvergence_crit
end

rrant_mintol=messages.setup.wavedet.rrant_mintol;
rrant_maxtol=messages.setup.wavedet.rrant_maxtol;
rrant_average=messages.setup.wavedet.rrant_average;
scale=messages.setup.wavedet.scale;
scale2=messages.setup.wavedet.scale2;
Tconvergence_crit=messages.setup.wavedet.Tconvergence_crit;

intervalo=intervalo(1):intervalo(end);

scalei=scale*ones(1,size(intreg,1));
if ~isempty(w3)
    %scalei(sum([position1.Tscale(intervalo);position2.Tscale(intervalo);position3.Tscale(intervalo)]==5)>1)=5;
    %Rute 17Mar06
    aux=[(indexes(1,intervalo));(indexes(2,intervalo));(indexes(3,intervalo))];
    aux(1,~isnan(aux(1,:)))=position1.Tscale(aux(1,~isnan(aux(1,:))));
    aux(2,~isnan(aux(2,:)))=position2.Tscale(aux(2,~isnan(aux(2,:))));
    aux(3,~isnan(aux(3,:)))=position3.Tscale(aux(3,~isnan(aux(3,:))));
    scalei(sum(aux==5)>1)=5;
    %%%%%%
else
    scalei(sum([position1.Tscale(intervalo);position2.Tscale(intervalo)]==scale2)>1)=scale2;
end

for i=1:size(intreg,1)

    if isnan(intreg(i,1))
        position.Tscale(intervalo(i))=NaN;
        position.Toff(intervalo(i))=NaN;
        position.T(intervalo(i))=NaN;
        position.Ttipooff(intervalo(i))=NaN;
        position.Ttipo(intervalo(i))=NaN;
        position.Tprima(intervalo(i))=NaN;
        position.Ton(intervalo(i))=NaN;
        position.Ttipoon(intervalo(i))=NaN;
    else

        scale=scalei(i);
        %marks taken as the last in the 3 leads

        aux2=find(~isnan(indexes(2,intervalo(i))));
        aux3=find(~isnan(indexes(3,intervalo(i))));
        S=max([position1.S(indexes(~isnan(indexes(1,intervalo(i))),intervalo(i))) position2.S(indexes(2*aux2,intervalo(i))) position3.S(indexes(3*aux3,intervalo(i))) ]-samp(1)+1);
        QRSoff=max([position1.QRSoff(indexes(~isnan(indexes(1,intervalo(i))),intervalo(i))) position2.QRSoff(indexes(2*aux2,intervalo(i))) position3.QRSoff(indexes(3*aux3,intervalo(i)))]-samp(1)+1);

        if ~isempty(w3)
            pontos=[w1(intreg(i,1):min(intreg(i,2),length(w1)),scale) w2(intreg(i,1):min(intreg(i,2),length(w2)),scale) w3(intreg(i,1):min(intreg(i,2),length(w3)),scale) ];
        else
            pontos=[w1(intreg(i,1):min(intreg(i,2),length(w1)),scale) w2(intreg(i,1):min(intreg(i,2),length(w2)),scale)];
        end
        weight=ones(size(pontos,1),1);
        [a,v] = optimline(pontos, weight,OPT);

        A=[A;a]; %#ok<AGROW>
        V=[V;v]; %#ok<AGROW>

        %4FEB2010
        if length(intervalo)>1
            rrant=position.qrs(intervalo(2))-position.qrs(intervalo(1));
        elseif intervalo(1)>1
            rrant=position.qrs(intervalo(1))-position.qrs(intervalo(1)-1);
        else
            rrant=messages.setup.wavedet.freq/2; %JUL2011
        end

        if (i>1),
            if (rrant_maxtol*rrant>(timenew(i)-timenew(i-1)))&&(timenew(i)-timenew(i-1)>rrant_mintol*rrant),
                rrmed = rrant_average(1)*rrant + rrant_average(2)*(timenew(i)-timenew(i-1));
            else
                rrmed = rrant;  % Exponentially averaged RR
            end
        else                  % Only for the first in each segment of the ECG
            rrmed = rrant;
        end
        rrant = rrmed;        %#ok<NASGU> % For next segment

        %WT projected: from the previous QRS complex to the following QRS complex
        if ~isempty(w3)
            if i<length(timenew),
                newleadbeat=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2)+w3(timenew(i):timenew(i+1),scale)*v(3))./norm(v);
                %signew=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2)+sig(timenew(i):timenew(i+1),3)*v(3))./norm(v);
            else                        % if last beat of the segment
                newleadbeat=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2)+w3(timenew(i):end,scale)*v(3))./norm(v);
                %signew=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2)+sig(timenew(i):end,3)*v(3))./norm(v);
            end
        else
            if i<length(timenew),
                newleadbeat=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2))./norm(v);
                %signew=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2))./norm(v);
            else                        % if last beat of the segment
                newleadbeat=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2))./norm(v);
                %signew=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2))./norm(v);
            end
        end
        [pos,picon,picoff,janelas1,messages]=twave3D( newleadbeat,timenew,i,messages.setup.wavedet.freq,S,QRSoff,samp,rrmed,messages); %#ok<ASGLU>
%         janelas1=janelas1+timenew(i)-1;
        position0.Tscale(intervalo(i))=scale;
        position0.Ton(intervalo(i))=pos.Ton;
        position0.Toff(intervalo(i))=pos.Toff;
        position0.T(intervalo(i))=pos.T;
        position0.Ttipo(intervalo(i))=pos.Ttipo;
        position0.Tprima(intervalo(i))=pos.Tprima;

        %position0.Wavedet(intervalo(i))=newleadbeat; % derivada wavedet Maikel 30 marzo 2009
        %position0.direccion(c)=V; % vector direcci�n Maikel 30 marzo 2009
        %pontos2=[w1(picoff:intreg(i,2),scale) w2(picoff:intreg(i,2),scale) w3(picoff:intreg(i,2),scale) ];

        if ~isnan(picoff)
            if picoff>(intreg(i,2)-1)
                messages.warnings=[messages.warnings {'Tend out of the searching interval, in the fist step of multilead!'}];
                position.Tscale(intervalo(i))=NaN;
                position.Toff(intervalo(i))=NaN;
                position.T(intervalo(i))=NaN;
                position.Ttipooff(intervalo(i))=NaN;
                position.Ttipo(intervalo(i))=NaN;
                position.Tprima(intervalo(i))=NaN;
                recursioncount.Toff(intervalo(i))=NaN;
                position.contadorToff(intervalo(i))=NaN; %Rute
            else
                if (pos.Toff-samp(1)+1)==picoff
                    endaux=min([(position0.Toff(intervalo(i))-samp(1)+1+round(messages.setup.wavedet.T_CSE_tol*messages.setup.wavedet.freq)) length(w1)]); %3JUL

                else
                    endaux=min([intreg(i,2) (position0.Toff(intervalo(i))-samp(1)+1+messages.setup.wavedet.T_CSE_tol*messages.setup.wavedet.freq) ]);
                end
                if ~isempty(w3)
                    pontos2=[w1(picoff:endaux,scale) w2(picoff:endaux,scale) w3(picoff:endaux,scale)];
                    %pontos2=[w1(janelas1(2):janelas1(3),scale) w2(janelas1(2):janelas1(3),scale) w3(janelas1(2):janelas1(3),scale)];
                else
                    pontos2=[w1(picoff:endaux,scale) w2(picoff:endaux,scale)];
                end
                weight2=ones(size(pontos2,1),1);
                [a,v] = optimline(pontos2, weight2,OPT);
                A2=[A2;a]; %#ok<AGROW>
                V2=[V2;v]; %#ok<AGROW>
                if ~isempty(w3)
                    if i<length(timenew),
                        newleadbeat2=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2)+w3(timenew(i):timenew(i+1),scale)*v(3))./norm(v);
                        %signew2=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2)+sig(timenew(i):timenew(i+1),3)*v(3))./norm(v);
                    else                        % if last beat of the segment
                        newleadbeat2=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2)+w3(timenew(i):end,scale)*v(3))./norm(v);
                        %signew2=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2)+sig(timenew(i):end,3)*v(3))./norm(v);
                    end
                else
                    if i<length(timenew),
                        newleadbeat2=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2))./norm(v);
                        %signew2=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2))./norm(v);
                    else                        % if last beat of the segment
                        newleadbeat2=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2))./norm(v);
                        %signew2=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2))./norm(v);
                    end
                end
                [pos,picon2,picoff2,janelas2,messages]=twave3D(newleadbeat2,timenew,i,messages.setup.wavedet.freq,S,QRSoff,samp,rrmed,messages); %#ok<ASGLU>
%                 janelasnew=janelas2+timenew(i)-1;
                picoffall=[picoff picoff2];
                if isnan(picoff2)
                    amppicoffall=[abs(newleadbeat(picoff-timenew(i)+1)) NaN];
                else
                    amppicoffall=[abs(newleadbeat(picoff-timenew(i)+1)) abs(newleadbeat2(picoff2-timenew(i)+1))];
                end
                newToff=[position0.Toff(intervalo(i)) pos.Toff];

                if (amppicoffall(end)<amppicoffall(end-1))
                    position.contadorToff(intervalo(i))=-1;
                    %Vg(i,:)=V(end,:);
                    position.Tscale(intervalo(i))=position0.Tscale(intervalo(i));
                    position.Toff(intervalo(i))=position0.Toff(intervalo(i));
                    position.T(intervalo(i))= position0.T(intervalo(i));
                    position.Ttipooff(intervalo(i))=position0.Ttipo(intervalo(i));
                    position.Ttipo(intervalo(i))=NaN;
                    position.Tprima(intervalo(i))=position0.Tprima(intervalo(i));
                    %position.contadorToff=recursioncount.Toff;
                    position.direccionToffopt(:,intervalo(i))=V(end,:);
                    %position.Wavedet(intervalo(i))=newleadbeat2; % derivada wavedet Maikel 30 marzo 2009
                    %position.direccion(:,intervalo(i))=V2; % vector direcci�n Maikel 30 marzo 2009
                else
                    position.contadorToff(intervalo(i))=0;
                    %Vg(i,:)=V2(end,:);
                    position.direccionToffopt(:,intervalo(i))=V2(end,:);
                    %%%%%%%%%%%%%%%%%%%%%%recursion
                    while (~isnan(picoffall(end)) &&  abs(newToff(end)-newToff(end-1))>Tconvergence_crit) && (amppicoffall(end)>amppicoffall(end-1))
                        position.contadorToff(intervalo(i))=position.contadorToff(intervalo(i))+1;
                        %maxTintervalend=maxTintervalend; % teste 14
                        if (pos.Toff-samp(1)+1)==picoff
                            endaux=(pos.Toff-samp(1)+1+round(messages.setup.wavedet.T_CSE_tol*messages.setup.wavedet.freq));
                        else
                            endaux=min([intreg(i,2) (pos.Toff-samp(1)+1+round(messages.setup.wavedet.T_CSE_tol*messages.setup.wavedet.freq))]);
                        end
                        if ~isempty(w3)
                            pontosnew=[w1(picoffall(end):endaux,scale) w2(picoffall(end):endaux,scale) w3(picoffall(end):endaux,scale)];
                            %pontosnew=[w1(picoff(end):endaux,scale) w2(picoff(end):endaux,scale) w3(picoff(end):endaux,scale)];
                            %pontosnew=[w1(janelasnew(2):janelasnew(3),scale) w2(janelasnew(2):janelasnew(3),scale) w3(janelasnew(2):janelasnew(3),scale)];
                        else
                            pontosnew=[w1(picoffall(end):endaux,scale) w2(picoffall(end):endaux,scale)];
                        end

                        if   size(pontosnew,1)>1
                            weightnew=ones(size(pontosnew,1),1);
                            [a,v] = optimline(pontosnew, weightnew,OPT);
%                             if i==6
%                                 title([ecgnr '(Tend-step' num2str(2+position.contadorToff(intervalo(i)))')'])
%                             else
%                                 close
%                             end
                            A2=[A2;a]; %#ok<AGROW>
                            V2=[V2;v]; %#ok<AGROW>
                            if ~isempty(w3)
                                if i<length(timenew),
                                    newleadbeatnew=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2)+w3(timenew(i):timenew(i+1),scale)*v(3))./norm(v);
                                    %signewnew=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2)+sig(timenew(i):timenew(i+1),3)*v(3))./norm(v);
                                else                        % if last beat of the segment
                                    newleadbeatnew=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2)+w3(timenew(i):end,scale)*v(3))./norm(v);
                                    %signewnew=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2)+sig(timenew(i):end,3)*v(3))./norm(v);
                                end
                            else
                                if i<length(timenew),
                                    newleadbeatnew=(w1(timenew(i):timenew(i+1),scale).*v(1)+w2(timenew(i):timenew(i+1),scale)*v(2))./norm(v);
                                    %signewnew=(sig(timenew(i):timenew(i+1),1).*v(1)+sig(timenew(i):timenew(i+1),2)*v(2))./norm(v);
                                else                        % if last beat of the segment
                                    newleadbeatnew=(w1(timenew(i):end,scale).*v(1)+w2(timenew(i):end,scale)*v(2))./norm(v);
                                    %signewnew=(sig(timenew(i):end,1).*v(1)+sig(timenew(i):end,2)*v(2))./norm(v);
                                end
                            end

                            [pos,picon2,picoffnew,janelasnew,messages]=twave3D(newleadbeatnew,timenew,i,messages.setup.wavedet.freq,S,QRSoff,samp,rrmed,messages); %#ok<ASGLU>
%                             janelasnew=janelas2+timenew(i)-1;
                        else
                            picoffnew=NaN;
                        end
                        picoffall=[picoffall picoffnew]; %#ok<AGROW>
                        if isnan(picoffnew)
                            amppicoffall=[amppicoffall NaN]; %#ok<AGROW>
                        else
                            amppicoffall=[amppicoffall abs(newleadbeatnew(picoffnew-timenew(i)+1))]; %#ok<AGROW>
                        end
                        newToff=[newToff pos.Toff]; %#ok<AGROW>

                        if (amppicoffall(end)<amppicoffall(end-1))
                            pos.Toff=NaN; % because the lead got worse
                        end
                        if isnan(pos.Toff); %01Jun05
                            pos.Toff=newToff(end-1);
                            position.contadorToff(intervalo(i))=position.contadorToff(intervalo(i))-1;
                        else
                            %Vg(i,:)=V2(end,:);
                            position.direccionToffopt(:,intervalo(i))=V2(end,:);
                            %contador=[contador; recursioncount.Toff];
                        end
                        if  prod(picoffall(1:end-1)-picoffall(end))==0  % ciclo infinito no teste 14
                            picoffall(end)=NaN;
                        end
                    end
                    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
                    position.Tscale(intervalo(i))=scale;
                    position.Toff(intervalo(i))=pos.Toff;
                    position.T(intervalo(i))=pos.T;
                    position.Ttipooff(intervalo(i))=pos.Ttipo;
                    position.Ttipo(intervalo(i))=NaN;
                    position.Tprima(intervalo(i))=pos.Tprima;
                    %position.contadorToff=recursioncount.Toff;
                    %position.Wavedet(intervalo(i))=newleadbeatnew; % derivada wavedet Maikel 30 marzo 2009
                    %position.direccion(:,intervalo(i))=V2; % vector direcci�n Maikel 30 marzo 2009

                end
                %
            end
        else
            position.Tscale(intervalo(i))=NaN;
            position.Toff(intervalo(i))=NaN;
            position.T(intervalo(i))=NaN;
            position.Ttipooff(intervalo(i))=NaN;
            position.Ttipo(intervalo(i))=NaN;
            position.Tprima(intervalo(i))=NaN;
            recursioncount.Toff(intervalo(i))=NaN;
            position.contadorToff(intervalo(i))=NaN; %Rute
            %position.Wavedet(intervalo(i))=NaN;  % derivada wavedet Maikel 30 marzo 2009
            %position.direccion(:,intervalo(i))=NaN; % vector direcci�n Maikel 30 marzo 2009
        end

        Tbeginauxiliar
    end
end
% position0.A(intervalo(i))=A;
% position0.A2(intervalo(i))=A2;
% position0.V(intervalo(i))=V;
% position0.V2(intervalo(i))=V2;


function  a = i4vec_indicator1 ( n )

%*****************************************************************************80
%
%% I4VEC_INDICATOR1 sets an I4VEC to the indicator vector (1,2,3,...).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 September 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Output, integer A(N), the vector.
%
  a = ( 1 : n );

  return
end


function plotData(x, y)
%PLOTDATA Plots the data points x and y into a new figure
%   PLOTDATA(x,y) plots the data points and gives the figure axes labels of
%   population and profit.

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the training data into a figure using the
%               "figure" and "plot" commands. Set the axes labels using
%               the "xlabel" and "ylabel" commands. Assume the
%               population and revenue data have been passed in
%               as the x and y arguments of this function.
%
% Hint: You can use the 'rx' option with plot to have the markers
%       appear as red crosses. Furthermore, you can make the
%       markers larger by using plot(..., 'rx', 'MarkerSize', 10);

figure; % open a new figure window

plot(x, y, 'rx', 'MarkerSize', 10);
xlabel('Population of City in 10,000s');
ylabel('Profit in $10,000s');

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

end


function [ a, b ] = p06_lim ( )

%*****************************************************************************80
%
%% P06_LIM returns the integration limits for problem 6.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = -1.0;
  b = 1.0;

  return
end


function [ a, b] = p02_interval ( )

%*****************************************************************************80
%
%% P02_INTERVAL returns a starting interval for optimization for problem 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 February 2002
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, two points defining an interval in which
%    the local minimizer should be sought.
%
  a = 0.0;
  b = 1.0;

  return
end


function cmap = crameri(ColormapName,varargin)
% crameri returns perceptually-uniform scientific colormaps created
% by Fabio Crameri.
%
%% Syntax
%
%  crameri
%  cmap = crameri('ColormapName')
%  cmap = crameri('-ColormapName')
%  cmap = crameri(...,NLevels)
%  cmap = crameri(...,'pivot',PivotValue)
%  crameri(...)
%
%% Description
%
% crameri without any inputs displays the options for colormaps.
%
% cmap = crameri('ColormapName') returns a 256x3 colormap.  For a visual
% depiction of valid colormap names, type |crameri|.
%
% cmap = crameri('-ColormapName') a minus sign preceeding any ColormapName flips the
% order of the colormap.
%
% cmap = crameri(...,NLevels) specifies a number of levels in the colormap.  Default
% value is 256.
%
% cmap = crameri(...,'pivot',PivotValue) centers a diverging colormap such that white
% corresponds to a given value and maximum extents are set using current caxis limits.
% If no PivotValue is set, 0 is assumed.
%
% crameri(...) without any outputs sets the current colormap to the current axes.
%
%% Examples
% For examples, type:
%
%  showdemo crameri_documentation
%
%% Author Info
% This function was written by Chad A. Greene of the University of Texas
% Institute for Geophysics (UTIG), August 2018, using Fabio Crameri's
% scientific colormaps, version 4.0. http://www.fabiocrameri.ch/colourmaps.php
%
%% Citing this colormap:
% Please acknowledge the free use of these colormaps by citing
%
% Crameri, F. (2018). Scientific colour-maps. Zenodo. http://doi.org/10.5281/zenodo.1243862
%
% Crameri, F. (2018), Geodynamic diagnostics, scientific visualisation and
% StagLab 3.0, Geosci. Model Dev., 11, 2541-2562, doi:10.5194/gmd-11-2541-2018.
%
% For more on choosing effective and accurate colormaps for science, be sure
% to enjoy this fine beach reading:
%
% Thyng, K.M., C.A. Greene, R.D. Hetland, H.M. Zimmerle, and S.F. DiMarco. 2016. True
% colors of oceanography: Guidelines for effective and accurate colormap selection.
% Oceanography 29(3):9-13, http://dx.doi.org/10.5670/oceanog.2016.66.
%
% See also colormap and caxis.

%% Display colormap options:

if nargin==0
   figure('menubar','none','numbertitle','off','Name','crameri options:')

   if license('test','image_toolbox')
      imshow(imread('crameri7.0.png'));
   else
      axes('pos',[0 0 1 1])
      image(imread('crameri7.0.png'));
      axis image off
   end

   return
end

%% Error checks:

assert(isnumeric(ColormapName)==0,'Input error: ColormapName must be a string.')

%% Set defaults:

NLevels = 256;
autopivot = false;
PivotValue = 0;
InvertedColormap = false;

%% Parse inputs:

% Does user want to flip the colormap direction?
dash = strncmp(ColormapName,'-',1);
if any(dash)
   InvertedColormap = true;
   ColormapName(dash) = [];
end

% Standardize all colormap names to lowercase:
%ColormapName = lower(ColormapName);

% Oleron's too hard for me to remember, so I'm gonna use dem or topo.
if ismember(ColormapName,{'dem','topo'})
   ColormapName = 'oleron';
end

% Does the user want to center a diverging colormap on a specific value?
% This parsing support original 'zero' syntax and current 'pivot' syntax.
tmp = strncmpi(varargin,'pivot',3);
if any(tmp)
   autopivot = true;
   try
      if isscalar(varargin{find(tmp)+1})
         PivotValue = varargin{find(tmp)+1};
         tmp(find(tmp)+1) = 1;
      end
   end
   varargin = varargin(~tmp);
end

% Has user requested a specific number of levels?
tmp = isscalar(varargin);
if any(tmp)
   NLevels = varargin{tmp};
end

%% Load RGB values and interpolate to NLevels:

try
   S = load('CrameriColourMaps7.0.mat',ColormapName);
   cmap = S.(ColormapName);
catch
   error(['Unknown colormap name ''',ColormapName,'''. Try typing crameri with no inputs to check the options and try again.'])
end

% Interpolate if necessary:
if NLevels~=size(cmap,1)
   cmap = interp1(1:size(cmap,1), cmap, linspace(1,size(cmap,1),NLevels),'linear');
end

%% Invert the colormap if requested by user:

if InvertedColormap
   cmap = flipud(cmap);
end

%% Adjust values to current caxis limits?

if autopivot
   clim = caxis;
   maxval = max(abs(clim-PivotValue));
   cmap = interp1(linspace(-maxval,maxval,size(cmap,1))+PivotValue, cmap, linspace(clim(1),clim(2),size(cmap,1)),'linear');
end

%% Clean up

if nargout==0
   colormap(gca,cmap)
   clear cmap
end

%% Code to collect Fabio's data into a single .mat file:
% Unzip the latest folder, navigate to that filepath, and run this.
% Update the file list as needed.
%
% clear all
% f = {'acton','bam','bamO','bamako','batlow','batlowK','batlowW','berlin','bilbao','broc','brocO','buda','bukavu','cork',...
%    'corkO','davos','devon','fes','grayC','hawaii','imola','lajolla','lapaz','lisbon',...
%    'nuuk','oleron','oslo','roma','romaO','tofino','tokyo','turku','vanimo','vik','vikO'};
%
% for k = 1:length(f)
%    load([f{k},'/',f{k},'.mat'])
% end
%
% clear f k
% save('CrameriColourMaps7.0.mat')


function [ a, b ] = p01_lim ( )

%*****************************************************************************80
%
%% P01_LIM returns the integration limits for problem 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function sz = mysize(M)
% MYSIZE Like the built-in size, except it returns n if M is a vector of length n, and 1 if M is a scalar.
% sz = mysize(M)
%
% The behavior is best explained by examples
% - M = rand(1,1),   mysize(M) = 1,      size(M) = [1 1]
% - M = rand(2,1),   mysize(M) = 2,      size(M) = [2 1]
% - M = rand(1,2),   mysize(M) = 2,      size(M) = [1 2]
% - M = rand(2,2,1), mysize(M) = [2 2],  size(M) = [2 2]
% - M = rand(1,2,1), mysize(M) = 2,      size(M) = [1 2]

if isvectorBNT(M)
  sz = length(M);
else
  sz = size(M);
end


% line_fewer_markers - line with controlled amount of markers and correct legend behaviour
%
%   LINE_FEWER_MARKERS(X,Y,NUM_MARKERS) adds the line in vectors X and Y to the current axes
%   with exactly NUM_MARKERS markers drawn.
%
%   LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...) plots the data
%   stored in the vectors X and Y.
%
%   LINE_FEWER_MARKERS returns handles to LINE/MARKER objects.
%
%   [H1,H2,H3] = LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...)
%   performs the actions as above and returns the handles of all the plotted lines/markers.
%   H1    = handle to the main marker(1 point); it may be put in array and used with legend
%   H2    = handle to the continuous line (as in H2=plot())
%   H3    = handle to all other markers
%
%   Property/Value pairs and descriptions:
%
%       Spacing    - 'x'      : ordinary uniform along x
%                  - 'curve'  : equal lengths along curve y(x)
%                  - 'logx'   : to be used with logarithmic x scale
%
%       LockOnMax  - 0        : first marker on 1st data point
%                  - 1        : offset all markers such that one marker on first max of y(x)
%
%       LegendLine - 'on'     : default, reproduce linestyle also in legend
%                  - 'off'    : shows only marker in legend
%
%       LineSpec: same as for LINE: LineStyle,LineWidth,Marker,MarkerSize,MarkerFaceColor...
%
%
%   Example: plot 3 curves with 9,9, and 15 markers each, using different input styles
%
%      figure; hold on;
%      t  = 0:0.005:pi;
%      line_fewer_markers(t*180/pi,cos(t) ,9,  '--bs','spacing','curve');
%      line_fewer_markers(t*180/pi,sin(t) ,9,  '-.ro','MarkerFaceColor','g', ...
%                                                     'markersize',6,'linewidth',2);
%      grey1 = [1 1 1]*0.5;
%      line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','marker','h','color',grey1, ...
%                                    'markerfacecolor',grey1,'linewidth',2,'LockOnMax',1);
%      leg = legend('cos','sin','sin*cos','location','best');
%
% Inspired by Ioannis Filippidis's answer:
% http://www.mathworks.com/matlabcentral/answers/2165-too-many-markers
%
% rev.4, Massimo Ciacci, October 17, 2014
%
function [H1,H2,H3] = line_fewer_markers(x,y,num_Markers, varargin)

%% find marker spec in varargin and remove it; extract special params: LockOnMax,Spacing
if mod(length(varargin),2)
    if ischar(varargin{1})
      linspec   = varargin{1};
      extraArgs = varargin(2:end);
      [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec,extraArgs);
    else
      error('odd sized [param | val] list, missing one param ?');
    end
else
      [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin{:});
end

%% input size check
if  isvector(x) &&  isvector(y)
    % make x,y row vectors
    if iscolumn(x), x = x.'; end
    if iscolumn(y), y = y.'; end
else
    error('line_fewer_markers: input arguments must be 1D vectors');
end

% How the method works: plots 3 times:
% a) once only the line with all points with the style                                        'r--' and invisible handle,
% b) last time the markers, using fewer points with style                                     'ro' and again invisible handle.
% c) once with a visible handle, only the first point, using the complete style you specified (e.g. 'r--o')

%% a) once only the line with all points with the style
H2 = line(x   ,y   ,varargInNoMk{:});                               %no markers here
hasbehavior(H2,'legend',0);                                         %prevent to appear in legends!

%% b) last time the markers, using fewer points with style
%sort the xvalues
[x_t,I] = sort(x);
y_t = y(I);
[x_t,I] = unique(x_t);
y_t = y_t(I);

if     (strcmp(Spacing,'x') || strcmp(Spacing,'X'))
    ti = round(linspace(1,length(x_t),num_Markers));
elseif (strcmp(Spacing,'logx') || strcmp(Spacing,'log'))
    xi = logspace(log10(x_t(2)),log10(x_t(end-1)),num_Markers);
    ti = floor(interp1(x_t,(1:length(x_t)),xi));
elseif (strcmp(Spacing,'curve') || strcmp(Spacing,'Curve'))
    scaleY     = 3/4; % 1/1 figure aspect ratio
    yNrm       = (y-min(y))./(max(y)-min(y))*scaleY;             %NORMALIZE y scale in [0 1], height of display is prop to max(abs(y))
    xNrm       = (x-min(x))./(max(x)-min(x));                    %NORMALIZE x scale in [0 1]

    if (sum(isinf(yNrm))>0) || sum(isinf(x))>0                   %spacing along curve not possible with infinites
        ti = round(linspace(1,length(x),num_Markers));
    else
        t        = 1:length(x);
        s        = [0 cumsum(sqrt(diff(xNrm).^2+diff(yNrm).^2))];%measures length along the curve
        si       = (0:num_Markers-1)*s(end)/(num_Markers-1);     %equally spaced lengths along the curve
        si(end)  = s(end);                                       %fix last point to be within the curve
        ti       = round(interp1(s,t,si));                       %find x index of markers
    end
else
    error('invalid spacing parameter');
end
%if LockOnMax
    %set one ti on max if found
%    [Mv,idx]   = max(y); idx=idx(1);
%    [mv,idxti] = min(abs(idx-ti));
%    deltati    = ti(idxti)-idx;
%    ti         = max(1,min(ti-deltati,length(y)));
%end
xi = x_t(ti);
yi = y_t(ti);
H3 = line(xi,yi,varargInNoMkNoLn{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc,'LineStyle','none');  %plot markers only
hasbehavior(H3,'legend',0); %prevent to appear in legends!

%% c) once with a visible handle, only the first point, using the complete style you specified
if strcmp(LegendLine,'on')
    H1 = line(xi(1),yi(1),varargInNoMk{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc);
else
    H1 = line(xi(1),yi(1),varargInNoMk{:},'linestyle','none','Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc);
end

%-------------------------------------------------------------
% PARSE FUNCTIONS
%-------------------------------------------------------------
% varargInNoMk = list of property pairs, marker specs removed
% varargInNoMkNoLn = list of property pairs, marker specs and line specs removed
function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin)
lm =[]; ms =[]; mfc=[]; LockOnMax=[]; Spacing=[]; LegendLine=[];
varargInNoMk = {};
varargInNoMkNoLn = {};
arg_index = 1;
while arg_index <= length(varargin)
	arg = varargin{arg_index};
    % extract special params and marker specs from arg list
    if strcmp(arg,'marker') || strcmp(arg,'Marker') || strcmp(arg,'Mk')  || strcmp(arg,'mk')
        lm              = varargin{arg_index+1};
    elseif strcmp(arg,'MarkerSize') || strcmp(arg,'markersize') || strcmp(arg,'Mks')  || strcmp(arg,'mks')
        ms              = varargin{arg_index+1};
    elseif strcmp(arg,'MarkerFaceColor') || strcmp(arg,'markerfacecolor')||strcmp(arg,'MFC')||strcmp(arg,'mfc')
        mfc             = varargin{arg_index+1};
    elseif strcmp(arg,'LockOnMax') || strcmp(arg,'lockonmax')
        LockOnMax       = varargin{arg_index+1};
    elseif strcmp(arg,'Spacing')   || strcmp(arg,'spacing')
        Spacing         = varargin{arg_index+1};
    elseif strcmp(arg,'LegendLine')   || strcmp(arg,'legendline')
        LegendLine      = varargin{arg_index+1};
    else
        % keep other params in arg list for line command
        varargInNoMk    = {varargInNoMk{:},  varargin{arg_index},  varargin{arg_index+1}};
        if ~strcmp(arg,'LineStyle') && ~strcmp(arg,'linestyle')
           % exclude line params for marker only plot
           varargInNoMkNoLn = {varargInNoMkNoLn{:},  varargin{arg_index},  varargin{arg_index+1}};
        end
    end
    arg_index = arg_index + 2;
end
%EXTRA DEFAULTS ARE SET HERE
if isempty(lm),         lm          = 'o'   ; end
if isempty(ms),         ms          = 10    ; end
if isempty(mfc),        mfc         = 'none'; end
if isempty(LockOnMax),  LockOnMax   = 1     ; end
if isempty(Spacing),    Spacing     = 'x'   ; end %%'x' -> marker delta-x constant; 'curve' : spacing constant along the curve length
if isempty(LegendLine), LegendLine  = 'on'  ; end

%-------------------------------------------------------------
% Parse LineSpec string and other arguments
% varargInNoMk     = list of property pairs, marker specs removed
% varargInNoMkNoLn = list of property pairs, marker specs and line specs removed
function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec, extraArgs)
%          b     blue          .     point              -     solid
%          g     green         o     circle             :     dotted
%          r     red           x     x-mark             -.    dashdot
%          c     cyan          +     plus               --    dashed
%          m     magenta       *     star             (none)  no line
%          y     yellow        s     square
%          k     black         d     diamond
%          w     white         v     triangle (down)
%                              ^     triangle (up)
%                              <     triangle (left)
%                              >     triangle (right)
%                              p     pentagram
%                              h     hexagram
varargInNoMk     = {};
varargInNoMkNoLn = {};

foundLine           = false;
stringSearch        = {'-.','--','-',':'};
for ii=1:4
    if strfind(linspec, stringSearch{ii})
        foundLine   = true;
        ls          = stringSearch{ii};
        linspec     = setdiff(linspec,ls);
        break
    end
end
if foundLine
    varargInNoMk    = {varargInNoMk{:},'lineStyle',ls};
else
    varargInNoMk    = {varargInNoMk{:},'lineStyle','-'};
end

if ~isempty(linspec)
    foundCol            = false;
    stringSearch        = {'b','g','r','c','m','y','k','w'};
    for ii=1:8
        if strfind(linspec, stringSearch{ii})
            foundCol    = true;
            colspec     = stringSearch{ii};
            linspec     = setdiff(linspec,colspec);
            break
        end
    end
    if foundCol
        varargInNoMk    = {varargInNoMk{:},'color',colspec};
        varargInNoMkNoLn    = {varargInNoMkNoLn{:},'color',colspec};
    end
end

if ~isempty(linspec)
    foundMk             = false;
    stringSearch        = {'.','o','x','+','*','s','d','v','^','<','>','p','h'};
    for ii=1:13
        if strfind(linspec, stringSearch{ii})
            foundMk     = true;
            mkspec      = stringSearch{ii};
            break
        end
    end
    if foundMk, lm = mkspec; else lm = 'none'; end
else
    lm = 'none';
end

[extraArgs1,unused,lm2,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(extraArgs{:});
if strcmp(lm,'none') && ~strcmp(lm2,'none') %if other marker specified in Property Pairs take that one
    lm = lm2;
end
varargInNoMk       = {varargInNoMk{:},extraArgs1{:}};
varargInNoMkNoLn   = {varargInNoMkNoLn{:},extraArgs1{:}};


function i4vec_transpose_print_test (  )

%*****************************************************************************80
%
%% I4VEC_TRANSPOSE_PRINT_TEST tests I4VEC_TRANSPOSE_PRINT.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 September 2014
%
%  Author:
%
%    John Burkardt
%
  n = 12;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4VEC_TRANSPOSE_PRINT_TEST\n' );
  fprintf ( 1, '  I4VEC_TRANSPOSE_PRINT prints an integer vector\n' );
  fprintf ( 1, '  with 5 entries to a row, and a title.\n' );

  a = i4vec_indicator1 ( n );

  i4vec_print ( n, a, '  Output from I4VEC_PRINT:' );

  i4vec_transpose_print ( n, a, '  My array:  ' );

  return
end


function chrpak_test022 ( )

%*****************************************************************************80
%
%% TEST022 tests I4_TO_HEX_DIGIT and HEX_DIGIT_TO_I4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    31 August 2009.
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST022\n' );
  fprintf ( 1, '  I4_TO_HEX_DIGIT: I4 -> hexadecimal digit\n' );
  fprintf ( 1, '  HEX_DIGIT_TO_I4: hexadecimal digit -> I4.\n' );
  fprintf ( 1, '\n' );

  for i = -2 : 11
    ch = i4_to_hex_digit ( i );
    i2 = hex_digit_to_i4 ( ch );
    fprintf ( 1, '  %8d  "%c"  %8d\n', i, ch, i2 );
  end

  return
end


function range = p02_range ( )

%*****************************************************************************80
%
%% P02_RANGE returns an interval bounding the root for problem 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real RANGE(2), the minimum and maximum values of
%    an interval containing the root.
%
  range(1) = -10.0;
  range(2) = 100.0;

  return
end


function test_num = c8mat_exp_test_num ( )

%*****************************************************************************80
%
%% C8MAT_EXP_TEST_NUM returns the number of matrix exponential tests.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 March 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, integer TEST_NUM, the number of tests.
%
  test_num = 3;

  return
end


function [ a, b ] = p53_lim ( )

%*****************************************************************************80
%
%% P53_LIM returns the integration limits for problem 53.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function [ a, b ] = p19_lim ( )

%*****************************************************************************80
%
%% P19_LIM returns the integration limits for problem 19.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function OUT = NaN2Num(DATA)
% =======================================================================
% Substitute NaN values with 123456789
% =======================================================================
% OUT = Num2NaN(DATA)
% -----------------------------------------------------------------------
% INPUT
%	- DATA: a (m x n) matrix with NaNs
% -----------------------------------------------------------------------
% OUTPUT
%	- OUT: a (m x n) matrix with 123456789 instead of NaNs
% -----------------------------------------------------------------------
% EXAMPLE
%   x = [NaN 2; NaN 4; 5 6; 7 8; 9 10];
%   OUT = NaN2Num(x)
% =======================================================================
% VAR Toolbox 3.0
% Ambrogio Cesa-Bianchi
% ambrogiocesabianchi@gmail.com
% March 2012. Updated November 2020
% -----------------------------------------------------------------------

OUT=DATA;
for i=1:size(DATA,1)
    for j=1:size(DATA,2)
        if isnan(DATA(i,j)) == 1
            OUT(i,j) = 123456789;
        end
    end
end


function p05_story ( )

%*****************************************************************************80
%
%% P05_STORY prints the "story" for problem p05.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Larry Irvine, Samuel Marin, Philip Smith,
%    Constrained Interpolation and Smoothing,
%    Constructive Approximation,
%    Volume 2, Number 1, December 1986, pages 129-151.
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This example is due to Larry Irvine, Samuel Marin and Philip Smith.\n' );
  fprintf ( 1, '  This data can cause problems for interpolation methods.\n' );
  fprintf ( 1, '  There are sudden changes in direction, and at the same time,\n' );
  fprintf ( 1, '  sparsely-placed data.  This can cause an interpolant to overshoot\n' );
  fprintf ( 1, '  the data in a way that seems implausible.\n' );

  return
end


function [ a, b ] = p16_lim ( )

%*****************************************************************************80
%
%% P16_LIM returns the integration limits for problem 16.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function [ a, b ] = p45_lim ( )

%*****************************************************************************80
%
%% P45_LIM returns the integration limits for problem 45.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function [ a, b ] = p11_lim ( )

%*****************************************************************************80
%
%% P11_LIM returns the integration limits for problem 11.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function p04_story ( )

%*****************************************************************************80
%
%% P04_STORY prints the "story" for problem p04.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Larry Irvine, Samuel Marin, Philip Smith,
%    Constrained Interpolation and Smoothing,
%    Constructive Approximation,
%    Volume 2, Number 1, December 1986, pages 129-151.
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  This example is due to Larry Irvine, Samuel Marin and Philip Smith.\n' );
  fprintf ( 1, '  This data can cause problems for interpolation methods.\n' );
  fprintf ( 1, '  There are sudden changes in direction, and at the same time,\n' );
  fprintf ( 1, '  sparsely-placed data.  This can cause an interpolant to overshoot\n' );
  fprintf ( 1, '  the data in a way that seems implausible.\n' );

  return
end


function p04_story ( )

%*****************************************************************************80
%
%% P04_STORY prints the "story" for problem 4.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 August 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    None
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Theoretically, the data is a step, 0 to the left of 5, and 1\n' );
  fprintf ( 1, '  to the right.  To keep things simple, the data is defined\n' );
  fprintf ( 1, '  to be 0 up to 5 - RADIUS, 1/2 at 5, 1 at 5 + RADIUS and beyond,\n' );
  fprintf ( 1, '  with RADIUS set to a "small" value, currently 0.01.\n' );
  fprintf ( 1, '  Some interpolation methods will violently overreact to this jump.\n' );

  return
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% pr01.m %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% function summe=pr01(name,x)
% prints a (0,1) profile of x and returns the number of nonzeros
%
function summe=pr01(name,x)

% check for row or column vector
[m,n]=size(x);row=(m==1);col=(n==1);n=max(m,n);
if ~(row|col), error('x must be a vector'); end;

text=[name,': '];summe=0;
for k=1:n,
  if x(k),
    text=[text,'1'];
    summe=summe+1;
  else
    text=[text,'0'];
  end;
end;
disp([text,'   ',num2str(summe),' nonzeros']);


function [ a, b ] = p40_lim ( )

%*****************************************************************************80
%
%% P40_LIM returns the integration limits for problem 40.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


% PLOTPDFTEX prints a PDF figure for inclusion in LaTeX documents, with
%    LaTeX fonts. It creates a complete pdf-file with annotation of the
%    figure (titles, labels and texts) and graphics (lines,arrows,markers,
%    ...). This function uses the LAPRINT function and makes simply a
%    concatenation of the text part and the graphical part in a single PDF
%    file. It requires:
%
%                  MATLAB        |      OTHER
%               -----------------|----------------------------
%                 laprint.m      |      latex
%                                |      dvips
%                                |      ps2epsi or eps2eps
%                                |      epstopdf
%                                |      GhostScript
%
%    The diference between ps2epsi and eps2eps is that the first is a
%    standard EPS converter, but creates very large file size. The commande
%    eps2eps can be replace by ps2epsi at line 191
%
%    USAGE:
%    ------------------------
%
%    PLOTPDFTEX creates the PDF file of the current graphical figure (CGF)
%    named LaTeXfile.pdf
%
%    PLOTPDFTEX(H) creates the PDF file from the graphical figure with
%    handle H, named LaTeXfile.pdf
%
%    PLOTPDFTEX(H,FILENAME) creates the PDF file from the graphical figure
%    with handle H, named FILENAME.PDF (FILENAME is a character array of
%    the filename, with or without the extension .PDF)
%
%    PLOTPDFTEX(H,FILENAME,[FONTSCALING LINESCALING]) scales the font and
%    line sizes relative to the figure size (values greater than 1 scale
%    up, less than 1 scale down).  If nan, the default of 1 is used.
%
%    PLOTPDFTEX(H,FILENAME,[FONTSCALING LINESCALING],PACKAGES) to adding
%    packages such as fonts, mathfont,...
%    ex: PACKAGES = 'amssymb, times'
%
% See also LAPRINT:
%          http://www.uni-kassel.de/fb16/rat/matlab/laprint/laprintdoc.ps
%
%_______________________________
% Adjusted from PLOTEPSTEX by
% J.C. Olivier                                    09/2007
% http://www.jc-olivier.2007.fr
%
%_______________________________
%
% Emmett Lalish                                   06/2008

function plotpdftex(h,FileName,FontLineSize,Packages)

if nargin >= 3
    fontsize=FontLineSize(1);
    linesize=FontLineSize(2);

    id=find(isnan(FontLineSize));
    if length(find(id==1))==1
        fontsize=1;
    end

    if length(find(id==2))==1
        linesize=1;
    end
end

if nargin < 3
   fontsize=1; linesize=1;
end

if nargin < 2
    FileName='LaTeXfile';
end

if nargin < 1
    h=gcf;
end

TempName = strcat('TEMP',num2str(round(rand*10000))); %Generate random file name

DTI = get(0,'defaulttextinterpreter');   %Backup of the text interpreter
set(0,'defaulttextinterpreter','none');  %Delete the TeX interpreter

id=findstr(FileName,'.');
if ~isempty(id)
    FileName(id:end)=[];
end

if ~exist('laprint.m')
    disp('Laprint M-file does not exist or is not in the MATLAB''s search path.');
    disp('This file can be downloaded at: http://www.mathworks.com/matlabcentral/fileexchange');
    disp('                                                         Try again...');
    return;
end

laprint(h,TempName,'width',12/fontsize,'factor',linesize/fontsize,'scalefonts','off','asonscreen','on'); % Generate the EPS/LaTeX file

disp(sprintf('\n-------------------------------------------------------'));
disp(sprintf('PlotEpsTeX                                      02/2008'));
disp(sprintf('-------------------------------------------------------'));
disp(sprintf('Exporting figure in EPS format, including LaTeX strings'));
disp(sprintf('This function is based on laprint.m:'));
disp(sprintf('http://www.uni-kassel.de/fb16/rat/matlab/laprint/laprintdoc.ps\n'));
%-------------------------------------------------------
% Temporary LaTeX file
%-------------------------------------------------------
fid = fopen(strcat(TempName,'2.tex'),'w');

fprintf(fid,'\\documentclass[11pt, oneside]{article}\n');
fprintf(fid,'\\usepackage{graphicx}\n');
fprintf(fid,'\\usepackage{amsmath}\n');
fprintf(fid,'\\usepackage[T1]{fontenc}\n');
fprintf(fid,'\\usepackage[latin1]{inputenc}\n');
fprintf(fid,'\\usepackage{ae}\n');
fprintf(fid,'\\usepackage{psfrag}\n');
fprintf(fid,'\\usepackage{color}\n');

if nargin==4
    fprintf(fid,'\\usepackage{%s}\n',Packages); % Suplementary packages
end
fprintf(fid,'\\pagestyle{empty}\n');
fprintf(fid,' \n');
fprintf(fid,'\\begin{document}\n');
fprintf(fid,'    \\begin{figure}\n');
fprintf(fid,'        \\centering\n');
fprintf(fid,'        \\input{%s}\n',TempName);
fprintf(fid,'    \\end{figure}\n');
fprintf(fid,' \n');
fprintf(fid,'\\end{document}\n');
fclose(fid);

%-------------------------------------------------------
% LaTeX Command
%-------------------------------------------------------
Str=sprintf('latex --src -interaction=nonstopmode %s2.tex',TempName);
disp(sprintf('\n[LaTeX Command] %s',Str));
[hdos,wdos]=system(Str);

if hdos ~=0
    if isunix
        dos(sprintf('rm %s*',TempName));
    else
        dos(sprintf('del %s*',TempName));
    end
    error('Error %d -- LATEX:\n%s',hdos ,wdos);
    return;
end

%-------------------------------------------------------
% DviPs Command
%-------------------------------------------------------
Str=sprintf('dvips %s2.dvi -o %s2.ps',TempName,TempName);
disp(sprintf('[DVIPS Command] %s',Str));
[hdos,wdos]=system(Str);
if hdos ~=0
    if isunix
        dos(sprintf('rm %s*',TempName));
    else
        dos(sprintf('del %s*',TempName));
    end
    error('Error %d -- DVIPS:\n%s', hdos , wdos);
    return;
end

%-------------------------------------------------------
% eps2eps Command (can be changed with PS2EPSI)
%-------------------------------------------------------
Str = sprintf('eps2eps -dNOCACHE %s2.ps %s.eps',TempName,FileName);
disp(sprintf('[EPS2EPS Command] %s',Str));
[hdos,wdos]=system(Str);
if hdos ~=0
    if isunix
        dos(sprintf('rm %s*',TempName));
    else
        dos(sprintf('del %s*',TempName));
    end
    error('Error %d -- PS2EPSI:\n%s',hdos ,wdos);
    return;
end

%-------------------------------------------------------
% epstopdf Command
%-------------------------------------------------------
Str = sprintf('epstopdf %s.eps',FileName);
disp(sprintf('[EPSTOPDF Command] %s',Str));
[hdos,wdos]=system(Str);
if hdos ~=0
    if isunix
        dos(sprintf('rm %s*',TempName));
        dos(sprintf('rm %s.eps',FileName));
    else
        dos(sprintf('del %s*',TempName));
        dos(sprintf('del %s.eps',FileName));
    end
    error('Error %d -- EPSTOPDF:\n%s',hdos ,wdos);
    return;
end

disp(sprintf('... OK!\nPDF file [%s.pdf] has been created in the current directory\n',FileName));
%-------------------------------------------------------
% Delete all the temporary files
%-------------------------------------------------------
if isunix
    dos(sprintf('rm %s*',TempName));
    dos(sprintf('rm %s.eps',FileName));
else
    dos(sprintf('del %s*',TempName));
    dos(sprintf('del %s.eps',FileName));
end

set(0,'defaulttextinterpreter',DTI);

return;


function c8mat_indicator_test ( )

%*****************************************************************************80
%
%% C8MAT_INDICATOR_TEST tests C8MAT_INDICATOR.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2015
%
%  Author:
%
%    John Burkardt
%
  m = 5;
  n = 3;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'C8MAT_INDICATOR_TEST\n' );
  fprintf ( 1, '  C8MAT_INDICATOR returns the complex indicator matrix.\n' );

  a = c8mat_indicator ( m, n );

  c8mat_print ( m, n, a, '  The indicator matrix:' );

  return
end


function nvar = p01_nvar ( option )

%*****************************************************************************80
%
%% P01_NVAR sets the number of variables for problem 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 September 2008
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer OPTION, the option chosen for this problem.
%    For some problems, several options are available.  At least,
%    OPTION = 1 is always legal.
%
%    Output, integer NVAR, the number of variables.
%
  nvar = 3;

  return
end


function i4_is_odd_test ( )

%*****************************************************************************80
%
%% I4_IS_ODD_TEST tests I4_IS_ODD.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 December 2014
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'I4_IS_ODD_TEST\n' );
  fprintf ( 1, '  I4_IS_ODD reports whether an I4 is odd.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  I     I4_IS_ODD(I)\n' );
  fprintf ( 1, '\n' );

  for i = -2 : 25
    fprintf ( 1, '  %6d  %1d\n', i, i4_is_odd ( i ) );
  end

  return
end


%% Copyright (C) 2014-2019, 2021-2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy 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.
%%
%% This software 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 software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @defun  vpa (@var{x})
%% @defunx vpa (@var{x}, @var{n})
%% Create a variable-precision floating point number.
%%
%% @var{x} can be a string, a sym or a double.  Example:
%% @example
%% @group
%% x = vpa('1/3', 32)
%%   @result{} x = (sym) 0.33333333333333333333333333333333
%% a = sym(1)/3;
%% x = vpa(a, 32)
%%   @result{} x = (sym) 0.33333333333333333333333333333333
%% @end group
%% @end example
%%
%% If @var{n} is omitted it defaults to the current value of
%% @code{digits()}.
%%
%% Be careful when creating a high-precision float from a
%% double as you will generally only get 15 digits:
%% @example
%% @group
%% vpa(1/3)
%%   @result{} (sym) 0.3333333333333333148296162...
%% vpa(sqrt(2));
%% ans^2
%%   @result{} (sym) 2.0000000000000002734323463...
%% @end group
%% @end example
%%
%% For the same reason, passing numbers with decimal points
%% may produce undesirable results:
%% @example
%% @group
%% vpa(0.1)
%%   @result{} (sym) 0.1000000000000000055511151...
%% @end group
%% @end example
%%
%% Instead, enclose the decimal number in a string:
%% @example
%% @group
%% vpa('0.1')
%%   @result{} (sym) 0.10000000000000000000000000000000
%% @end group
%% @end example
%%
%% Very simple expressions can also be enclosed in quotes:
%% @example
%% @group
%% vpa('sqrt(2)')
%%   @result{} (sym) 1.4142135623730950488016887242097
%% @end group
%% @end example
%%
%% But be careful as this can lead to unexpected behaviour, such as
%% low-precision results if the string contains decimal points:
%% @example
%% @group
%% vpa('cos(0.1)')
%%   @print{} warning: string expression involving decimals is
%%   @print{}          dangerous, see "help vpa"...
%%   @result{} ans = (sym) 0.99500416527802...
%% @end group
%% @end example
%%
%% Instead, it is preferrable to use @code{sym} or @code{vpa} on the
%% inner-most parts of your expression:
%% @example
%% @group
%% cos(vpa('0.1'))
%%   @result{} (sym) 0.99500416527802576609556198780387
%% vpa(cos(sym(1)/10))
%%   @result{} (sym) 0.99500416527802576609556198780387
%% @end group
%% @end example
%%
%% @seealso{sym, vpasolve, digits}
%% @end defun

function r = vpa(x, n)

  if (nargin == 1)
    n = digits();
  elseif (nargin ~= 2)
    print_usage ();
  end

  if (isa(x, 'sym'))
    cmd = {
        'x, n = _ins'
        'return sympy.N(x, n),' };
    r = pycall_sympy__ (cmd, x, n);
  elseif (ischar (x))
    x = strtrim (x);
    isfpnum = ...
      ~isempty (regexp (x, '^[-+]*?[\d_]*\.[\d_]*(e[+-]?[\d_]+)?[ij]?$'));
    if (~isfpnum && ~isempty (strfind (x, '.')))
      warning ('OctSymPy:vpa:precisionloss', ...
               'string expression involving decimals is dangerous, see "help vpa"')
    end
    if (isfpnum && any (strcmp (x(end), {'i', 'j'})))
      r = sym (1i)*vpa (x(1:end-1), n);
      return
    end
    if (any (strcmp (x, {'inf', 'Inf', '+inf', '+Inf'})))
      x = 'S.Infinity';
    elseif (strcmp (x, '-inf') || strcmp (x, '-Inf'))
      x = '-S.Infinity';
    elseif (strcmp (x, 'I'))
      x = 'Symbol("I")';
    elseif (any (strcmp (x, {'1i', '1j'})))
      x = 'S.ImaginaryUnit';
    end
    % Want Float if its '2.3' but N if its 'sqrt(2)'
    cmd = {
        'x, n = _ins'
        'try:'
        '    return sympy.Float(x, n),'
        'except ValueError:'
        '    return sympy.N(x, n),' };
    r = pycall_sympy__ (cmd, x, n);
  elseif (isfloat (x) && ~isreal (x))
    r = vpa (real (x), n) + sym (1i)*vpa (imag (x), n);
  elseif (isfloat(x) && isscalar(x) == 1)
    if (isnan (x))
      x = 'S.NaN';
    elseif (isinf (x) && x < 0)
      x = '-S.Infinity';
    elseif (isinf (x))
      x = 'S.Infinity';
    elseif (isequal (x, pi))
      x = 'S.Pi';
    elseif (isequal (x, -pi))
      x = '-S.Pi';
    elseif (isequal (x, exp (1)))
      x = exp (sym (1));
    elseif (isequal (x, -exp (1)))
      x = -exp (sym (1));
    end
    cmd = {
      'x, n = _ins'
      'return sympy.N(x, n)' };
    r = pycall_sympy__ (cmd, x, n);
  elseif (isinteger(x) && isscalar(x) == 1)
    cmd = {
        'x, n = _ins'
        'return sympy.N(x, n),' };
    r = pycall_sympy__ (cmd, x, n);
  elseif (~isscalar(x))
    cmd = { sprintf('return sympy.ZeroMatrix(%d, %d).as_mutable(),', size(x)) };
    r = pycall_sympy__ (cmd);
    for i=1:numel(x)
      r(i) = vpa(x(i), n);
    end
  else
    x
    class(x)
    error('conversion to vpa with those arguments not (yet) supported');
  end

end

%!test
%! a = vpa(0, 4);
%! b = double(a);
%! assert(b == 0)

%!test
%! a = vpa(pi, 4);
%! b = sin(a);
%! assert(abs(double(b)) < 1e-4)

%!test
%! % vpa from double is ok, doesn't warn (c.f., sym(2.3))
%! a = vpa(2.3);
%! assert(true)

%!test
%! % vpa from double not more than 16 digits
%! a = vpa(sqrt(pi), 32);
%! b = sin(a^2);
%! assert(abs(double(b)) > 1e-20)
%! assert(abs(double(b)) < 1e-15)

%!test
%! a = vpa(sym(pi), 32);
%! b = sin(a);
%! assert(abs(double(b)) < 1e-30)

%!test
%! a = vpa(sym(pi), 256);
%! b = sin(a);
%! assert(abs(double(b)) < 1e-256)

%!test
%! % pi str
%! a = vpa('pi', 32);
%! b = sin(a);
%! assert(abs(double(b)) < 1e-32)

%!test
%! % pi str
%! a = vpa('pi', 32);
%! b = vpa(sym('pi'), 32);
%! assert (double (a - b) == 0)

%!test
%! spi = sym(pi);
%! a = vpa(spi, 10);
%! b = double(a);
%! assert(~isAlways(spi == a))

%!test
%! % matrix of sym
%! a = [sym(pi) 0; sym(1)/2 1];
%! b = [pi 0; 0.5 1];
%! c = vpa(a, 6);
%! assert(max(max(abs(double(c)-b))) < 1e-6)

%!test
%! % matrix of double
%! b = [pi 0; 0.5 1];
%! c = vpa(b, 6);
%! assert(max(max(abs(double(c)-b))) < 1e-6)

%!test
%! % integer type
%! a = vpa(int32(6), 64);
%! b = vpa(6, 64);
%! assert (isequal (a, b))

%!test
%! % matrix of int
%! b = int32([pi 0; 6.25 1]);
%! c = vpa(b, 6);
%! assert (isequal (double(c), [3 0; 6 1]))

%!test
%! % can pass pi directly to vpa
%! a = vpa(sym(pi), 128);
%! b = vpa(pi, 128);
%! assert (isequal (a, b))

%!test
%! % if sym does sth special for e so should vpa
%! a = vpa(sym(exp(1)), 64);
%! b = vpa(exp(1), 64);
%! assert (isequal (a, b))

%!test
%! % can pass pi directly to vpa, even in array
%! a = vpa(sym([2 pi]), 128);
%! b = vpa([2 pi], 128);
%! assert (isequal (a, b))

%!test
%! % can pass i directly to vpa
%! a = vpa(sym(i));
%! b = vpa(i);

%!test
%! % 'i' and 'I' just make vars
%! a = vpa(sym(1i));
%! b = vpa('i');
%! c = vpa('I');
%! assert (~isequal (a, b))
%! assert (~isequal (a, c))

%!test
%! % '1i' and '1j' strings
%! a = vpa(sym(1i));
%! b = vpa('1i');
%! c = vpa('1j');
%! assert (isequal (a, b))
%! assert (isequal (a, c))

%!test
%! % Issue #868, precision loss on '0.33j'
%! a = vpa('0.33j', 40);
%! b = vpa('0.33i', 40);
%! assert (double (abs (imag (a)*100/33) - 1) < 1e-39)
%! assert (isequal (a, b))

%!test
%! % inf/-inf do not become symbol('inf')
%! S = {'oo', '-oo', 'inf', 'Inf', '-inf', '+inf'};
%! for j = 1:length(S)
%!   a = vpa(S{j});
%!   b = vpa(sym(S{j}));
%!   assert (isequal (a, b))
%! end

%!test
%! a = vpa('2.3', 20);
%! s = strtrim(disp(a, 'flat'));
%! assert (strcmp (s, '2.3000000000000000000'))

%!test
%! % these should *not* be the same
%! a = vpa(2.3, 40);
%! b = vpa('2.3', 40);
%! sa = sympy (a);
%! sb = sympy (b);
%! assert (~isequal (a, b))
%! assert (abs(double(a - b)) > 1e-20)
%! assert (abs(double(a - b)) < 1e-15)
%! assert (~strcmp(sa, sb))

%!test
%! % these should *not* be the same
%! x = vpa('1/3', 32);
%! y = vpa(sym(1)/3, 32);
%! z = vpa(1/3, 32);
%! assert (isequal (x, y))
%! assert (~isequal (x, z))

%!test
%! % big integers
%! a = int64(12345678);
%! a = a*a;
%! b = vpa(a);
%! c = vpa('152415765279684');
%! assert (isequal (b, c))

%!test
%! % big integers (workaround poor num2str, works in 4.0?)
%! a = int64(1234567891);  a = a*a;
%! b = vpa(a);
%! c = vpa('1524157877488187881');
%! assert (isequal (b, c))

%!warning <dangerous> vpa ('sqrt(2.0)');

%!warning <dangerous>
%! if (pycall_sympy__ ('return Version(spver) > Version("1.4")'))
%! a = vpa('2**0.5');
%! b = vpa(sqrt(sym(2)));
%! assert (isequal (a, b))
%! else
%! warning('dangerous')  % fake it until we drop 1.4
%! end

%!test
%! a = vpa('2.3e1');
%! b = vpa(' 2.3e+1 ');
%! assert (isequal (a, b))
%! a = vpa('21e-1');
%! b = vpa('2.1');
%! assert (isequal (a, b))

%!test
%! % Issue #859, operations on immutable matrices
%! x = vpa (sym ([1 2]));
%! % If vpa no longer makes an ImmutableDenseMatrix,
%! % may need to adjust or remove this test.
%! assert (~ isempty (strfind (sympy (x), 'Immutable')))
%! y = sin(x);
%! y2 = [sin(vpa(sym(1))) sin(vpa(sym(2)))];
%! assert (isequal (y, y2))


function [ a, b ] = p21_lim ( )

%*****************************************************************************80
%
%% P21_LIM returns the integration limits for problem 21.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function [out1, out2] = templateFunction(arg1, arg2, arg3)
% This function does this and that
%
% USAGE:
%
%   [out1, out2] = templateFunction(arg1, arg2, arg3)
%
% INPUTS:
%    arg1: a short description for this argument
%    arg2: another argument
%
% OPTIONAL INPUT:
%    arg3: optional argument
%
% OUTPUT:
%    out1: the product of arg1 and arg2
%
% OPTIONAL OUTPUT:
%    out2: the product of arg1, arg2 and arg3
%
% EXAMPLE:
%
%   [out1, out2] = templateFunction(1, 2, 3);
%   >> out1 = 2
%   >> out2 = 6
%
% .. Authors: - myself
%             - laurent
%
if nargin < 3
    arg3 = 1;
end

out1 = arg1 * arg2;

if nargout > 1
    out2 = out1 * arg3;
end


function range = p15_range ( )

%*****************************************************************************80
%
%% P15_RANGE returns an interval bounding the root for problem 15.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    06 May 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real RANGE(2), the minimum and maximum values of
%    an interval containing the root.
%
  range(1) = - 10.0;
  range(2) =   10.0;

  return
end


function [ a, b ] = p05_lim ( )

%*****************************************************************************80
%
%% P05_LIM returns the integration limits for problem 5.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 January 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A(2), B(2), the lower and upper limits of integration.
%
  a(1:2) = 0.0;
  b(1:2) = 1.0;

  return
end


function a = r8mat_diag_set_vector ( n, a, v )

%*****************************************************************************80
%
%% R8MAT_DIAG_SET_VECTOR sets the diagonal of a matrix to a vector.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 April 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of rows and columns of the matrix.
%
%    Input, real A(N,N), the matrix.
%
%    Input, real V(N), the vector to be assigned to the
%    diagonal of A.
%
%    Output, real A(N,N), the modified matrix.
%
  for i = 1 : n
    a(i,i) = v(i);
  end

  return
end


function p = pshift ( p, x0, y0 )

%*****************************************************************************80
%
%% PSHIFT shifts a set of points by a given increment.
%
%  Licensing:
%
%    (C) 2004 Per-Olof Persson.
%    See COPYRIGHT.TXT for details.
%
%  Reference:
%
%    Per-Olof Persson and Gilbert Strang,
%    A Simple Mesh Generator in MATLAB,
%    SIAM Review,
%    Volume 46, Number 2, June 2004, pages 329-345.
%
%  Parameters:
%
%    Input/output, real P(NP,2), a set of points to be shifted.
%
%    Input, real X0, Y0, the X and Y increments to be added to each point.
%
  p(:,1) = p(:,1) + x0;
  p(:,2) = p(:,2) + y0;

  return
end


function [ a, b ] = p01_lim ( )

%*****************************************************************************80
%
%% P01_LIM returns the integration limits for problem 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    17 January 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A(2), B(2), the lower and upper limits of integration.
%
  a(1:2) = 0.0;
  b(1:2) = 1.0;

  return
end


function plotData(x, y)
%PLOTDATA Plots the data points x and y into a new figure
%   PLOTDATA(x,y) plots the data points and gives the figure axes labels of
%   population and profit.

% ====================== YOUR CODE HERE ======================
% Instructions: Plot the training data into a figure using the
%               "figure" and "plot" commands. Set the axes labels using
%               the "xlabel" and "ylabel" commands. Assume the
%               population and revenue data have been passed in
%               as the x and y arguments of this function.
%
% Hint: You can use the 'rx' option with plot to have the markers
%       appear as red crosses. Furthermore, you can make the
%       markers larger by using plot(..., 'rx', 'MarkerSize', 10);

figure; % open a new figure window

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

end


function title = p01_title ( )

%*****************************************************************************80
%
%% P01_TITLE returns a title for problem 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 February 2002
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, string TITLE, a title for the problem.
%
  title = 'Simple quadratic, (x-2)^2+1.';

  return
end


%CCODEFUNCTIONSTRING Converts a symbolic expression into a C-code function
%
% [FUNSTR, HDRSTR] = ccodefunctionstring(SYMEXPR, ARGLIST) returns a string
% representing a C-code implementation of a symbolic expression SYMEXPR.
% The C-code implementation has a signature of the form:
%
%         void funname(double[][n_o] out, const double in1,
%           const double* in2, const double[][n_i] in3);
%
% depending on the number of inputs to the function as well as the
% dimensionality of the inputs (n_i) and the output (n_o).
% The whole C-code implementation is returned in FUNSTR, while HDRSTR
% contains just the signature ending with a semi-colon (for the use in
% header files).
%
% Options::
% 'funname',name    Specify the name of the generated C-function. If
%                   this optional argument is omitted, the variable name
%                   of the first input argument is used, if possible.
% 'output',outVar   Defines the identifier of the output variable in the C-function.
% 'vars',varCells   The inputs to the C-code function must be defined as a cell array. The
%                   elements of this cell array contain the symbolic variables required to
%                   compute the output. The elements may be scalars, vectors or matrices
%                   symbolic variables. The C-function prototype will be composed accoringly
%                   as exemplified above.
% 'flag',sig        Specifies if function signature only is generated, default (false).
%
% Example::
%          % Create symbolic variables
%          syms q1 q2 q3
%
%          Q = [q1 q2 q3];
%          % Create symbolic expression
%          myrot = rotz(q3)*roty(q2)*rotx(q1)
%
%          % Generate C-function string
%          [funstr, hdrstr] = ccodefunctionstring(myrot,'output','foo', ...
%          'vars',{Q},'funname','rotate_xyz')
%
% Notes::
% - The function wraps around the built-in Matlab function 'ccode'. It does
%   not check for proper C syntax. You must take care of proper
%   dimensionality of inputs and outputs with respect to your symbolic
%   expression on your own. Otherwise the generated C-function may not
%   compile as desired.
%
% Author::
%  Joern Malzahn, (joern.malzahn@tu-dortmund.de)
%
% See also ccode, matlabFunction.

% Copyright (C) 2012-2018, by Joern Malzahn
%
% This file is part of The Robotics Toolbox for MATLAB (RTB).
%
% RTB is free software: 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.
%
% RTB 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.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB.  If not, see <http://www.gnu.org/licenses/>.
%
% http://www.petercorke.com

function [funstr hdrstr] = ccodefunctionstring(f,varargin)

% option defaults
opt.funname = inputname(1);
opt.output{1} = zeros(size(f));
opt.outputName{1} = inputname(1);
opt.flag = 0;

if isempty(opt.outputName{1})
    opt.outputName{1} = 'myout';
end
opt.vars = {};

% tb_optparse is not applicable here,
% since handling cell inputs and extracting input variable names is
% required.
% Thus, scan varargin manually:
if mod(nargin,2)==0
    error('CodeGenerator:codefunctionstring:wrongArgumentList',...
        'Wrong number of elements in the argument list.');
end
for iArg = 1:2:nargin-1
    switch lower(varargin{iArg})
        case 'funname'
            opt.funname = varargin{iArg+1};
        case 'output'
            if ~isempty(varargin{iArg+1})
                opt.outputName{1} = varargin{iArg+1};
            end
        case 'vars'
            opt.vars = varargin{iArg+1};
        case 'flag'
            opt.flag = varargin{iArg+1};
        otherwise
            error('ccodefunctionstring:unknownArgument',...
                ['Argument ',inputname(iArg),' unknown.']);
    end
end

nOut = numel(opt.output);
nIn = numel(opt.vars);

%% Function signature
funstr = sprintf('void %s(', opt.funname);
initstr = '';

% outputs
for iOut = 1:nOut
    tmpOutName = opt.outputName{iOut};
    tmpOut = opt.output{iOut};

    if ~isscalar(tmpOut);
        funstr = [funstr, sprintf('double %s[][%u]', tmpOutName, size(tmpOut,1) ) ];
        for iRow = 1:size(tmpOut,1)
            for iCol = 1:size(tmpOut,2)
                initstr = sprintf(' %s %s[%u][%u]=0;\n',initstr,tmpOutName,iCol-1,iRow-1);
            end
        end
    else
        funstr = [funstr, sprintf('double %s', tmpOutName ) ];
    end

    % separate argument list by commas
    if ( iOut ~= nOut ) || ( nIn > 0 )
        funstr = [funstr,', '];
    end

end

% inputs
for iIn = 1:nIn
    tmpInName = ['input',num2str(iIn)];%opt.varsName{iIn};
    tmpIn = opt.vars{iIn};

    % treat different dimensionality of input variables
    if isscalar(tmpIn)
        funstr = [funstr, sprintf('const double %s', tmpInName ) ];
    elseif isvector(tmpIn)
        funstr = [funstr, sprintf('const double* %s', tmpInName ) ];
    elseif ismatrix(tmpIn)
        funstr = [funstr, sprintf('const double %s[][%u]', tmpInName, size(tmpIn,2) ) ];
    else
        error('ccodefunctionstring:UnsupportedOutputType', 'Unsupported datatype for %s', tmpOutName)
    end

    % separate argument list by commas
    if ( iIn ~= nIn )
        funstr = [funstr,', '];
    end

end
funstr = [funstr,sprintf('%s', ')')];

% finalize signature for the use in header files
if nargout > 1
    hdrstr = [funstr,sprintf('%s', ';')];
end
if opt.flag
    return;         %% STOP IF FLAG == TRUE
end

% finalize signature for use in function definition
funstr = [funstr,sprintf('%s', '{')];
funstr = sprintf('%s\n%s',funstr,sprintf('%s', ' ') ); % empty line

%% Function body
% input paramter expansion
for iIn = 1:nIn
    tmpInName = ['input',num2str(iIn)];%opt.varsName{iIn};
    tmpIn = opt.vars{iIn};

    % for scalars
    %   -> do nothing

    % for vectors
    if ~isscalar(tmpIn) && isvector(tmpIn)
        nEl = numel(tmpIn);
        for iEl = 1:nEl
            funstr = sprintf('%s\n%s',...
                funstr,...
                sprintf('  double %s = %s[%u];', char(tmpIn(iEl)), tmpInName,iEl-1 ));
        end

        % for matrices
    elseif ~isscalar(tmpIn) && ~isvector(tmpIn) && ismatrix(tmpIn)
        nRow = size(tmpIn,1);
        nCol = size(tmpIn,2);
        for iRow = 1:nRow
            for iCol = 1:nCol

                funstr = sprintf('%s\n%s',...
                    funstr,...
                    sprintf('  double %s%u%u = %s[%u][%u];', char(tmpIn(iRow,iCol)), iRow, iCol, tmpInName{iIn},iRow-1,iCol-1 ));
            end
        end
    end

end

funstr = sprintf('%s\n%s',...
    funstr,...
    sprintf('%s', ' ') );
funstr = sprintf('%s\n%s',...
    funstr,...
    sprintf('%s\n\n', initstr) );

% Actual code
% use f.' here, because of column/row indexing in C
codestr = '';
if ~isequal(f, sym(zeros(size(f))))
    eval([opt.outputName{1}, ' = f.''; codestr = ccode(',opt.outputName{1},');'])
end

if isscalar(f)
    % in the case of scalar expressions the resulting ccode always
    % begins with '  t0'. Replace that with the desired name.
    codestr = strrep(codestr,'t0',opt.outputName{1});
end

funstr = sprintf('%s\n%s',...
    funstr,...
    codestr );

funstr = sprintf('%s\n%s',...
    funstr,sprintf('%s', '}') );
funstr = sprintf('%s\n%s',...
    funstr,sprintf('%s', ' ') ); % empty line


function v = vec( x )

% VEC   Vectorize.
%    VEC(X), where X is a vector, matrix, or N-D array, returns a column vector
%    containing all of the elements of X; i.e., VEC(X)=X(:).

v = reshape( x, numel( x ), 1 );

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


function [mbar] = hPa2mbar(hPa)
% Convert pressure from hectopascals to millibars.
% They're the same!
% Chad Greene 2012
mbar = hPa;


function [ a, b ] = p51_lim ( )

%*****************************************************************************80
%
%% P51_LIM returns the integration limits for problem 51.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real A, B, the limits of integration.
%
  a = 0.0;
  b = 1.0;

  return
end


function ch = digit_oct_to_ch ( i )

%*****************************************************************************80
%
%% DIGIT_OCT_TO_CH returns the character representation of an octal digit.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 April 2011
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer I, the integer, between 0 and 7.
%
%    Output, character CH, the octal representation of the integer.
%
  if ( 0 <= i && i <= 7 )
    ch = char ( '0' + i );
  else
    ch = '?';
  end

  return
end