function r8poly_print ( m, a, title )

%*****************************************************************************80
%
%% R8POLY_PRINT prints out a polynomial.
%
%  Discussion:
%
%    The power sum form is:
%
%      p(x) = a(1) + a(2) * x + ... + a(m-1) * x^(m-1) + a(m) * x^(m-1)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 February 2015
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the nominal degree of the polynomial.
%
%    Input, real A(1:M+1), the polynomial coefficients.
%    A(1) is the constant term and
%    A(M+1) is the coefficient of X^(M).
%
%    Input, string TITLE, a title.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, '%s\n', title );
  fprintf ( 1, '\n' );

  if ( a(m+1) < 0.0 )
    plus_minus = '-';
  else
    plus_minus = ' ';
  end

  mag = abs ( a(m+1) );

  if ( 3 <= m + 1 )
    fprintf ( 1, '  p(x) = %c%14g * x^%d\n', plus_minus, mag, m );
  elseif ( m + 1 == 2 )
    fprintf ( 1, '  p(x) = %c%14g * x\n', plus_minus, mag );
  elseif ( m + 1 == 1 )
    fprintf ( 1, '  p(x) = %c%14g\n', plus_minus, mag );
  end

  for i = m : -1 : 1

    if ( a(i) < 0.0 )
      plus_minus = '-';
    else
      plus_minus = '+';
    end

    mag = abs ( a(i) );

    if ( mag ~= 0.0 )

      if ( 3 <= i )
        fprintf ( 1, '         %c%14g * x^%d\n', plus_minus, mag, i-1 );
      elseif ( i == 2 )
        fprintf ( 1, '         %c%14g * x\n', plus_minus, mag );
      elseif ( i == 1 )
        fprintf ( 1, '         %c%14g\n', plus_minus, mag );
      end
    end

  end

  return
end


function hermite_poly_phys_values_test ( )

%*****************************************************************************80
%
%% HERMITE_POLY_PHYS_VALUES_TEST demonstrates the use of HERMITE_POLY_PHYS_VALUES.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    13 February 2012
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'HERMITE_POLY_PHYS_VALUES_TEST:\n' );
  fprintf ( 1, '  HERMITE_POLY_PHYS_VALUES stores values of\n' );
  fprintf ( 1, '  the physicist''s Hermite polynomials.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '     N      X            H(N,X)\n' );
  fprintf ( 1, '\n' );

  n_data = 0;

  while ( 1 )

    [ n_data, n, x, fx ] = hermite_poly_phys_values ( n_data );

    if ( n_data == 0 )
      break
    end

    fprintf ( 1, '  %4d  %12f  %24.16e\n', n, x, fx );

  end

  return
end


function s = logsumexp(a, dim)
% Returns log(sum(exp(a),dim)) while avoiding numerical underflow.
% Default is dim = 1 (columns).
% logsumexp(a, 2) will sum across rows instead of columns.
% Unlike matlab's "sum", it will not switch the summing direction
% if you provide a row vector.

% Written by Tom Minka
% (c) Microsoft Corporation. All rights reserved.

if nargin < 2
  dim = 1;
end

% subtract the largest in each column
[y, i] = max(a,[],dim);
dims = ones(1,ndims(a));
dims(dim) = size(a,dim);
a = a - repmat(y, dims);
s = y + log(sum(exp(a),dim));
i = find(~finite(y));
if ~isempty(i)
  s(i) = y(i);
end


function vrot=givapp(c,s,vin,k)
%givapp   apply a sequence of Givens rotations
%   input
%          c, s      vectors of length k-1 defining rotations
%          vin       vector of length k to which rotations are applied
%          k         k-1 = number of rotations
%   output
%          tranformed vector after rotations are applied
% called by gmres_r
%   IFISS function: HCE; 15 March 2005.

%
%  C. T. Kelley, July 10, 1994
%Copyright 1994 C. T. Kelley.
%Reproduced and distributed with permission of the copyright holder.
%
% This code comes with no guarantee or warranty of any kind.
%
%  function vrot=givapp(c, s, vin, k)
%
vrot=vin;
for i=1:k
    w1=c(i)*vrot(i)-s(i)*vrot(i+1);        % Change on next line, 6/3/97
    w2=s(i)*vrot(i)+conj(c(i))*vrot(i+1);  % w2=s(i)*vrot(i)+c(i)*vrot(i+1);
    vrot(i:i+1)=[w1,w2];
end


classdef CEC2017_F20 < PROBLEM
% <single> <real> <constrained>
% CEC'2017 constrained optimization benchmark problem

%------------------------------- Reference --------------------------------
% G. Wu, R. Mallipeddi, and P. N. Suganthan, Problem definitions and
% evaluation criteria for the CEC 2017 competition on constrained real-
% parameter optimization, National University of Defense Technology, China,
% 2016.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    properties
        O;  % Optimal decision vector
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            CallStack = dbstack('-completenames');
            load(fullfile(fileparts(CallStack(1).file),'CEC2017.mat'),'Data');
            obj.O = Data{12}.o;
            obj.M = 1;
            if isempty(obj.D); obj.D = 10; end
            obj.D = min(obj.D,length(obj.O));
            obj.lower    = zeros(1,obj.D) - 100;
            obj.upper    = zeros(1,obj.D) + 100;
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(obj,PopDec)
            Y = PopDec - repmat(obj.O(1:size(PopDec,2)),size(PopDec,1),1);
            Y = Y.^2;
            PopObj = sum(0.5+(sin(sqrt(Y(:,1:end-1)+Y(:,2:end))).^2-0.5)./(1+0.001*sqrt(Y(:,1:end-1)+Y(:,2:end))).^2,2) + ...
                     0.5+(sin(sqrt(Y(:,end)+Y(:,1))).^2-0.5)./(1+0.001*sqrt(Y(:,end)+Y(:,1))).^2;
        end
        %% Calculate constraint violations
        function PopCon = CalCon(obj,PopDec)
            Y = PopDec - repmat(obj.O(1:size(PopDec,2)),size(PopDec,1),1);
            Y = sum(Y,2);
            PopCon(:,1) = cos(Y).^2 - 0.25*cos(Y) - 0.125;
            PopCon(:,2) = exp(cos(Y)) - exp(0.25);
        end
    end
end


% Chapter 8 - Planar Systems.
% Program_8c - Phase Portrait of a Nonlinear System (Fig. 8.12).
% Copyright Birkhauser 2013. Stephen Lynch.

% Phase portrait of a nonlinear system of ODE's.
% IMPORTANT - Program_8a is vectorfield.m.
clear
% sys=inline('[x(2);x(1)*(1-(x(1))^2)+x(2)]','t', 'x');
sys = @(t,x) [x(2);x(1)*(1-(x(1))^2)+x(2)];
vectorfield(sys,-3:.5:3,-3:.5:3);
     hold on
     sep=1;
     for x0=-3:sep:3
         for y0=-3:sep:3
            [ts,xs] = ode45(sys,[0 6],[x0 y0]);
            plot(xs(:,1),xs(:,2))
         end
     end
     for x0=-3:sep:3
         for y0=-3:sep:3
            [ts,xs] = ode45(sys,[0 -6],[x0 y0]);
            plot(xs(:,1),xs(:,2))
         end
     end
     hold off
axis([-3 3 -3 3])
fsize=15;
set(gca,'XTick',-3:1:3,'FontSize',fsize)
set(gca,'YTick',-3:1:3,'FontSize',fsize)
xlabel('x(t)','FontSize',fsize)
ylabel('y(t)','FontSize',fsize)
hold off

% End of Program_8c.


classdef OmoriModel < int32
    enumeration
        pck   (1) % 3 free parameters: p, c , k      % Modified Omori law (pck)
        pckk  (2) % 4 free parameters: p, c , k1, k2 % MOL with secondary aftershock (pckk)
        ppckk (3) % 5 free parameters: p1,p2,c,k1,k2 % MOL with secondary aftershock
        ppcckk(4) % 6 free parameters: p1,p2,c1, c2,k1,k2 % MOL with secondary aftershock
    end

    methods(Static)
        function cm = doForecast(nMod, t, p_1, c_1, k_1, t_break, k_2, p_2, c_2) % notice funky order!
            % log likelyhood
            %   where p = pvalues as n x 1
            %   where c = cvalues as n x 1
            %   where k = kvalues as n x 1
            %   where t = amount of time after the main shock, as m x 1 duration
            %
            %   returns an n x m matrix of values
            %
            % each row represents ONE time.
            % each column represents one itteration of p,c, and k
            %
            %  for scalar p,c,k, this would return a single row of values. one for each time.
            %  for scalar t, this would returna  single column of values.
            %
            %  p1t1   p2t1  p3t1     params ->
            %  p1t2   p2t2  p3t2
            %  p1t3   p2t3  p3t3
            %  p1t4   p2t4  p3t4
            %
            %  time
            %    |
            %    v

            assert(isrow(p_1) && isrow(c_1) && isrow(k_1) , 'All p,c,k input values should be rows');
            assert(all(numel(p_1) == [ numel(k_1), numel(c_1)]),'p, c, and k values should have same length');
            assert(isvector(t), 'time should be a vector');
            if isduration(t)
                t=days(t);
            end
            if ~iscolumn(t)
                t=t';
            end

            cm = nan(numel(t),numel(p_1));
            sz=size(cm);
            switch nMod
                case OmoriModel.pck
                    % deal with non infinite solutions first
                    idx = p_1 ~= 1;
                    c=c_1(idx);
                    k=k_1(idx);
                    p=p_1(idx);
                    cm(:,idx) = k ./ (p-1) .* (c .^ (1-p)-(t +c).^ (1-p));

                    c=c_1(~idx);
                    k=k_1(~idx);
                    p=[];
                    cm(:,~idx) = k .* log(t ./ c + 1);

                case {OmoriModel.pckk, OmoriModel.ppckk, OmoriModel.ppcckk}

                    assert(isrow(p_2) && isrow(c_2) && isrow(k_2) , 'All p2,c2,k2 input values should be rows');
                    assert(all(numel(p_1) == [ numel(p_2) numel(k_2), numel(c_2)]),'pn, cn, and kn values should have same length');
                    assert(isscalar(t_break));
                    if isduration(t_break)
                        t_break=days(t_break);
                    end

                    isafter = t >= t_break;
                    cm(~isafter,:) =  OmoriModel.doForecast(OmoriModel.pck, t(~isafter), p_1, c_1, k_1);

                    idx = p_1 ~= 1 & p_2 ~= 1;
                    if any(idx)
                        c1 = c_1(idx);
                        c2 = c_2(idx);
                        p1 = p_1(idx);
                        p2 = p_2(idx);
                        k1 = k_1(idx);
                        k2 = k_2(idx);
                        cm(isafter,idx) = k1./(p1-1) .* (c1.^(1-p1)-(t(isafter)+c1).^(1-p1)) + k2./(p2-1).*(c2.^(1-p2)-(t(isafter)-t_break + c2).^(1-p2));
                    end

                    idx = p_1 ~= 1 & p_2 == 1;
                    if any(idx)
                        c1 = c_1(idx);
                        c2 = c_2(idx);
                        p1 = p_1(idx);
                        p2 = [];
                        k1 = k_1(idx);
                        k2 = k_2(idx);
                        cm(isafter,idx) = k1./(p1-1) .* (c1.^(1-p1)-(t(isafter)+c1).^(1-p1)) + k2 .* log((t(isafter)-t_break)./c2+1);
                    end

                    idx = p_1 == 1 & p_2 ~= 1;
                    if any(idx)
                        c1 = c_1(idx);
                        c2 = c_2(idx);
                        p1 = [];
                        p2 = p_2(idx);
                        k1 = k_1(idx);
                        k2 = k_2(idx);
                        cm(isafter,idx) =k1.*log(t(isafter)./c1+1) + k2./(p2-1).*(c2.^(1-p2)-(t(isafter)-t_break+c2).^(1-p2));
                    end

                    idx = p_1 == 1 & p_2 == 1;
                    if any(idx)
                        c1 = c_1(idx);
                        c2 = c_2(idx);
                        p1 = [];
                        p2 = [];
                        k1 = k_1(idx);
                        k2 = k_2(idx);
                        cm(isafter,idx) = k1.*log(t(isafter)./c1+1) + k2.*log((t(isafter)-t_break)./c2+1);
                    end

            end
            assert(isequal(size(cm),sz)); % make sure sizes are as expected
        end
    end
end


% m-file which generates data from a simple system with a localized
% nonlinearity and processes it using RLM's zeroing algorithm.
%
% Matt Allen, June 27, 2005
% MSA: Major Update - Nov, 2005 - changed to two arbitrary subsystems.
%
clear all; close all;

% Set up system parameters
% m1 = 1; m2 = 1; m3 = 1; m4 = 1; m5 = 1;
    M1 = eye(5);
    M2 = 0.1*eye(2); % Subsystem is about 10% the weight of normal system.

    kall = 1e6;
    k1 = kall; k2 = kall; k3 = kall; k4 = kall; k5 = kall; k6 = kall; kat = kall;
    K1 = [k1, -k1, 0, 0, 0; % System 1
        -k1, k1+k2, -k2, 0, 0
        0, -k2, k2+k3, -k3, 0;
        0, 0, -k3, k3+k4, -k4;
        0, 0, 0, -k4, k4];
    Ns1 = 5; Ns2 = 2; Ntot = 7;
    K2 = [k5, -k5; % System 2 - attached subsystem - dof's
        -k5, k5];
    Mtot = [M1, zeros(size(M1,1),size(M2,2));
        zeros(size(M2,1),size(M1,2)), M2];
    Ktot = [K1, zeros(size(K1,1),size(K2,2));
        zeros(size(K2,1),size(K1,2)), K2];
    % Specify how systems are connected
    at_ns = [2,6]; % attachment happens between this pair of nodes.
    fext_ns = 5; % Node at which external force is applied
    fnl_vec = zeros(Ntot,1); fnl_vec(at_ns(1)) = -1; fnl_vec(at_ns(2)) = 1;
    fext_vec = zeros(Ntot,1); fext_vec(fext_ns(1)) = 1;
    dnodes = [1:Ntot];
    vnodes = [(Ntot+1):(Ntot*2)];

    % Damping Matrix
    cfactk = 0.00003; % multiplied by K to get damping.
    cfactm = 8; % Multiplied by M to get damping
    % for k = 1:5; eval(['c',num2str(k),' = cfact*k',num2str(k),';']); end
    C1 = cfactk*K1 + cfactm*M1;
    C2 = cfactk*K2 + cfactm*M2; % proportional damping
    Ctot = [C1, zeros(size(C1,1),size(C2,2));
        zeros(size(C2,1),size(C1,2)), C2];

    % Linearized System Analysis %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % add a linear spring between attachment nodes
        Mlin = Mtot;
        Klin = Ktot;
        Klin(at_ns,at_ns) = Klin(at_ns,at_ns) + kat*[1, -1; -1, 1];
        % Linear Damping matrix:
        Clin = Ctot;
        Clin(at_ns,at_ns) = Clin(at_ns,at_ns) + cfactk*kat*[1, -1; -1, 1];

    % State Space Eigenanalysis
    Slin = [Clin, Mlin; Mlin, zeros(size(Mlin))];
    Rlin = [-Klin, zeros(size(Mlin));
        zeros(size(Mlin)), Mlin];
    Alin = (Slin\Rlin);
    [Philin,lamlin] = eig(Alin);
    lamlin = diag(lamlin);
    [junk,sind] = sort(abs(lamlin) - 0.001*min(abs(lamlin))*(imag(lamlin) > 0));
    lamlin = lamlin(sind);
    Philin = Philin(:,sind);

%         % Plot Mode Shapes
%         figure(1)
%         hls = plot([1:Ntot], imag(Philin(1:Ntot,1:2:end ))); grid on;
%         legend(hls, num2str([1:Ntot].'));
%         xlabel('X-coordinate');
%         ylabel('Im\{Mode Shape\}');

    wns = abs(lamlin);
    fns = wns/2/pi;
    zts = -real(lamlin)./abs(lamlin);
    disp('Natural Frequencies:, Damping Ratios:');
    [fns, zts]
%     DispFnZt(lamlin) - replace 2 lines abouve with this if you have the EMA Functions toolbox

    % Nonlinear Parameters
    NLType = 'bang'
    if strcmp(NLType,'bang');
        % Bang (Contact) Nonlinearity
        delcont = 1e-3;
        k4mult = 20; % Factor by which k4 increases: k4_contact = k4*k4mult
        c4mult = 1; % Factor by which c4 increases: c4_contact = c4*c4mult
    elseif strcmp(NLType,'cubic');
        % Cubic Spring
        katnl = 1e8;
    else
        error('NLType not recognized');
    end
    % Force paramters
        % length of half-sine force pulse
        % This is normalized in the EOM to unit area and multiplied by Afnl
        tfp = 1e-4;
        Afnl = 4e9;

    % Which Response to Use in evaluating Nonlinearity (i.e. x1, x2, x3..?)
    respind = 6;

    % Number of numerical derivatives to evaluate.  This M-file simulates
    % the displacement response of the 5-DOF system.  To simulate the
    % measurement of the velocity or acceleration response, the
    % displacement response is differentiated using finite differences
    % (i.e. Matlab's 'diff' command.)  This parameter sets the number of
    % derivatives to perform:
    nders = 2;
        % nders = 0; => use displacement
        % nders = 1; => use velocity
        % nders = 2; => use acceleration

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Put all of this in a structure for the EOM
global eom
S = whos;
for k = 1:length(S)
    eval(['eom.',S(k).name,' = ',S(k).name,';']);
end

    % Compute TF of Linearized System
    F = zeros(Ntot,1); F(fext_ns) = 1;
    wlin = [1:1:500]*2*pi;
    Halin = zeros(Ntot,length(wlin));
    for k = 1:length(wlin)
        Halin(:,k) = wlin(k).^2*([Mlin*-wlin(k).^2 + Clin*i*wlin(k) + Klin]\F);
    end
    Halin = Halin.';

%     figure(2)
%     semilogy(wlin/2/pi,abs(Halin)); grid on;
%     xlabel('Frequency (Hz)')
%     ylabel('H_{ACCEL}(\omega)');
%     for k = 1:Ntot; leg_txt{k} = ['H_{',num2str(k),',5}']; end
%     legend(leg_txt);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Nonlinear Simulation
% Compute sample rate and time
    elas_modes = find(imag(lamlin) > 0);
    dt = (5*2*max(fns(elas_modes)))^-1;
    Tmin = log(0.001)/(-min(abs(real(lamlin(elas_modes)))));
    N = 2^ceil(log2(Tmin/dt));

    ts = [0:dt:(N-1)*dt].';

% Specify initial time step so the solver doesn't miss the pulse:
    odeopts = odeset('InitialStep',tfp/10,'AbsTol',1e-9);

    % [ts_ode,hnl] = ode45(@nldetect_anex2_v1_eom,ts,zeros(10,1),odeopts,eom);

% Alternate Calling form:
sol = ode45(@nldt_bng_cub_v2_eom,[ts(1),ts(end)],zeros(Ntot*2,1),odeopts);
    [hnl, hnldot] = deval(sol,ts);
    hnl = hnl.';  hnldot = hnldot.';

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Linear Simulation
ltisys = ss(Alin,Slin\[F; zeros(Ntot,1)],[eye(Ntot), zeros(Ntot)], zeros(Ntot,1));

    % Use fine sample increment over duration of pulse
    if tfp < dt
        tlini = [0:100].'*tfp/100;
        ulini = (Afnl*2*tfp/pi)*sin((pi/tfp)*tlini);
        % Over Pulse duation to first sample
        [ylini,junki,xlini] = lsim(ltisys, [ulini], [tlini], zeros(Ntot*2,1));
        [ylin, junk2, xlin2] = lsim(ltisys, zeros(2,1), [junki(end); ts(2)], xlini(end,:).');
        % Free Response
        [ylin, junk3, xlin3] = lsim(ltisys, zeros(size(ts(2:end))), ts(2:end), xlin2(end,:).');
        hlin = [xlini(1,:); xlin2(end,:); xlin3(2:end,:)];
    else
        error('tfp > dt not yet supported!');
    end

% Plot Results
figure(10); set(gcf,'Position',[532   189   560   567]);
subplot(2,1,1)
plot(ts, hlin(:,respind), ts, hnl(:,respind), 'o-',sol.x, sol.y(respind,:), '.:'); grid on;
legend('h_{(r,5)} LIN','h_{(r,5)} NL','h_{(r,5)} ODE45');
xlabel('time (s)');
title('Comparison of Linear and Nonlinear Time Responses')

% Approximate derivatives of the response:
disp(['Number of Derivatives Requested: ',num2str(nders)]);
ndhlin = [zeros(nders,1); dt^-nders*diff(hlin(:,respind ),nders,1);];
ndhnl = [zeros(nders,1); dt^-nders*diff(hnl(:,respind ),nders,1); ];
%   Derivatives computed by "diff" don't appear to be ideal.  I don't know
%   that they are equivalent to a forward difference scheme.
% Select ODE45 derivatives - USE ODE45 Derivatives in the analysis!
if nders == 0;
    dhnlode = hnl(:,respind);
elseif nders == 1;
    dhnlode = hnl(:,respind + Ntot);
elseif nders == 2;
    dhnlode = hnldot(:,respind + Ntot);
end
tsdh = ts;%ts((1+nders):end);
subplot(2,1,2)
plot(tsdh, ndhlin, tsdh, ndhnl, ts, dhnlode, '.'); grid on;
legend(['h_D_{(',num2str(respind),',5)} LIN'],['h_D_{(',num2str(respind),',5)} NL'],...
    ['h_D_{(',num2str(respind),',5)} NL-ODE45']);
xlabel('time (s)');
title('Comparison of Derivatives of Linear and Nonlinear Responses')

% Find Actual force curve:
% This must be modified manually
% Fnl2 = Mtot(at_ns(2),at_ns(2))*hnldot(:,Ntot+at_ns(2)) - k5*(hnl(:,at_ns(2)) - hnl(:,at_ns(2)+1));
Fnl2 = Mtot(at_ns(2),:)*(hnldot(:,vnodes).') + Ktot(at_ns(2),:)*(hnl(:,dnodes).');
    if abs(fext_vec(at_ns(1))) > 0; warning('Equation for Force may not be correct'); end
Fnl3 = - Mtot(at_ns(1),:)*(hnldot(:,vnodes).') - Ktot(at_ns(1),:)*(hnl(:,dnodes).');
    if abs(fext_vec(at_ns(1))) > 0; warning('Equation for Force may not be correct'); end
delt_nl = hnl(:,at_ns(1)) - hnl(:,at_ns(2));

% Track the magnitude of the displacement of spring 4 - for NL
figure(11); set(gcf, 'Units','Normalized'); set(gcf,'Position',[0.069444,  0.48444, 0.43819, 0.39111]);
    set(gcf,'Name','Force vs. Delta Curve','Toolbar','figure');
subplot(1,3,1)
deltas = [-100:100]*(max(delt_nl)/100);
if strcmp(NLType,'bang');
    for k = 1:length(deltas)
        if deltas(k) < eom.delcont % No Contact Occurs
            Fnl(k) = eom.kat*deltas(k);
        else                % Contact Occurs
            Fnl(k) = eom.kat*eom.k4mult*deltas(k);
        end
    end
elseif strcmp(NLType,'cubic');
    Fnl = kat*deltas.*(1+katnl.*deltas.^2);
end
plot(Fnl, deltas*1e3, ...
    k4*deltas, deltas*1e3, '--',...
    Fnl2,delt_nl*1e3,'.',...
    Fnl3,delt_nl*1e3,'k.'); grid on;
ax1h = gca;
ylabel('\bf\Delta - NL Spring (mm)'); xlabel('\bfSpring Force')
title('\bfSpring Curve');
hx = subplot(1,3,2:3)
plot(ts*1e3, delt_nl*1e3); grid on;
% Set Axes to Equal
    ylim2 = get(gca,'Ylim');
    set(ax1h,'Ylim',ylim2);
xlabel('\bftime (ms)'); ylabel('\bf\Delta - NL Spring (mm)');
title('\bfDisplacement of NL Spring');

% Add button to make y-axes equal
set(hx,'tag','Main');
    PointsPerPixel = 72/get(0,'ScreenPixelsPerInch');
    hf = gcf;
    h1 = uicontrol('Parent',hf, ...
        'Units','points', ...
        'Position',[168, 51, 45, 25]*PointsPerPixel, ...
        'Callback','set_equal_ylims(hf);', ...
        'String','EqYlim', ...
        'Tag','YAxEqual');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Analysis

if strcmp(NLType,'bang');
    % ZNLDetect(hlin(:,respind),ts,[0,0.2],400)
    [Hmat,fs,ts_zc] = ZNLDetect(dhnlode,tsdh,[0,0.1],500);
    % ZNLDetectC(hnldot(:,6:10),tsdh,[0,0.3],30,400)
elseif strcmp(NLType,'cubic');
    [Hmat,fs,ts_zc] = ZNLDetect(dhnlode,tsdh,[0,0.15],500,4);
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Alternate analysis - use all sensors with ZNLDetectC
% This gives 20 ZEFFTs equally distributed between 0 and 0.1 s, 0 to 500 Hz
%
% [Hmat,fs,ts_zc] = ZNLDetectC(hnldot(:,8:end),tsdh,[0,0.1],500,20);


 function [sn,psdx,ff] = get_noise_fft(Y,options)

        defoptions = CNMFSetParms;
        if nargin < 2 || isempty(options); options = defoptions; end

        if ~isfield(options,'noise_range'); options.noise_range = defoptions.noise_range; end
        range_ff = options.noise_range;
        if ~isfield(options,'noise_method'); options.noise_method = defoptions.noise_method; end
        method = options.noise_method;
        if ~isfield(options,'block_size'); options.block_size = defoptions.block_size; end
        block_size = options.block_size;
        if ~isfield(options,'split_data'); options.split_data = defoptions.split_data; end
        split_data = options.split_data;
        if ~isfield(options,'max_timesteps') || isempty(options.max_timesteps);
            options.max_timesteps = defoptions.max_timesteps;
        end

        dims = ndims(Y);
        sizY = size(Y);
        N = min(sizY(end),options.max_timesteps);
        if N < sizY(end)
           %Y = reshape(Y,prod(sizY(1:end-1)),[]);
           switch ndims(Y),
               case 2,
                    Y(:,N+1:end) = [];
               case 3,
                    Y(:,:,N+1:end) = [];
               case 4,
                    Y(:,:,:,N+1:end) = [];
           end
        end

        Fs = 1;
        ff = 0:Fs/N:Fs/2;
        indf=ff>range_ff(1);
        indf(ff>range_ff(2))=0;
        if dims > 1
            d = prod(sizY(1:dims-1));
            Y = reshape(Y,d,N);
            Nb = prod(block_size);
            SN = cell(ceil(d/Nb),1);
            PSDX = cell(ceil(d/Nb),1);
            if ~split_data
                for ind = 1:ceil(d/Nb);
                    xdft = fft(Y((ind-1)*Nb+1:min(ind*Nb,d),:),[],2);
                    xdft = xdft(:,1: floor(N/2)+1); % FN: floor added.
                    psdx = (1/(Fs*N)) * abs(xdft).^2;
                    psdx(:,2:end-1) = 2*psdx(:,2:end-1) + eps;
                    %SN{ind} = mean_psd(psdx(:,indf),method);
                    switch lower(method)
                        case 'mean'
                            SN{ind}=sqrt(mean(psdx(:,indf)/2,2));
                        case 'median'
                            SN{ind}=sqrt(median(psdx(:,indf)/2,2));
                        case 'logmexp'
                            SN{ind} = sqrt(exp(mean(log(psdx(:,indf)/2),2)));
                        otherwise
                            error('unknown method for averaging noise..')
                    end
                    PSDX{ind} = psdx;
                end
            else
                nc = ceil(d/Nb);
                Yc = mat2cell(Y,[Nb*ones(nc-1,1);d-(nc-1)*Nb],N);
                parfor ind = 1:ceil(d/Nb);
                    xdft = fft(Yc{ind},[],2);
                    xdft = xdft(:,1:floor(N/2)+1);
                    psdx = (1/(Fs*N)) * abs(xdft).^2;
                    psdx(:,2:end-1) = 2*psdx(:,2:end-1) + eps;
                    Yc{ind} = [];
                    switch lower(method)
                        case 'mean'
                            SN{ind}=sqrt(mean(psdx(:,indf)/2,2));
                        case 'median'
                            SN{ind}=sqrt(median(psdx(:,indf)/2,2));
                        case 'logmexp'
                            SN{ind} = sqrt(exp(mean(log(psdx(:,indf)/2),2)));
                        otherwise
                            error('unknown method for averaging noise..')
                    end

                end
            end
            sn = cell2mat(SN);
        else
            xdft = fft(Y);
            xdft = xdft(:,1:floor(N/2)+1);
            psdx = (1/(Fs*N)) * abs(xdft).^2;
            psdx(:,2:end-1) = 2*psdx(:,2:end-1) + eps;
            switch lower(method)
                case 'mean'
                    sn = sqrt(mean(psdx(:,indf)/2,2));
                case 'median'
                    sn = sqrt(median(psdx(:,indf)/2,2));
                case 'logmexp'
                    sn = sqrt(exp(mean(log(psdx(:,indf)/2),2)));
                otherwise
                    error('unknown method for averaging noise..')
            end
        end
        psdx = cell2mat(PSDX);
        if dims > 2
            sn = reshape(sn,sizY(1:dims-1));
        end
 end


function [CD0] = DetermineProfileDrag(airfoildata,geo,panel)
%Determine the wing profile drag from the airfoils' drag polars

airfoil_r = geo.rootindex;
airfoil_t = geo.tipindex;

%Root dimensions
chord_r = geo.c_r;

%Determine Reynolds number at root; using log10 because regression was
%done this way
Re_r = log10(geo.Re_r);

%Convert back to degrees because the polynomial regression of the XFOIL
%drag data is in terms of degrees
alpha_r = (geo.i_r + geo.alpha)*180/pi;
b = cell2mat(airfoildata{2}(airfoil_r)); %Load the coefficients
c = cell2mat(airfoildata{3}(airfoil_r));
d = cell2mat(airfoildata{4}(airfoil_r));
k = cell2mat(airfoildata{5}(airfoil_r));
cd0_r = b(1) + b(2)*Re_r + b(3)*Re_r^2;
cd1_r = c(1) + c(2)*Re_r + c(3)*Re_r^2;
cd2_r = d(1) + d(2)*Re_r + d(3)*Re_r^2;
alpha_stall_r = k(1) + k(2)*Re_r + k(3)*Re_r^2;

%Test to see if airfoil is past stall angle of attack
if alpha_r > alpha_stall_r
    cd2_r = 2*cd2_r;
    %Double the last coefficient to account for the large increase in drag
    %past stall
end

%Tip dimensions
chord_t = geo.c_r*geo.taper;

%Determine Reynolds number at tip, use log10 because performed regression
%using log10
Re_t = log10(geo.Re_t);

%Convert back to degrees because the polynomial regression of the XFOIL
%drag data is in terms of degrees
alpha_t = (geo.i_r + geo.twist + geo.alpha)*180/pi;
b = cell2mat(airfoildata{2}(airfoil_t)); %Load the coefficients
c = cell2mat(airfoildata{3}(airfoil_t));
d = cell2mat(airfoildata{4}(airfoil_t));
k = cell2mat(airfoildata{5}(airfoil_t));
cd0_t = b(1) + b(2)*Re_t + b(3)*Re_t^2;
cd1_t = c(1) + c(2)*Re_t + c(3)*Re_t^2;
cd2_t = d(1) + d(2)*Re_t + d(3)*Re_t^2;
alpha_stall_t = k(1) + k(2)*Re_t + k(3)*Re_t^2;

%Test to see if airfoil is past stall angle of attack
if alpha_t > alpha_stall_t
    cd2_t = 2*cd2_t;
    %Double the last coefficient to account for the large increase in drag
    %past stall
end

%eta represents the fraction from 0 to 1 at the center of the panel where 0
%corresponds to y = 0 and 1 corresponds to y = b
eta = (2*(1:geo.ns)-1)/(2*geo.ns);
chord = chord_r + eta*(chord_t-chord_r);
alpha = alpha_r + eta*(alpha_t-alpha_r);
cd0 = cd0_r + eta*(cd0_t-cd0_r);
cd1 = cd1_r + eta*(cd1_t-cd1_r);
cd2 = cd2_r + eta*(cd2_t-cd2_r);

Deltay = zeros(1,geo.ns);
for i = 1:geo.ns
    Deltay(i) = panel(i,1).BV2(2) - panel(i,1).BV1(2);
end

D_q = (cd0 + cd1.*alpha + cd2.*alpha.^2).*chord.*Deltay;

CD0 = 2*sum(D_q,2)/geo.S;


function value = r4_gamma ( x )

%*****************************************************************************80
%
%% R4_GAMMA evaluates the gamma function of an R4 argument.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    25 September 2011
%
%  Author:
%
%    Original FORTRAN77 version by Wayne Fullerton.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Wayne Fullerton,
%    Portable Special Function Routines,
%    in Portability of Numerical Software,
%    edited by Wayne Cowell,
%    Lecture Notes in Computer Science, Volume 57,
%    Springer 1977,
%    ISBN: 978-3-540-08446-4,
%    LC: QA297.W65.
%
%  Parameters:
%
%    Input, real X, the argument.
%
%    Output, real VALUE, the gamma function of X.
%
  persistent dxrel
  persistent gcs
  persistent ngcs
  persistent sq2pil
  persistent xmax
  persistent xmin
  persistent xsml

  sq2pil = 0.91893853320467274;

  if ( isempty ( ngcs ) )

    gcs = [ ...
      0.008571195590989331, ...
      0.004415381324841007, ...
      0.05685043681599363, ...
     -0.004219835396418561, ...
      0.001326808181212460, ...
     -0.0001893024529798880, ...
      0.0000360692532744124, ...
     -0.0000060567619044608, ...
      0.0000010558295463022, ...
     -0.0000001811967365542, ...
      0.0000000311772496471, ...
     -0.0000000053542196390, ...
      0.0000000009193275519, ...
     -0.0000000001577941280, ...
      0.0000000000270798062, ...
     -0.0000000000046468186, ...
      0.0000000000007973350, ...
     -0.0000000000001368078, ...
      0.0000000000000234731, ...
     -0.0000000000000040274, ...
      0.0000000000000006910, ...
     -0.0000000000000001185, ...
      0.0000000000000000203 ]';

    ngcs = r4_inits ( gcs, 23, 0.1 * r4_mach ( 3 ) );
    [ xmin, xmax ] = r4_gaml ( );
    xsml = exp ( max ( log ( r4_mach ( 1 ) ), ...
      - log ( r4_mach ( 2 ) ) ) + 0.01 );
    dxrel = sqrt ( r4_mach ( 4 ) );

  end

  y = abs ( x );

  if ( y <= 10.0 )

    n = r4_aint ( x );
    if ( x < 0.0 )
      n = n - 1;
    end
    y = x - n;
    n = n - 1;
    value = 0.9375 + r4_csevl ( 2.0 * y - 1.0, gcs, ngcs );

    if ( n == 0 )

      return

    elseif ( n < 0 )

      n = - n;

      if ( x == 0.0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is 0.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      if ( x < 0.0 && x + n - 2 == 0.0 )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is a negative integer.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      if ( x < - 0.5 && ...
        abs ( ( x - r4_aint ( x - 0.5 ) ) / x ) < dxrel )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Warning!\n' );
        fprintf ( 1, '  X too near a negative integer,\n' );
        fprintf ( 1, '  answer is half precision.\n' );
      end

      if ( y < xsml )
        fprintf ( 1, '\n' );
        fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
        fprintf ( 1, '  X is so close to zero that Gamma overflows.\n' );
        error ( 'R4_GAMMA - Fatal error!' )
      end

      for i = 1 : n
        value = value / ( x + i - 1 );
      end

    elseif ( n == 0 )

    else

      for i = 1 : n
        value = ( y + i ) * value;
      end

    end

  else

    if ( xmax < x )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
      fprintf ( 1, '  X so big that Gamma overflows.\n' );
      error ( 'R4_GAMMA - Fatal error!' )
    end
%
%  Underflow.
%
    if ( x < xmin )
      value = 0.0;
      return
    end

    value = exp ( ( y - 0.5 ) * log ( y ) - y + sq2pil + r4_lgmc ( y ) );

    if ( 0.0 < x )
      return
    end

    if ( abs ( ( x - r4_aint ( x - 0.5 ) ) / x ) < dxrel )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Warning!\n' );
      fprintf ( 1, '  X too near a negative integer,\n' );
      fprintf ( 1, '  answer is half precision.\n' );
    end

    sinpiy = sin ( pi * y );

    if ( sinpiy == 0.0 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'R4_GAMMA - Fatal error!\n' );
      fprintf ( 1, '  X is a negative integer.\n' );
      error ( 'R4_GAMMA - Fatal error!' )
    end

    value = - pi / ( y * sinpiy * value );

  end

  return
end


function [G, pixels, patches] = gsp_patch_graph(img, param)
%GSP_PATCH_GRAPH Create a graph by NN patches of an image
%   Usage :  G = compute_patch_graph( img );
%            [G, f] = gsp_patch_graph( img, param );
%            [G, f, patches] = gsp_patch_graph( img, param );
%
%   Input parameters:
%       img         : Input image (unknown pixels marked as NaN)
%       param       : Structure of optional parameters
%
%   Output parameters:
%       G           : Resulting graph
%       f           : Image signal
%       patches     : Patches
%
%   'compute_patch_graph( path , param )' creates a graph between pixels in
%   an image by connecting them using the euclidean distance between
%   patches around the pixels
%
%   Additional parameters
%   ---------------------
%
%   * *param.patch_size*      : int     the patch size in pixels (odd)
%   * *param.scale*           : float   to rescale the input image
%   * *param.rho*             : float   spatial constraint
%   * *use_incomplete_patch*  : boolean use incomplete patch for the graph construction
%   * *param.nnparam*         : struct  parameters for graph construction
%

% Author: Johan Paratte, Michael Defferrard, Nathanael Perraudin
% Date: November 2014
%

    if nargin < 2
    % Define parameters
        param = {};
    end

    if ~isfield(param, 'patch_size'), param.patch_size = 5; end
    if ~isfield(param, 'rho'), param.rho = 0.001; end
    if ~isfield(param, 'use_incomplete_patch'), param.use_incomplete_patch = 0; end
    if ~isfield(param, 'nnparam')
       param.nnparam = {};
       param.nnparam.center = 0;
       param.nnparam.resize = 0;
       param.nnparam.k = 10;
       param.nnparam.use_l1 = 0;
       param.nnparam.use_flann = 1;
    end

    if (mod(param.patch_size, 2) == 0)
        disp('Patch size must be odd, converting to closest odd number');
        param.patch_size = param.patch_size + 1;
    end

%     if length(size(img)) > 2
%        img = rgb2gray(img);
%     end

    %Extract patches
    [oheight, owidth,Nc] = size(img);

    psize = param.patch_size;

    %Parameters
    if isfield(param, 'scale')
        img = imresize(img, param.scale);
    end

    margin = floor(psize / 2);

    dim = psize*psize;
    %height = (oheight - 2*margin);
    %width = (owidth - 2*margin);

    %Expand the image to compensate the margin
    h = oheight;
    w = owidth;
    new_img = zeros(h + 2*margin, w + 2*margin,Nc);
    %Copy image
    new_img(1+margin:end-margin, 1+margin:end-margin,:) = img;
    %Four lines
    new_img(1:margin, 1+margin:end-margin,:) = img(margin:-1:1, :,:);
    new_img(1+margin:end-margin, 1:margin,:) = img(:, margin:-1:1,:);
    new_img(end-margin:end, 1+margin:end-margin,:) = img(end:-1:end-margin, :,:);
    new_img(1+margin:end-margin, end-margin:end,:) = img(:,end:-1:end-margin,:);
    %Four corners
    new_img(1:margin, 1:margin,:) = img(margin:-1:1, margin:-1:1,:);
    new_img(1:margin, end-margin:end,:) = img(margin:-1:1, end:-1:end-margin,:);
    new_img(end-margin:end, 1:margin,:) = img(end:-1:end-margin, margin:-1:1,:);
    new_img(end-margin:end, end:-1:end-margin,:) = img(end:-1:end-margin, end:-1:end-margin,:);

    % Signals on the graph.
    patches = zeros(h*w, dim*Nc+2);
    pixels  = double(reshape(img, h*w, Nc)); % zeros(h*w, 1);
    coords  = zeros(h*w, 2);  % gsp_plot_signal takes [x,y]
    coords(:,2) = repmat((h:-1:1).', w, 1);
    coords(:,1) = reshape(repmat((1:+1:w), h, 1), [], 1);

    % Pre-allocation.
    nUnknown = sum(sum(img(:,:,1)<0)) * 2;
    unknowns = zeros(nUnknown, 1);
    iUnknown = 0;

    count = 1;

    % For speed improvement, one of the for loop can probably be removed
    % here
    for w = 1:owidth
       for h = 1:oheight
            patches(count, 1:Nc*dim) = reshape(new_img(h:h+psize-1, w:w+psize-1,:), 1, Nc*dim);
            patches(count, Nc*dim+1:end) = [param.rho*w; param.rho*h];
            count = count + 1;
        end
    end

    fprintf('Compute graph with %d vertices\n', size(patches,1));

    if param.use_incomplete_patch

        G = gsp_rmse_mv_graph(patches, param.nnparam);
    else
        % Ignore patches which contain unknown pixel values.
        % We do not want them to be connected with known patches.
        clearedPatches = patches;

        for count = 1:size(clearedPatches,1)
            if sum(isnan(clearedPatches(count,:)))
                clearedPatches(count,:) = -1e3;
                % List of unknown patches.
                iUnknown = iUnknown + 1;
                unknowns(iUnknown) = count;
            end
        end

        G = gsp_nn_graph(clearedPatches, param.nnparam);

        % Disconnect unknown patches.
        unknowns = unknowns(1:iUnknown);
        G.W(unknowns,:) = 0;
        G.W(:,unknowns) = 0;

        % Update G.A, G.d and G.Ne.
        G = gsp_graph_default_parameters(G);
    end

    % These are coordinates in the high dimensional patch space. We prefer
    % to visualize the graph in the 2D image space.
%     patches = G.coords;
    G.coords = coords;
    G.plotting.limits = [1,w,1,h];

end


function [regions, thresholds, maxSig] = imMultiOtsuThreshold(img, nClasses, varargin)
% Multilevel Thresholding using Otsu Method.
%
%   CLASSES = imMultiOtsuThreshold(IMG, NC)
%   Computes a segmentation of the input grayscale image IMG into NC
%   classes. The number of classes must be comprised between 2 and 5.
%
%   [CLASSES, THRESHOLDS] = imMultiOtsuThreshold(IMG, NC)
%   Also returns the list of threshold. The number of threshold values is
%   the number of classes minus one.
%
%   Example
%     % segment cameraman image into three classes
%     img = imread('cameraman.tif');
%     [classes, threshs] = imMultiOtsuThreshold(img, 3);
%     rgb = label2rgb(classes, 'jet', [1 0 0], 'shuffle');
%     figure; imshow(rgb);
%     % also displays histogram with threshold levels
%     figure; imHistogram(img);
%     hold on;
%     for i = 1:2
%        plot(threshs([i i]), [0 1800], 'color', 'r', 'linewidth', 2);
%     end
%
%   References
%   * Ping-Sung Liao, Tse-Sheng Chen, Pau-Choo Chung (2001). "A Fast
%   Algorithm for Multilevel Thresholding". Journal of Information Science
%   and Engineering, Vol. 17 No. 5, pp. 713-727.
%   https://jise.iis.sinica.edu.tw/JISESearch/pages/View/PaperView.jsf?keyId=86_1302#
%   * https://imagej.net/Multi_Otsu_Threshold
%
%   See also
%     imOtsuThreshold, imHistogram, imMaxEntropyThreshold
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% INRAE - BIA Research Unit - BIBS Platform (Nantes)
% Created: 2021-01-29,    using Matlab 9.8.0.1323502 (R2020a)
% Copyright 2021 INRAE.

%% Input arguments

if ~isa(img, 'uint8')
    error('Requires a grayscale uint8 image as first input');
end

if nClasses < 2 || nClasses > 5
    error('The number of classes must be comprised between 2 and 5.');
end

%% Initialisations

% compute histogram, and convert into probability density
[h, levels] = imHistogram(img, varargin{:});
h = h / sum(h);

% number of gray levels
nLevels = length(levels);

Puv = zeros(nLevels, nLevels);
Suv = zeros(nLevels, nLevels);
Huv = zeros(nLevels, nLevels);

% initialize diagonal terms
for i = 1:nLevels
    Puv(i, i) = h(i);
    Suv(i, i) = h(i) * i;
end

% initialize first rows
for i = 2:nLevels
    Puv(1, i) = Puv(1, i-1) + h(i);
    Suv(1, i) = Suv(1, i-1) + i*h(i);
end
% initialize the rest of the matrices
for u = 2:nLevels
    for v = u+1:nLevels
        Puv(u, v) = Puv(1, v) - Puv(1, u-1);
        Suv(u, v) = Suv(1, v) - Suv(1, u-1);
    end
end

% now calculate Huv
for u = 1:nLevels
    for v = u+1:nLevels
        if Puv(u,v) > 0
            Huv(u,v) = Suv(u,v) * Suv(u,v) / Puv(u,v);
        end
    end
end

%% Main processing

% create array for threshold values (first one is zeros, last one is inf)
thresholds = zeros(nClasses+1, 1);
thresholds(end) = inf;

% iterate over all possible combinations
maxSig = 0.0;
switch nClasses
    case 2
        % two classes -> only need to find second threshold value
        for i = 1:nLevels-1
            Sq = Huv(1,i) + Huv(i+1, end);
            if Sq >= maxSig
                thresholds(2) = i;
                maxSig = Sq;
            end
        end

    case 3
        % three classes
        for i = 1:nLevels-2
            for j = i+1:nLevels-1
                Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, end);
                if Sq >= maxSig
                    thresholds(2) = i;
                    thresholds(3) = j;
                    maxSig = Sq;
                end
            end
        end

    case 4
        % four classes
        for i = 1:nLevels-3
            for j = i+1:nLevels-2
                for k = j+1:nLevels-1
                    Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, k) + Huv(k+1, end);
                    if Sq >= maxSig
                        thresholds(2) = i;
                        thresholds(3) = j;
                        thresholds(4) = k;
                        maxSig = Sq;
                    end
                end
            end
        end

    case 5
        % five classes
        for i = 1:nLevels-3
            for j = i+1:nLevels-2
                for k = j+1:nLevels-1
                    for m = k+1:nLevels-1
                        Sq = Huv(1,i) + Huv(i+1, j) + Huv(j+1, k) + Huv(k+1, m) + Huv(m+1, end);
                        if Sq >= maxSig
                            thresholds(2) = i;
                            thresholds(3) = j;
                            thresholds(4) = k;
                            thresholds(5) = m;
                            maxSig = Sq;
                        end
                    end
                end
            end
        end

    otherwise
        error('Can not manage %d number of classes', nClasses);
end

%% Create region image

regions = zeros(size(img), 'uint8');
for i = 1:nClasses
    inds = img >= thresholds(i) & img < thresholds(i+1);
    regions(inds) = i;
end


function A = VBA_spm_mesh_adjacency(F)
% Compute the adjacency matrix of a triangle mesh
% FORMAT A = spm_mesh_adjacency(F)
% F        - a [fx3] faces array or a patch structure
%
% A        - adjacency matrix as a sparse [vxv] array
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_mesh_adjacency.m 4035 2010-08-05 18:54:32Z guillaume $

if ~isnumeric(F) && isfield(F,'vertices')
    N = size(F.vertices,1);
    F = double(F.faces);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1, N, N);
else
    if isstruct(F), F = F.faces; end
    F = double(F);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1);
end

A = double(A > 0);


function A = spm_mesh_adjacency(F)
% Compute the adjacency matrix of a triangle mesh
% FORMAT A = spm_mesh_adjacency(F)
% F        - a [fx3] faces array or a patch structure
%
% A        - adjacency matrix as a sparse [vxv] array
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Guillaume Flandin
% $Id: spm_mesh_adjacency.m 4035 2010-08-05 18:54:32Z guillaume $

if ~isnumeric(F) && isfield(F,'vertices')
    N = size(F.vertices,1);
    F = double(F.faces);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1, N, N);
else
    if isstruct(F), F = F.faces; end
    F = double(F);
    A = sparse([F(:,1); F(:,1); F(:,2); F(:,2); F(:,3); F(:,3)], ...
           [F(:,2); F(:,3); F(:,1); F(:,3); F(:,1); F(:,2)], 1);
end

A = double(A > 0);


function varargout = sl2dmatcov(type, data, matsiz, n, meanmat, PL, PR, w)
%SL2DMATCOV Computes the 2D matrix-covariances
%
% $ Syntax $
%   - CL = sl2dmatcov('CL', data, matsiz, n, meanmat, PL, PR, w)
%   - CR = sl2dmatcov('CR', data, matsiz, n, meanmat, PL, PR, w)
%   - [CL, CR] = sl2dmatcov('Both', data, matsiz, n, meanmat, PL, PR, w)
%
% $ Arguments $
%   - data:     the stack of matrices or the cell array of filenames of the
%               array files storing the matrices.
%   - matsiz:   the size of each matrix
%   - n:        the number of samples
%   - PL:       the left-projection matrix, default = []
%   - PR:       the right-projection matrix, default = []
%   - w:        the weights of the matrix samples, default = []
%
% $ Remarks $
%   - The function computes the 2D matrix-covariances according to
%     the following formulas:
%       Y_i = PL^T * (X - meanX)* PR
%       CL = ( sum_{i=1}^n w(i) * Y_i * Y_i^T ) / ( sum_{i=1}^n w(i) )
%       CR = ( sum_{i=1}^n w(i) * Y_i^T * Y_i ) / ( sum_{i=1}^n w(i) )
%     Following special cases are considered:
%       If w is empty, then we take w(i) = 1 for all i
%       If PL is empty, then we take PL as an identity matrix
%       If PR is empty, then we take PR as an identity matrix
%       If meanmat is 0, then we take meanmat as a zero matrix
%
% $ History $
%   - Created by Dahua Lin, on Jul 31st, 2006
%

%% parse and verify input arguments

if nargin < 5
    raise_lackinput('sl2dmatcov', 5);
end
if nargin < 6
    PL = [];
end
if nargin < 7
    PR = [];
end
if nargin < 8
    w = [];
end

matsiz = matsiz(:)';
if length(matsiz) ~= 2
    error('sltoolbox:invalidarg', ...
        'matsiz shoudl be a 2-elem vector');
end
if ~isequal(size(meanmat), matsiz)
    error('sltoolbox:invalidarg', ...
        'The size of mean matrix is not as specified');
end

d1 = matsiz(1);
d2 = matsiz(2);
if ~isempty(PL) && size(PL, 1) ~= d1
    error('sltoolbox:invalidarg', ...
        'The size of PL is inconsistent with the matrix dimension');
end
if ~isempty(PR) && size(PR, 1) ~= d2
    error('sltoolbox:invalidarg', ...
        'The size of PR is inconsistent with the matrix dimension');
end

if ~isempty(w)
    if length(w) ~= n
        error('The weights length is inconsistent with the number of samples');
    end
    tw = sum(w);
else
    tw = n;
end

%% Main body

if isnumeric(data)

    if ~isequal(size(data), [matsiz, n])
        error('sltoolbox:invalidarg', ...
            'The size of data is inconsistent with specified');
    end

    Y = compute_Y(data, meanmat, PL, PR);

    switch type
        case 'CL'
            CL = compute_SL(Y, w);
            CL = CL / tw;
            varargout = {CL};
        case 'CR'
            CR = compute_SR(Y, w);
            CR = CR / tw;
            varargout = {CR};
        case 'Both'
            [CL, CR] = compute_SLSR(Y, w);
            CL = CL / tw;
            CR = CR / tw;
            varargout = {CL, CR};
        otherwise
            error('sltoolbox:invalidarg', ...
                'invalid type: %s', type);
    end

elseif iscell(data)

    nfiles = length(data);
    cf = 0;

    switch type
        case 'CL'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                curCL = compute_SL(Y, w);
                if i == 1
                    CL = curCL;
                else
                    CL = CL + curCL;
                end
                clear Y curCL;
                cf = cf + curn;
            end
            CL = CL / tw;
            varargout = {CL};

        case 'CR'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                curCR = compute_SR(Y, w);
                if i == 1
                    CR = curCR;
                else
                    CR = CR + curCR;
                end
                clear Y curCR;
                cf = cf + curn;
            end
            CR = CR / tw;
            varargout = {CR};

        case 'Both'
            for i = 1 : nfiles
                curarr = slreadarray(data{i});
                curn = size(curarr, 3);
                Y = compute_Y(curarr, meanmat, PL, PR);
                [curCL, curCR] = compute_SLSR(Y, w);
                if i == 1
                    CL = curCL;
                    CR = curCR;
                else
                    CL = CL + curCL;
                    CR = CR + curCR;
                end
                clear Y curCL curCR;
                cf = cf + curn;
            end
            CL = CL / tw;
            CR = CR / tw;
            varargout = {CL, CR};

        otherwise
            error('sltoolbox:invalidarg', ...
                'invalid type: %s', type);
    end

    if cf ~= n
        error('sltoolbox:sizmismatch', ...
            'The total number of samples is not n');
    end

else
    error('sltoolbox:invalidarg', ...
        'data should be a numeric array or a cell array of filenames');
end

%% Core routine

function Y = compute_Y(X, M, PL, PR)

n = size(X, 3);
if isempty(PL)
    if isempty(PR)
        if isequal(M, 0)
            Y = X;
        else
            Y = zeros(size(X, 1), size(X, 2), n);
            for i = 1 : n
                Y(:,:,i) = X(:,:,i) - M;
            end
        end
    else
        Y = zeros(size(X, 1), size(PR, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = X(:,:,i) * PR;
            end
        else
            for i = 1 : n
                Y(:,:,i) = (X(:,:,i) - M) * PR;
            end
        end
    end
else
    PLT = PL';
    if isempty(PR)
        Y = zeros(size(PL, 2), size(X, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = PLT * X(:,:,i);
            end
        else
            for i = 1 : n
                Y(:,:,i) = PLT * (X(:,:,i) - M);
            end
        end
    else
        Y = zeros(size(PL, 2), size(PR, 2), n);
        if isequal(M, 0)
            for i = 1 : n
                Y(:,:,i) = PLT * X(:,:,i) * PR;
            end
        else
            for i = 1 : n
                Y(:,:,i) = PLT * (X(:,:,i) - M) * PR;
            end
        end
    end
end

function SL = compute_SL(Y, w)

SL = zeros(size(Y, 1));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + curY * curY';
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + w(i) * curY * curY';
    end
end

function SR = compute_SR(Y, w)

SR = zeros(size(Y, 2));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SR = SR + curY' * curY;
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SR = SR + w(i) * curY' * curY;
    end
end

function [SL, SR] = compute_SLSR(Y, w)

SL = zeros(size(Y, 1));
SR = zeros(size(Y, 2));
n = size(Y, 3);
if isempty(w)
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + curY * curY';
        SR = SR + curY' * curY;
    end
else
    for i = 1 : n
        curY = Y(:, :, i);
        SL = SL + w(i) * curY * curY';
        SR = SR + w(i) * curY' * curY;
    end
end


function [solution, nIterations, bestApprox] = sparseLP(model, approximation, params)
% DC programming for solving the sparse LP
% :math:`min ||x||_0` subject to linear constraints
% See `Le Thi et al., DC approximation approaches for sparse optimization,
% European Journal of Operational Research, 2014`;
% http://dx.doi.org/10.1016/j.ejor.2014.11.031
%
% USAGE:
%
%    [solution, nIterations, bestApprox] = sparseLP(model, approximation, params);
%
% INPUTS:
%    model:       Structure containing the following fields describing the linear constraints:
%
%                        * .A - `m x n` LHS matrix
%                        * .b - `m x 1` RHS vector
%                        * .lb - `n x 1` Lower bound vector
%                        * .ub - `n x 1` Upper bound vector
%                        * .csense - `m x 1` Constraint senses, a string containting the model sense for
%                          each row in `A` ('E', equality, 'G' greater than, 'L' less than).
%
% OPTIONAL INPUTS
%    approximation:    appoximation type of zero-norm. Available approximations:
%
%                        * 'cappedL1' : Capped-L1 norm
%                        * 'exp'      : Exponential function
%                        * 'log'      : Logarithmic function
%                        * 'SCAD'     : SCAD function
%                        * 'lp-'      : `L_p` norm with `p < 0`
%                        * 'lp+'      : `L_p` norm with `0 < p < 1`
%                        * 'l1'       : L1 norm
%                        * 'all'      : try all approximations and return the best result
%
% OPTIONAL INPUTS:
%    params:           Parameters structure:
%
%                        * .nbMaxIteration - stopping criteria - number maximal of iteration (Defaut value = 1000)
%                        * .epsilon - stopping criteria - (Defaut value = 10e-6)
%                        * .theta - parameter of the approximation (Defaut value = 0.5)
%
% OUTPUT:
%    solution:         Structure containing the following fields:
%
%                        * .x - `n x 1` solution vector
%                        * .stat - status:
%
%                          * 1 =  Solution found
%                          * 2 =  Unbounded
%                          * 0 =  Infeasible
%                          * -1=  Invalid input
%
%   nIterations:       Number of iterations
%   bestApprox:        Best approximation
%
% .. Author: - Hoai Minh Le,	20/10/2015
%              Ronan Fleming,    2017

availableApprox = {'exp','log','SCAD','lp-','lp+','l1','cappedL1','all'};

if ~exist('approximation','var')
    approximation='cappedL1';
end

% Check inputs
if nargin < 3
    params.nbMaxIteration = 1000;
    params.epsilon = 1e-6;
    params.theta   = 0.5;
    params.pNeg = -1;
    params.pPos = 0.5;
else
    if ~isfield(params,'nbMaxIteration')
        params.nbMaxIteration = 1000;
    end

    if ~isfield(params,'epsilon')
        params.epsilon = 1e-6;
    end

    if ~isfield(params,'theta')
        params.theta   = 0.5;
    end

    if ~isfield(params,'pNeg')
        params.pNeg = -1;
    end

    if ~isfield(params,'pPos')
        params.pPos = 0.5;
    end

end

if ~isfield(model,'A')
    error('Error:LHS matrix is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'b')
    error('RHS vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'lb')
    error('Lower bound vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'ub')
    error('Upper bound vector is not defined');
    solution.stat = -1;
    return;
end
if ~isfield(model,'csense')
    error('Constraint sense vector is not defined');
    solution.stat = -1;
    return;
end

if ~ismember(approximation,availableApprox)
    error('Approximation is not valid');
    solution.stat = -1;
    return;
end

bestApprox = '';

switch approximation
    case 'all'
        approximations = setdiff(availableApprox,'all','stable');
        bestResult = size(model.A,2);
        bestSolution.x = [];
        bestSolution.stat = 0;
        bestIterations = 0;
        feasTol = getCobraSolverParams('LP','feasTol');
        for i=1:length(approximations)
            %disp(approximations(i))
            %try
            [candSolution,candIterations] = sparseLP(model,approximations{i},params);
            %catch
            %fail gracefully
            %solutionL0.stat = 0;
            %end
            if candSolution.stat == 1
                candResult = nnz(abs(candSolution.x) > feasTol);
                if bestResult >= candResult
                    bestResult = candResult;
                    bestApprox = approximations{i};
                    bestSolution = candSolution;
                    bestIterations = candIterations;
                end
            end
        end
        solution = bestSolution;
        nIterations = bestIterations;

    otherwise
        [nbMaxIteration,epsilon,theta,pNeg,pPos] = deal(params.nbMaxIteration,params.epsilon,params.theta,params.pNeg,params.pPos);
        [A,b,lb,ub,csense] = deal(model.A,model.b,model.lb,model.ub,model.csense);

        %Parameters
        nbIteration = 0;
        epsilonP = 10e-2;
        alpha = 3;
        [m,n] = size(A);

        %Create the linear sub-programme that one needs to solve at each iteration, only its
        %objective function changes, the constraints set remains.

        % Constraints
        % Ax <=b
        % t >= x
        % t >= -x
        A2 = [A         sparse(m,n);
            speye(n) -speye(n);
            -speye(n) -speye(n)];
        b2 = [b; zeros(2*n,1)];
        csense2 = [csense;repmat('L',2*n, 1)];

        % Bound;
        % lb <= x <= ub
        % 0  <= t <= max(|lb|,|ub|)
        lb2 = [lb;zeros(n,1)];
        ub2 = [ub;max(abs(lb),abs(ub))];

        %Define the linear sub-problem
        subLPproblem = struct('osense',1,'A',A2,'csense',csense2,'b',b2,'lb',lb2,'ub',ub2);

        %Initialisation
        x = zeros(n,1);
        obj_old = evalObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);

        %DCA
        tic
        while nbIteration < nbMaxIteration

            x_old = x;

            %Solve the linear problem
            subLPproblem.c = updateObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);
            solution = solveCobraLP(subLPproblem);

            if solution.stat == 1
                x = solution.full(1:n);

                %Check stopping criterion
                error_x = norm(x - x_old);
                obj_new = evalObj(x,theta,pNeg,pPos,epsilonP,alpha,approximation);
                error_obj = abs(obj_new - obj_old);
                if (error_x < epsilon) || (error_obj < epsilon)
                    break;
                else
                    obj_old = obj_new;
                end
                % Automatically update the approximation parameter theta
                if theta < 1000
                    theta = theta * 1.5;
                end
                nbIteration = nbIteration + 1;
                %             disp(strcat('DCA - Iteration: ',num2str(nbIteration)));
                %             disp(strcat('Obj:',num2str(obj_new)));
                %             disp(strcat('Stopping criteria error: ',num2str(min(error_x,error_obj))));
                %             disp('=================================');
            else
                x = [];
                break;
            end
        end

        time = toc;
        solution.x = x;
        solution.time = time;
        nIterations = nbIteration;

end


function [ a, info ] = cpofa ( a, lda, n )

%*****************************************************************************80
%
%% CPOFA factors a complex hermitian positive definite matrix.
%
%  Discussion:
%
%    CPOFA is usually called by CPOCO, but it can be called
%    directly with a saving in time if RCOND is not needed.
%    (time for CPOCO) = (1 + 18/N) * (time for CPOFA).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex A(LDA,N), the hermitian matrix to be factored.
%
%    Input, integer LDA, the leading dimension of A.
%
%    Input, integer N, the order of the matrix.
%
%    Output, complex A(LDA,N); an upper triangular matrix R so that
%      A = hermitian(R)*R
%    where hermitian(R) is the conjugate transpose.  The strict lower
%    triangle is unaltered.  If INFO /= 0, the factorization is not
%    complete.  Only the diagonal and upper triangle are used.
%
%    Output, integer INFO.
%    0, for normal return.
%    K, signals an error condition.  The leading minor of order K is
%    not positive definite.
%
  info = 0;

  for j = 1 : n

    s = 0.0;

    for k = 1 : j-1
      t = a(k,j) - a(1:k-1,k)' * a(1:k-1,j);
      t = t / a(k,k);
      a(k,j) = t;
      s = s + real ( t * conj ( t ) );
    end

    s = real ( a(j,j) ) - s;

    if ( s <= 0.0 | imag ( a(j,j) ) ~= 0.0 )
      info = j;
      break
    end

    a(j,j) = sqrt ( s );

  end

  return
end


function out = sum(f)
%SUM   Definite integral of a SINGFUN on the interval [-1,1].
%   SUM(F) is the integral of F from -1 to 1.
%
% See also CUMSUM, DIFF.

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

% Note for developers:
%
% The main algorithm:
%
% When the smoothPart of F is a CHEBTECH, that is, it can be written as
% Chebyshev sum, the integral
%
% I = \int_{-1}^{1} F dx = \sum_{0}^{n-1} c_r M_r,
%
% where M_r = \int_{-1}^{1} (1+x)^a(1-x)^b T_r(x) dx is the rth Jacobi moment.
%
% The computation of M_r is treated differently for different a and b:
%
% (I) when a == b, M_r are the Gegenbauer moments, which bear a closed-form
% solution as indicated in [2] and [4].
%
% (II) when a ~= b, M_r are the general Jacobi moments, which can be obtained
% using a three-term recursive relation discussed in [3].
%
% This way, all quadratures in SINGFUN, along with those in CHEBTECH are now
% entirely of Clenshaw-Curtis style.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Useful References:
%
% [1]. K. Xu and M. Javed, Singfun Working Note, August 2013
%
% [2]. Hunter, D., and Nikolov, G., Gaussian Quadrature of Chebyshev
% Polynomials, J. Comput. Appl. Math. 94 (1998), 123-131.
%
% [3]. Piessens, R., and Branders, M., The Evaluation and Application of Some
% Modified Moments, BIT 13 (1973), 443-450.
%
% [4]. Sommariva, A., Fast construction of Fejer and Clenshaw–Curtis rules for
% general weight functions, Computers & Mathematics with Applications 65
% (2012), 682-693.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%
% Trivial cases:
if ( all(f.exponents == 0) )
    % If both the exponents are trivial, then compute the integral by calling
    % the sum in smoothfun.
    out = sum(f.smoothPart);
    return

elseif ( all(f.exponents <= -1) )
    % The integral is divergent or not a number when both the exponents are
    % non-zero.

    if ( isreal(f) )

        % The sign of the smoothPart of F at the end points:
        sl = sign(get(f.smoothPart, 'lval'));
        sr = sign(get(f.smoothPart, 'rval'));

        if  ( sl == sr )
            out = sl.*inf;
        else
            out = NaN;
        end

    else
        % The sign of the real part of the smoothPart of F at the end
        % points:
        rsl = sign(real(get(f.smoothPart, 'lval')));
        rsr = sign(real(get(f.smoothPart, 'rval')));

        % The sign of the real part of the smoothPart of F at the end
        % points:
        isl = sign(imag(get(f.smoothPart, 'lval')));
        isr = sign(imag(get(f.smoothPart, 'rval')));

        if ( (rsl == rsr) && (isl == isr) )
            out = Inf + 1i*Inf;
        else
            out = NaN;
        end
    end

    return

elseif ( any(f.exponents <= -1) )

    % The integral is divergent or not a number when one of the exponents
    % are non-zero.

    if ( isreal(f) )

        % The sign of the smoothPart of F at the end points:
        sl = sign(get(f.smoothPart, 'lval'));
        sr = sign(get(f.smoothPart, 'rval'));

        s = [sl sr];
        ind = ( f.exponents <= -1 );
        out = Inf*s(ind);

    else
        % The sign of the real part of the smoothPart of F at the end
        % points:
        rsl = sign(real(get(f.smoothPart, 'lval')));
        rsr = sign(real(get(f.smoothPart, 'rval')));

        % The sign of the real part of the smoothPart of F at the end
        % points:
        isl = sign(imag(get(f.smoothPart, 'lval')));
        isr = sign(imag(get(f.smoothPart, 'rval')));

        rs = [rsl rsr];
        is = [isl isr];
        ind = ( f.exponents <= -1 );

        % The real part:
        realPart = 0;
        if ( any(rs) )
            realPart = Inf*rs(ind);
        end

        % The imaginary part:
        imagPart = 0;
        if ( any(is) )
            imagPart = Inf*is(ind);
        end

        % The sum:
        out = realPart + imagPart;
    end

    return
end

%%
% The non-trivial case:

if ( isa(f.smoothPart, 'chebtech') )

    % If the smooth part of F is a CHEBTECH, then evaluate the integral by using
    % Clenshaw-Curtis-Jacobi moments and the Chebyshev coefficients:

    % Grab the number of points for the smooth part of f:
    n = length(f);

    % Grab the exponents:
    a = f.exponents(1);

    if ( diff(f.exponents) == 0 )
        % If the exponents at the endpoints are same, then compute the
        % appropriate modified moments for Gegenbauer weights.

        r = a + .5;
        m0 = gamma(r + .5)*sqrt(pi)/gamma(r + 1);
        k = 1:floor((n-1)/2);
        % Even modified moments for M_2k = \int_{-1}^1 (1-x)^a(1+x)^a T_2k(x) dx
        % and notice that the odd moments vanish due to parity.
        m = m0*[1, cumprod((k - r - 1)./(k + r))];
        % Form the modified moments vector:
        M(1:2:n) = m;
        M(2:2:n) = 0;

    else

        % The general case:
        b = f.exponents(2);

        % Common coefficient for the modified moments:
        c1 = a + 1;
        c2 = b + 1;
        c3 = a + b + 1;
        c4 = c1 + c2;
        c5 = a - b;
        c0 = (2^c3)*beta(c1, c2);

        % Compute the hypergeometric function related to the modified moments:
        M = zeros(1,n);
        M(1) = 1;
        if ( n > 1 )
            M(2) = c5/c4;
            % Sister Celine's three-term recurrence:
            for j = 3:n
                M(j) = (2*c5*M(j-1) + (j - 2 - c4)*M(j-2)) / (c3 + j - 1);
            end
        end
        % Compute the modified moments:
        M = c0*M;

    end

    % Chebyshev coefficients of the smooth part of F:
    coeffs = get(f, 'coeffs');

    % multiplication of weights and values
    out = M*coeffs;

else
    %%
    % If f.smoothPart is not a CHEBTECH, we evaluate the integral by using
    % Gauss-Jacobi points and weights.

    % Give a sufficiently large number:
    % [TODO]: This number needs to be determined in future when other 'tech's join.
    % [TODO]: Or perhaps compute iteratively until result doesn't change?
    n = 1000;

    [x, w] = jacpts(ceil(n/2) + 1, f.exponents(2), f.exponents(1));
    out = w*feval(f.smoothPart, x);

end

end


function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p)
% CPD_TO_LAMBDA_MSG Compute lambda message (gaussian)
% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p)
% Pearl p183 eq 4.52

switch msg_type
 case 'd',
  error('gaussian_CPD can''t create discrete msgs')
 case 'g',
  self_size = CPD.sizes(end);
  if all(msg{n}.lambda.precision == 0) % no info to send on
    lam_msg.precision = zeros(self_size);
    lam_msg.info_state = zeros(self_size, 1);
    return;
  end
  cpsizes = CPD.sizes(CPD.cps);
  dpval = 1;
  Q = CPD.cov(:,:,dpval);
  Sigmai = Q;
  wmu = zeros(self_size, 1);
  for k=1:length(ps)
    pk = ps(k);
    if pk ~= p
      bk = block(k, cpsizes);
      Bk = CPD.weights(:, bk, dpval);
      m = msg{n}.pi_from_parent{k};
      Sigmai = Sigmai + Bk * m.Sigma * Bk';
      wmu = wmu + Bk * m.mu; % m.mu = u(k)
    end
  end
  % Sigmai = Q + sum_{k \neq i} B_k Sigma_k B_k'
  i = find_equiv_posns(p, ps);
  bi = block(i, cpsizes);
  Bi = CPD.weights(:,bi, dpval);

  if 0
  P = msg{n}.lambda.precision;
  if isinf(P) % inv(P)=Sigma_lambda=0
    precision_temp = inv(Sigmai);
    lam_msg.precision = Bi' * precision_temp * Bi;
    lam_msg.info_state = precision_temp * (msg{n}.lambda.mu - wmu);
  else
    A = inv(P + inv(Sigmai));
    precision_temp = P + P*A*P;
    lam_msg.precision = Bi' * precision_temp * Bi;
    self_size = length(P);
    C = eye(self_size) + P*A;
    z = msg{n}.lambda.info_state;
    lam_msg.info_state = C*z - C*P*wmu;
  end
  end

  if isinf(msg{n}.lambda.precision)
    Sigma_lambda = zeros(self_size, self_size); % infinite precision => 0 variance
    mu_lambda = msg{n}.lambda.mu; % observed_value;
  else
    Sigma_lambda = inv(msg{n}.lambda.precision);
    mu_lambda = Sigma_lambda * msg{n}.lambda.info_state;
  end
  precision_temp = inv(Sigma_lambda + Sigmai);
  lam_msg.precision = Bi' * precision_temp * Bi;
  lam_msg.info_state = Bi' * precision_temp * (mu_lambda - wmu);
end


function [Ka, pKa] = acidDissociationConstant(metAbbr, Alberty2006, metAbbrAlbertyAbbr, temp, is, chi)
% Acid dissociation constant for the different metabolite species that make up a reactant
%
% USAGE:
%
%    [Ka, pKa] = acidDissociationConstant(metAbbr, Alberty2006, metAbbrAlbertyAbbr, temp, is, chi)
%
% INPUTS:
%    metAbbr:               reconstruction reactant abbreviation
%    Alberty2006:           Basic data on the metabolite species that make
%                           up a reactant, compiled by Robert A. Alberty,
%                           Massachusetts Institute of Technology.
%                           In Print: `Robert A. Alberty, Biochemical Thermodynamics:
%                           Applications of Mathematica. John Wiley & Sons, 2006. p391-395`
%                           Online: BasicBioChemData3.nb
%                           http://library.wolfram.com/infocenter/MathSource/5704/
%    metAbbrAlbertyAbbr:    mapping from model metabolite primary key to
%                           primary key of reactants in `Alberty2006`
%
% OPTIONAL INPUT
%    temp:                  temperature (default 298.15 K)
%    is:                    ionic strength (default 0 M)
%    chi:                   electrical potential (default 0)
%
% OUTPUTS:
%    Ka:                    apparent equilibrium constants
%    pKa:                   :math:`-log_{10}(Ka)`

if ~exist('temp','var')
    temp=298.15;
end
if ~exist('is','var')
    is=0;
end
if ~exist('chi','var')
    chi=0;
end

%find the alberty abbreviation for this metabolite Abbreviation
albertyAbbr=metAbbrAlbertyAbbr(strcmp(metAbbr,metAbbrAlbertyAbbr(:,2)),3);

%make a list of alberty abbreviations
klt=size(Alberty2006,2);
allAlbertyAbbr=cell(klt,1);
for k=1:klt
    allAlbertyAbbr{k}=Alberty2006(k).abbreviation;
end
%index for matching data for the alberty abbreviation
n=find(strcmp(albertyAbbr,allAlbertyAbbr));

%find the number of species within pseudoisomer group
p=max(find(~isnan(Alberty2006(n).basicData(:,1))));

%no Legendre transformation for pH or electrical potential
Legendre     = 0;
LegendreCHI  = 0;
pHr = 7; %dummy, has no effect

[dGf0,dHf0,mf,aveHbound,aveZi,lambda,gpfnsp]=calcdGHT(Alberty2006(n).basicData(1:p,1),Alberty2006(n).basicData(1:p,2),Alberty2006(n).basicData(1:p,3),Alberty2006(n).basicData(1:p,4),pHr,is,temp,chi,Legendre,LegendreCHI);

Ka=zeros(p-1);
pKa=zeros(p-1);

gasConstant = 8.314472/1000; % kJ K-1 mol-1

%RTalpha p 49 Alberty 2003
%where alpha is the Debye-Huckel Constant
gibbscoeff = (9.20483*temp)/10^3 - (1.284668*temp^2)/10^5 + (4.95199*temp^3)/10^8;

% A <--> A- + H+
% Take into account the ionic strength effect on the Gibbs energy of a
% hydrogen ion
zi=1;
hydrogenIonistermG = -(gibbscoeff*(zi.^2)*is^0.5)/(1 + 1.6*is^0.5);

for x=1:p-1

    Ka(x)  =  exp((gpfnsp(x+1,1)-gpfnsp(x,1)-hydrogenIonistermG)/(gasConstant*temp));
    if 1
        pKa(x) =  -(gpfnsp(x+1,1)-gpfnsp(x,1)-hydrogenIonistermG)/(gasConstant*temp*log(10));
    else
        %p244 Alberty 2003 uses a slightly less accurate gas constant so slight
        %difference
        gpfnsp=Alberty2006(n).basicData(1:p,1);
        pKa(x) =  -(gpfnsp(x+1,1)-gpfnsp(x,1))/(log(10)* 8.31451 * .29815);
    end
end


function pot = combine_pots(pot1, pot2)
% COMBINE_POTS combine two potentials
% pot = combine_pots(pot1, pot2)

% Reduce both potentials before trying to combine them.
% Cf. "Stable Local computation with Conditional Gaussian Distributions", page 9
% Consider again two potentials with minimal tail

% Guarantee minimal tails. If pot1 or pot2 are minimal, they are not changed
pot1 = reduce_pot(pot1);
pot2 = reduce_pot(pot2);

%if the intersect set of these two potentials' head conts. combination is undifined
if ~isempty( myintersect(pot1.cheaddom, pot2.cheaddom) )
    return;
end

if  isempty( myintersect(pot1.domain, pot2.cheaddom) ) | isempty( myintersect(pot2.domain, pot1.cheaddom))
    % if satisfy the condition of directed combine
    pot = direct_combine_pots(pot1, pot2);
else
    % perform recursive combine
    pot = recursive_combine_pots(pot1, pot2);
end


function [ o, x, w ] = en_r2_11_1 ( n, option )

%*****************************************************************************80
%
%% EN_R2_11_1 implements the Stroud rule 11.1 for region EN_R2.
%
%  Discussion:
%
%    The rule has order
%
%      O = ( 4 * N^5 - 20 * N^4 + 140 * N^3 - 130 * N^2 + 96 * N + 15 ) / 15.
%
%    The rule has precision P = 11.
%
%    EN_R2 is the entire N-dimensional space with weight function
%
%      w(x) = exp ( - x1^2 - x2^2 ... - xn^2 )
%
%    There are two versions of each rule, chosen by setting the
%    OPTION variable to 1 or 2.
%
%    The rule as tabulated by Stenger is available for N = 2 through 20.
%    This function accepts N = 3 through 5.
%
%     N    O
%    __  ___
%     3  151
%     4  417
%     5  983
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    21 January 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Arthur Stroud,
%    Approximate Calculation of Multiple Integrals,
%    Prentice Hall, 1971,
%    ISBN: 0130438936,
%    LC: QA311.S85.
%
%  Parameters:
%
%    Input, integer N, the spatial dimension.
%    3 <= N <= 5.
%
%    Input, integer OPTION, chooses rule option 1 or 2.
%
%    Output, integer O, the order.
%
%    Output, real X(N,O), the abscissas.
%
%    Output, real W(O), the weights.
%
  if ( n < 3 | 5 < n )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'EN_R2_11_1 - Fatal error!\n' );
    fprintf ( 1, '  3 <= N <= 5 required.\n' );
    error ( 'EN_R2_11_1 - Fatal error!' )
  end

  if ( nargin < 2 )
    option = 1;
  end

  if ( option < 1 | 2 < option )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'EN_R2_11_1 - Fatal error!\n' );
    fprintf ( 1, '  1 <= OPTION <= 2 required.\n' );
    error ( 'EN_R2_11_1 - Fatal error!' )
  end

  o = ( 4 * n^5 - 20 * n^4 + 140 * n^3 - 130 * n^2 + 96 * n + 15 ) / 15;
  volume = sqrt ( pi^n );

  if ( n == 3 & option == 1 )
    u =     0.235060497367449E+01;
    v =     0.436077411927617E+00;
    w2 =    0.133584907401370E+01;
    b0 =  - 0.881591029957858E+01;
    b1 =  - 0.751996143360650E-01;
    b2 =    0.621743189471515E+01;
    b3 =    0.241426451456494E+00;
    b4 =  - 0.120709739276065E-02;
    b5 =  - 0.427751221210138E+01;
    b6 =    0.550169924840163E-01;
    b7 =    0.237084999634707E-01;
    b8 =  - 0.169791992887741E-02;
    b9 =  - 0.252266276123350E-04;
    b10 =   0.326777873717691E+01;
    b11 =   0.968469949206802E-02;
    b12 =   0.789754514877422E-03;
    b13 =   0.000000000000000E+00;
    b14 =   0.000000000000000E+00;
    b15 =   0.000000000000000E+00;
  elseif ( n == 3 & option == 2 )
    u =     0.235060497367449E+01;
    v =     0.133584907401370E+01;
    w2 =    0.436077411927617E+00;
    b0 =  - 0.141214037032900E+02;
    b1 =  - 0.803730274707282E-01;
    b2 =    0.235546545595906E+00;
    b3 =    0.888123191556611E+01;
    b4 =    0.142467131155533E-03;
    b5 =    0.582993124006494E-01;
    b6 =  - 0.561099173155661E+01;
    b7 =  - 0.204028691521686E-02;
    b8 =    0.252880089932256E-01;
    b9 =  - 0.814378678627283E-04;
    b10 =   0.804353953375146E-02;
    b11 =   0.393451849690453E+01;
    b12 =   0.171183493169724E-03;
    b13 =   0.000000000000000E+00;
    b14 =   0.000000000000000E+00;
    b15 =   0.000000000000000E+00;
  elseif ( n == 4 & option == 1 )
    u =     0.235060497367449E+01;
    v =     0.436077411927617E+00;
    w2 =    0.133584907401370E+01;
    b0 =    0.241502736147339E+03;
    b1 =  - 0.196095938531478E+00;
    b2 =  - 0.128675737999280E+03;
    b3 =    0.307568784278696E+00;
    b4 =  - 0.480908422319460E-02;
    b5 =    0.698087019367085E+02;
    b6 =    0.631837143743771E-01;
    b7 =    0.392226151971179E-01;
    b8 =  - 0.300948471646799E-02;
    b9 =  - 0.650235306755170E-04;
    b10 = - 0.386951974646715E+02;
    b11 =   0.171656829095787E-01;
    b12 =   0.139980343116450E-02;
    b13 =   0.101552487093372E-04;
    b14 =   0.222435922356439E+02;
    b15 =   0.000000000000000E+00;
  elseif ( n == 4 & option == 2 )
    u =     0.235060497367449E+01;
    v =     0.133584907401370E+01;
    w2 =    0.436077411927617E+00;
    b0 =  - 0.151944464736584E+03;
    b1 =  - 0.223498438689039E+00;
    b2 =    0.243574919068010E+00;
    b3 =    0.634373877008693E+02;
    b4 =  - 0.782065187814018E-04;
    b5 =    0.911833754536616E-01;
    b6 =  - 0.238927288245914E+02;
    b7 =  - 0.422314408318853E-02;
    b8 =    0.448218289217760E-01;
    b9 =  - 0.138053374667391E-03;
    b10 =   0.607473265800655E-02;
    b11 =   0.697375246129742E+01;
    b12 =   0.303414841680135E-03;
    b13 = - 0.314574391771792E-05;
    b14 =   0.409103498175100E-02;
    b15 =   0.000000000000000E+00;
  elseif ( n == 5 & option == 1 )
    u =     0.235060497367449E+01;
    v =     0.436077411927617E+00;
    w2 =    0.133584907401370E+01;
    b0 =    0.255885269311763E+04;
    b1 =  - 0.439598677491526E+00;
    b2 =  - 0.106541406144610E+04;
    b3 =    0.453540909054264E+00;
    b4 =  - 0.132100905623778E-01;
    b5 =    0.418606568954203E+03;
    b6 =    0.511394563043680E-01;
    b7 =    0.645581013845604E-01;
    b8 =  - 0.533417277494500E-02;
    b9 =  - 0.137981626254496E-03;
    b10 = - 0.147436933189884E+03;
    b11 =   0.304253807765057E-01;
    b12 =   0.248108698207828E-02;
    b13 =   0.113652094546015E-04;
    b14 =   0.394257407160391E+02;
    b15 =   0.331725011358320E-05;
  elseif ( n == 5 & option == 2 )
    u =     0.235060497367449E+01;
    v =     0.133584907401370E+01;
    w2 =    0.436077411927617E+00;
    b0 =  - 0.761305347548192E+03;
    b1 =  - 0.536360805019297E+00;
    b2 =    0.110669832078736E+00;
    b3 =    0.246421088923968E+03;
    b4 =  - 0.773649327968607E-03;
    b5 =    0.169088641205970E+00;
    b6 =  - 0.670700680243651E+02;
    b7 =  - 0.856090560229205E-02;
    b8 =    0.794446232770302E-01;
    b9 =  - 0.220272863263544E-03;
    b10 = - 0.373515812228225E-02;
    b11 =   0.123606544052884E+02;
    b12 =   0.537788804557843E-03;
    b13 = - 0.122101861480881E-04;
    b14 =   0.725117070759373E-02;
    b15 =   0.331725011358320E-05;
  end

  x = zeros(n,o);
  w = zeros(o,1);

  k = 0;
%
%  1 point.
%
  k = k + 1;
% x(1:n,k) = 0.0;
  w(k) = b0;
%
%  2 * N points.
%
  for i = 1 : n
    k = k + 1;
    x(i,k) = - u;
    w(k) = b1;
    k = k + 1;
    x(i,k) = + u;
    w(k) = b1;
  end
%
%  2 * N points.
%
  for i = 1 : n
    k = k + 1;
    x(i,k) = - v;
    w(k) = b2;
    k = k + 1;
    x(i,k) = + v;
    w(k) = b2;
  end
%
%  2 * N points.
%
  for i = 1 : n
    k = k + 1;
    x(i,k) = - w2;
    w(k) = b3;
    k = k + 1;
    x(i,k) = + w2;
    w(k) = b3;
  end
%
%  4 * ( N * ( N - 1 ) / 2 ) points.
%
  for i = 1 : n - 1
    for j = i + 1 : n
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = - u;
      w(k) = b4;
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = + u;
      w(k) = b4;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = - u;
      w(k) = b4;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = + u;
      w(k) = b4;
    end
  end
%
%  4 * ( N * ( N - 1 ) / 2 ) points.
%
  for i = 1 : n - 1
    for j = i + 1 : n
      k = k + 1;
      x(i,k) = - v;
      x(j,k) = - v;
      w(k) = b5;
      k = k + 1;
      x(i,k) = - v;
      x(j,k) = + v;
      w(k) = b5;
      k = k + 1;
      x(i,k) = + v;
      x(j,k) = - v;
      w(k) = b5;
      k = k + 1;
      x(i,k) = + v;
      x(j,k) = + v;
      w(k) = b5;
    end
  end
%
%  4 * ( N * ( N - 1 ) / 2 ) points.
%
  for i = 1 : n - 1
    for j = i + 1 : n
      k = k + 1;
      x(i,k) = - w2;
      x(j,k) = - w2;
      w(k) = b6;
      k = k + 1;
      x(i,k) = - w2;
      x(j,k) = + w2;
      w(k) = b6;
      k = k + 1;
      x(i,k) = + w2;
      x(j,k) = - w2;
      w(k) = b6;
      k = k + 1;
      x(i,k) = + w2;
      x(j,k) = + w2;
      w(k) = b6;
    end
  end
%
%  4 * ( N * ( N - 1 ) ) points.
%
  for i = 1 : n - 1
    for j = i + 1 : n
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = - v;
      w(k) = b7;
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = + v;
      w(k) = b7;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = - v;
      w(k) = b7;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = + v;
      w(k) = b7;
      k = k + 1;
      x(i,k) = - v;
      x(j,k) = - u;
      w(k) = b7;
      k = k + 1;
      x(i,k) = - v;
      x(j,k) = + u;
      w(k) = b7;
      k = k + 1;
      x(i,k) = + v;
      x(j,k) = - u;
      w(k) = b7;
      k = k + 1;
      x(i,k) = + v;
      x(j,k) = + u;
      w(k) = b7;
    end
  end
%
%  4 * ( N * ( N - 1 ) ) points.
%
  for i = 1 : n - 1
    for j = i + 1 : n
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = - w2;
      w(k) = b8;
      k = k + 1;
      x(i,k) = - u;
      x(j,k) = + w2;
      w(k) = b8;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = - w2;
      w(k) = b8;
      k = k + 1;
      x(i,k) = + u;
      x(j,k) = + w2;
      w(k) = b8;
      k = k + 1;
      x(i,k) = - w2;
      x(j,k) = - u;
      w(k) = b8;
      k = k + 1;
      x(i,k) = - w2;
      x(j,k) = + u;
      w(k) = b8;
      k = k + 1;
      x(i,k) = + w2;
      x(j,k) = - u;
      w(k) = b8;
      k = k + 1;
      x(i,k) = + w2;
      x(j,k) = + u;
      w(k) = b8;
    end
  end
%
%  8 * ( N * ( N - 1 ) * ( N - 2 ) / 6 ) points.
%
  for i = 1 : n - 2
    for j = i + 1 : n - 1
      for l = j + 1 : n
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - u;
        x(l,k) = - u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - u;
        x(l,k) = + u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + u;
        x(l,k) = - u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + u;
        x(l,k) = + u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - u;
        x(l,k) = - u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - u;
        x(l,k) = + u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + u;
        x(l,k) = - u;
        w(k) = b9;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + u;
        x(l,k) = + u;
        w(k) = b9;
      end
    end
  end
%
%  8 * ( N * ( N - 1 ) * ( N - 2 ) / 6 ) points.
%
  for i = 1 : n - 2
    for j = i + 1 : n - 1
      for l = j + 1 : n
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = - v;
        x(l,k) = - v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = - v;
        x(l,k) = + v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = + v;
        x(l,k) = - v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = + v;
        x(l,k) = + v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = - v;
        x(l,k) = - v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = - v;
        x(l,k) = + v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = + v;
        x(l,k) = - v;
        w(k) = b10;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = + v;
        x(l,k) = + v;
        w(k) = b10;
      end
    end
  end
%
%  8 * ( N * ( N - 1 ) * ( N - 2 ) / 6 ) points.
%
  for i = 1 : n - 2
    for j = i + 1 : n - 1
      for l = j + 1 : n
        k = k + 1;
        x(i,k) = - w2;
        x(j,k) = - w2;
        x(l,k) = - w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = - w2;
        x(j,k) = - w2;
        x(l,k) = + w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = - w2;
        x(j,k) = + w2;
        x(l,k) = - w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = - w2;
        x(j,k) = + w2;
        x(l,k) = + w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = + w2;
        x(j,k) = - w2;
        x(l,k) = - w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = + w2;
        x(j,k) = - w2;
        x(l,k) = + w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = + w2;
        x(j,k) = + w2;
        x(l,k) = - w2;
        w(k) = b11;
        k = k + 1;
        x(i,k) = + w2;
        x(j,k) = + w2;
        x(l,k) = + w2;
        w(k) = b11;
      end
    end
  end
%
%  8 * ( N * ( N - 1 ) * ( N - 2 ) / 2 ) points.
%
  for i = 1 : n - 2
    for j = i + 1 : n - 1
      for l = j + 1 : n
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - u;
        x(l,k) = - v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - u;
        x(l,k) = + v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + u;
        x(l,k) = - v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + u;
        x(l,k) = + v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - u;
        x(l,k) = - v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - u;
        x(l,k) = + v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + u;
        x(l,k) = - v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + u;
        x(l,k) = + v;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - v;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = - v;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + v;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - u;
        x(j,k) = + v;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - v;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = - v;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + v;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + u;
        x(j,k) = + v;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = - u;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = - u;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = + u;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = - v;
        x(j,k) = + u;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = - u;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = - u;
        x(l,k) = + u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = + u;
        x(l,k) = - u;
        w(k) = b12;
        k = k + 1;
        x(i,k) = + v;
        x(j,k) = + u;
        x(l,k) = + u;
        w(k) = b12;
      end
    end
  end
%
%  16 * ( N * ( N - 1 ) * ( N - 2 ) * ( N - 3 ) / 24 ) points.
%
  for i = 1 : n - 3
    for j = i + 1 : n - 2
      for l = j + 1 : n - 1
        for m = l + 1 : n
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = - u;
          x(l,k) = - u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = - u;
          x(l,k) = - u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = - u;
          x(l,k) = + u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = - u;
          x(l,k) = + u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = + u;
          x(l,k) = - u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = + u;
          x(l,k) = - u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = + u;
          x(l,k) = + u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = - u;
          x(j,k) = + u;
          x(l,k) = + u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = - u;
          x(l,k) = - u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = - u;
          x(l,k) = - u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = - u;
          x(l,k) = + u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = - u;
          x(l,k) = + u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = + u;
          x(l,k) = - u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = + u;
          x(l,k) = - u;
          x(m,k) = + u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = + u;
          x(l,k) = + u;
          x(m,k) = - u;
          w(k) = b13;
          k = k + 1;
          x(i,k) = + u;
          x(j,k) = + u;
          x(l,k) = + u;
          x(m,k) = + u;
          w(k) = b13;
        end
      end
    end
  end
%
%  16 * ( N * ( N - 1 ) * ( N - 2 ) * ( N - 3 ) / 24 ) points.
%
  for i = 1 : n - 3
    for j = i + 1 : n - 2
      for l = j + 1 : n - 1
        for m = l + 1 : n
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = - v;
          x(l,k) = - v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = - v;
          x(l,k) = - v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = - v;
          x(l,k) = + v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = - v;
          x(l,k) = + v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = + v;
          x(l,k) = - v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = + v;
          x(l,k) = - v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = + v;
          x(l,k) = + v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = - v;
          x(j,k) = + v;
          x(l,k) = + v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = - v;
          x(l,k) = - v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = - v;
          x(l,k) = - v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = - v;
          x(l,k) = + v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = - v;
          x(l,k) = + v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = + v;
          x(l,k) = - v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = + v;
          x(l,k) = - v;
          x(m,k) = + v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = + v;
          x(l,k) = + v;
          x(m,k) = - v;
          w(k) = b14;
          k = k + 1;
          x(i,k) = + v;
          x(j,k) = + v;
          x(l,k) = + v;
          x(m,k) = + v;
          w(k) = b14;
        end
      end
    end
  end
%
%  All quintuples UUUUU with 32 sign combinations.
%
  for i1 = 1 : n - 4
    for i2 = i1 + 1 : n - 3
      for i3 = i2 + 1 : n - 2
        for i4 = i3 + 1 : n - 1
          for i5 = i4 + 1 : n
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = - u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = - u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = - u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = - u;
            x(i5,k) = + u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = - u;
            w(k) = b15;
            k = k + 1;
            x(i1,k) = + u;
            x(i2,k) = + u;
            x(i3,k) = + u;
            x(i4,k) = + u;
            x(i5,k) = + u;
            w(k) = b15;
          end
        end
      end
    end
  end

  return
end