% Minimize sidelobe level of an array with arbitrary 2-D geometry
% "Convex optimization examples" lecture notes (EE364) by S. Boyd
% "Antenna array pattern synthesis via convex optimization"
% by H. Lebret and S. Boyd
% (figures are generated)
%
% Designs an antenna array such that:
% - it minimizes sidelobe level outside the beamwidth of the pattern
% - it has a unit sensitivity at some target direction
% - it has nulls (zero sensitivity) at specified direction(s) (optional)
%
% This is a convex problem (after sampling it can be formulated as an SOCP).
%
%   minimize   max |y(theta)|     for theta outside the beam
%       s.t.   y(theta_tar) = 1
%              y(theta_null) = 0  (optional)
%
% where y is the antenna array gain pattern (complex function) and
% variables are w (antenna array weights or shading coefficients).
% Gain pattern is a linear function of w: y(theta) = w'*a(theta)
% for some a(theta) describing antenna array configuration and specs.
%
% Written for CVX by Almir Mutapcic 02/02/06

% select array geometry
ARRAY_GEOMETRY = '2D_RANDOM';
% ARRAY_GEOMETRY = '1D_UNIFORM_LINE';
% ARRAY_GEOMETRY = '2D_UNIFORM_LATTICE';

% select if the optimal array pattern should enforce nulls or not
HAS_NULLS = 0; % HAS_NULLS = 1;

%********************************************************************
% problem specs
%********************************************************************
lambda = 1;           % wavelength
theta_tar = 60;       % target direction (should be an integer -- discretization)
half_beamwidth = 10;  % half beamwidth around the target direction

% angles where we want nulls (optional)
if HAS_NULLS
  theta_nulls = [95 110 120 140 225];
end

%********************************************************************
% random array of n antenna elements
%********************************************************************
if strcmp( ARRAY_GEOMETRY, '2D_RANDOM' )
  % set random seed to repeat experiments
  rand('state',0);

  % (uniformly distributed on [0,L]-by-[0,L] square)
  n = 40;
  L = 5;
  loc = L*rand(n,2);
  angleRange = 360;

%********************************************************************
% uniform 1D array with n elements with inter-element spacing d
%********************************************************************
elseif strcmp( ARRAY_GEOMETRY, '1D_UNIFORM_LINE' )
  % (unifrom array on a line)
  n = 30;
  d = 0.45*lambda;
  loc = [d*[0:n-1]' zeros(n,1)];
  angleRange = 180;

%********************************************************************
% uniform 2D array with m-by-m element with d spacing
%********************************************************************
elseif strcmp( ARRAY_GEOMETRY, '2D_UNIFORM_LATTICE' )
  m = 6; n = m^2;
  d = 0.45*lambda;

  loc = zeros(n,2);
  for x = 0:m-1
    for y = 0:m-1
      loc(m*y+x+1,:) = [x y];
    end
  end
  loc = loc*d;
  angleRange = 360;

else
  error('Undefined array geometry')
end

%********************************************************************
% construct optimization data
%********************************************************************
% build matrix A that relates w and y(theta), ie, y = A*w
theta = [1:angleRange]';
A = kron(cos(pi*theta/180), loc(:,1)') + kron(sin(pi*theta/180), loc(:,2)');
A = exp(2*pi*i/lambda*A);

% target constraint matrix
[diff_closest, ind_closest] = min( abs(theta - theta_tar) );
Atar = A(ind_closest,:);

% nulls constraint matrix
if HAS_NULLS
  Anull = []; ind_nulls = [];
  for k = 1:length(theta_nulls)
    [diff_closest, ind_closest] = min( abs(theta - theta_nulls(k)) );
    Anull = [Anull; A(ind_closest,:)];
    ind_nulls = [ind_nulls ind_closest];
  end
end

% stopband constraint matrix
ind = find(theta <= (theta_tar-half_beamwidth) | ...
           theta >= (theta_tar+half_beamwidth) );
if HAS_NULLS, ind = setdiff(ind,ind_nulls); end;
As = A(ind,:);

%********************************************************************
% optimization problem
%********************************************************************
cvx_begin
  variable w(n) complex
  minimize( max( abs(As*w) ) )
  subject to
    Atar*w == 1;   % target constraint
    if HAS_NULLS   % nulls constraints
      Anull*w == 0;
    end
cvx_end

% check if problem was successfully solved
disp(['Problem is ' cvx_status])
if ~strfind(cvx_status,'Solved')
  return
end

min_sidelobe_level = 20*log10( max(abs(As*w)) );
fprintf(1,'The minimum sidelobe level is %3.2f dB.\n\n',...
          min_sidelobe_level );

%********************************************************************
% plots
%********************************************************************
figure(1), clf
plot(loc(:,1),loc(:,2),'o')
title('Antenna locations')

% plot array pattern
if angleRange == 180,
    theta = [1:360]';
    A = [ A; -A ];
end
y = A*w;
figure(2), clf
ymin = floor(0.1*min_sidelobe_level)*10-10; ymax = 0;
plot([1:360], 20*log10(abs(y)), ...
     [theta_tar theta_tar],[ymin ymax],'r--',...
     [theta_tar+half_beamwidth theta_tar+half_beamwidth],[ymin ymax],'g--',...
     [theta_tar-half_beamwidth theta_tar-half_beamwidth],[ymin ymax],'g--');
if HAS_NULLS % add lines that represent null positions
  hold on;
  for k = 1:length(theta_nulls)
    plot([theta_nulls(k) theta_nulls(k)],[ymin ymax],'m--');
  end
  hold off;
end
xlabel('look angle'), ylabel('mag y(theta) in dB');
axis([0 360 ymin ymax]);

% polar plot
figure(3), clf
zerodB = -ymin;
dBY = 20*log10(abs(y)) + zerodB;
ind = find( dBY <= 0 ); dBY(ind) = 0;
plot(dBY.*cos(pi*theta/180), dBY.*sin(pi*theta/180), '-');
axis([-zerodB zerodB -zerodB zerodB]), axis('off'), axis('square')
hold on
plot(zerodB*cos(pi*theta/180),zerodB*sin(pi*theta/180),'k:') % 0 dB
plot( (min_sidelobe_level + zerodB)*cos(pi*theta/180), ...
      (min_sidelobe_level + zerodB)*sin(pi*theta/180),'k:')  % min level
text(-zerodB,0,'0 dB')
tt = text(-(min_sidelobe_level + zerodB),0,sprintf('%0.1f dB',min_sidelobe_level));
set(tt,'HorizontalAlignment','right');
theta_1 = theta_tar+half_beamwidth;
theta_2 = theta_tar-half_beamwidth;
plot([0 55*cos(theta_tar*pi/180)], [0 55*sin(theta_tar*pi/180)], 'k:')
plot([0 55*cos(theta_1*pi/180)], [0 55*sin(theta_1*pi/180)], 'k:')
plot([0 55*cos(theta_2*pi/180)], [0 55*sin(theta_2*pi/180)], 'k:')
if HAS_NULLS % add lines that represent null positions
  for k = 1:length(theta_nulls)
    plot([0 55*cos(theta_nulls(k)*pi/180)], ...
         [0 55*sin(theta_nulls(k)*pi/180)], 'k:')
  end
end
hold off


function [ px, pxp ] = least_val2 ( nterms, b, c, d, x )

%*****************************************************************************80
%
%% LEAST_VAL2 evaluates a least squares polynomial defined by LEAST_SET.
%
%  Discussion:
%
%    This routine also computes the derivative of the polynomial.
%
%    The least squares polynomial is assumed to be defined as a sum
%
%      P(X) = SUM ( I = 1 to NTERMS ) D(I) * P(I-1,X)
%
%    where the orthogonal basis polynomials P(I,X) satisfy the following
%    three term recurrence:
%
%      P(-1,X) = 0
%      P(0,X) = 1
%      P(I,X) = ( X - B(I-1) ) * P(I-1,X) - C(I-1) * P(I-2,X)
%
%    Therefore, the least squares polynomial can be evaluated as follows:
%
%    If NTERMS is 1, then the value of P(X) is D(1) * P(0,X) = D(1).
%
%    Otherwise, P(X) is defined as the sum of NTERMS > 1 terms.  We can
%    reduce the number of terms by 1, because the polynomial P(NTERMS,X)
%    can be rewritten as a sum of polynomials;  Therefore, P(NTERMS,X)
%    can be eliminated from the sum, and its coefficient merged in with
%    those of other polynomials.  Repeat this process for P(NTERMS-1,X)
%    and so on until a single term remains.
%    P(NTERMS,X) of P(NTERMS-1,X)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    24 May 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer NTERMS, the number of terms in the least squares
%    polynomial.  NTERMS must be at least 1.  The value of NTERMS
%    may be reduced from the value given to LEAST_SET.
%    This will cause LEAST_VAL to evaluate the least squares polynomial
%    of the lower degree specified.
%
%    Input, real B(NTERMS), C(NTERMS), D(NTERMS), the information
%    computed by LEAST_SET.
%
%    Input, real X, the point at which the least squares polynomial
%    is to be evaluated.
%
%    Output, real PX, PXP, the value and derivative of the least
%    squares polynomial at X.
%
  px = d(nterms);
  pxp = 0.0;
  pxm1 = 0.0;
  pxpm1 = 0.0;

  for i = nterms-1 : -1 : 1

    pxm2 = pxm1;
    pxpm2 = pxpm1;
    pxm1 = px;
    pxpm1 = pxp;

    if ( i == nterms-1 )
      px = d(i) + ( x - b(i) ) * pxm1;
      pxp = pxm1 + ( x - b(i) ) * pxpm1;
    else
      px = d(i) + ( x - b(i) ) * pxm1 - c(i+1) * pxm2;
      pxp = pxm1 + ( x - b(i) ) * pxpm1 - c(i+1) * pxpm2;
    end

  end

  return
end


function value = r8mat_maxcol_minrow ( m, n, a )

%*****************************************************************************80
%
%% R8MAT_MAXCOL_MINROW gets the maximum column minimum row of an R8MAT.
%
%  Discussion:
%
%    value = max ( 1 <= I <= N ) ( min ( 1 <= J <= M ) A(I,J) )
%
%    For a given matrix, MAT_MAXCOL_MINROW <= MAT_MINROW_MAXCOL
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    11 December 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the number of rows in A.
%
%    Input, integer N, the number of columns in A.
%
%    Input, real A(M,N), the matrix.
%
%    Output, real VALUE, the maximum column
%    minimum row entry of A.
%
  value = max ( min ( a(1:m,1:n)' ) );

  return
end


function xCommon=findLongestCommonSubsequence(x,y)
%%FINDLONGESTCOMMONSUBSEQUENCE Given two vectors of numbers, characters,
%              etc., find the longest sequence of elements in both of them.
%              The elements must appear in order need NOT BE CONSECUTIVE.
%
%INPUTS:      x,y  Two vectors.
%
%OUTPUTS: xCommon  The longest common subsequence shared by the vectors.
%                  The elements in the subsequence need not be consecutive.
%                  For example, the longest common subsequence of "dunkin"
%                  and "doughnuts" is "dun".
%
%The algorithm is taken from Chapter 15.4 of [1], but modified so that the
%sequence comes out in order and to deal with Matlab addressing things from
%1 instead of 0.
%
%REFERENCES:
%[1] T. H. Cormen, C. E. Leiserson, R. L. Rivest, and C. Stein,
%    Introduction to Algorithms, 2nd ed. Cambridge, MA: The MIT Press,
%    2001.
%
%October 2014 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

m=length(x);
n=length(y);

c=zeros(m+1,n+1);
for i=m:-1:1
    for j=n:-1:1
        if(x(i)==y(j))
            c(i,j)=c(i+1,j+1)+1;
        else
            c(i,j)=max(c(i,j+1),c(i+1,j));
        end
    end
end

i=1;
j=1;
%Setting xCommon to x rather than alocating with zeros assured that xCommon
%will have the same type and shape as x. This is good when x is a character
%string.
xCommon=x;
numFound=0;
while(i<=m&&j<=n)
    if(x(i)==y(j))
       numFound=numFound+1;
       xCommon(numFound)=x(i);
       i=i+1;
       j=j+1;
    elseif(c(i+1,j)>=c(i,j+1))
        i=i+1;
    else
        j=j+1;
    end
end

%Get rid of extra elements in xCommon.
xCommon=xCommon(1:numFound);
end

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


function F=HessTaylor(deltaT,dadx,d2adx,method)
%%HESSTAYLOR Simulate a nonlinear continuous-time random process specified
%            by the Langevin equation forward in time by a step-size of
%            deltaT using a Taylor scheme.
%
%INPUTS: deltaT The size of the single step over which to generate the
%               state transition matrix.
%          dadx A xDimXxDim matrix of the derivative of the drift function
%               with respect to the state at state xCur and time curT.
%         d2adx A xDimXxDimXxDim matrix of the second derivative of the
%               drift function with respect to the state at state xCur and
%               time curT. The value at point (m,k,l) represents
%               d2a(m)/dx(k)dx(l). If not provided, this is assumed to be
%               zero.
%        method Set to 0 for the shorter Euler-Maruyama expansion,
%               otherwise will the Taylor expansion will be used (default).
%
%OUTPUTS: H The Hessian matrix of a nonlinear continuous-time random
%           process specified by the Langevin equation forward in time by a
%           step-size of deltaT using a strong Taylor scheme.
%
%The second derivative state prediction matrix is derived from the
%stochastic order 1.5 Taylor scheme described in 10.4 of [1].
%
%REFERENCES:
%[1] P. E. Kloeden and E. Platen, Numerical Solution of Stochastic
%    Differential Equations. Berlin: Springer, 1999.
%
%April 2015 David Karnick, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

xDim=size(dadx,1);
if(nargin<4||isempty(method))
    method=1;
end

if(method==0)
    F=deltaT*d2adx;
else
    %Assumes 3rd derivative is zero
    term1=zeros(xDim,xDim,xDim);
    term2=zeros(xDim,xDim,xDim);
    term3=zeros(xDim,xDim,xDim);
    for m=1:xDim
        term1(:,:,m)=d2adx(:,:,m)*dadx;
        term2(:,m,:)=d2adx(:,:,m)*dadx;
        term3(:,:,m)=dadx*d2adx(:,:,m);
    end

    F=deltaT*d2adx+(deltaT^2/2)*(term1+term2+term3);
end

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


function mind = dijkstra_distance ( nv, ohd )

%*****************************************************************************80
%
%% DIJKSTRA_DISTANCE uses Dijkstra's minimum distance algorithm.
%
%  Discussion:
%
%    We essentially build a tree.  We start with only node 0 connected
%    to the tree, and this is indicated by setting CONNECTED(0) = 1.
%
%    We initialize MIND(I) to the one step distance from node 0 to node I.
%
%    Now we search among the unconnected nodes for the node MV whose minimum
%    distance is smallest, and connect it to the tree.  For each remaining
%    unconnected node I, we check to see whether the distance from 0 to MV
%    to I is less than that recorded in MIND(I), and if so, we can reduce
%    the distance.
%
%    After NV-1 steps, we have connected all the nodes to 0, and computed
%    the correct minimum distances.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 July 2010
%
%  Author:
%
%    Original C version by Norm Matloff, CS Dept, UC Davis.
%    This MATLAB version by John Burkardt.
%
%  Parameters:
%
%    Input, integer OHD(NV,NV), the distance of the direct link between
%    nodes I and J.
%
%    Output, integer MIND(NV), the minimum distance from node 1 to each node.
%

%
%  Start out with only node 1 connected to the tree.
%
  connected(1) = 1;
  connected(2:nv) = 0;
%
%  Initialize the minimum distance to the one-step distance.
%
  mind(1:nv) = ohd(1,1:nv);
%
%  Attach one more node on each iteration.
%
  for step = 2 : nv
%
%  Find the nearest unconnected node.
%
    [ md, mv ] = find_nearest ( nv, mind, connected );

    if ( mv == - 1 )
      fprintf ( 1, '\n' );
      fprintf ( 1, 'DIJKSTRA_DISTANCE - Warning!\n' );
      fprintf ( 1, '  Search terminated early.\n' );
      fprintf ( 1, '  Graph might not be connected.\n' );
      return
    end
%
%  Mark this node as connected.
%
    connected(mv) = 1;
%
%  Having determined the minimum distance to node MV, see if
%  that reduces the minimum distance to other nodes.
%
    mind = update_mind ( nv, mv, connected, ohd, mind );

  end

  return
end


function vol = hist_vol(ticker, N)
% HIST_VOL          Calculate historical volatility
%   vol = hist_vol(ticker, N) is used to calculate the historical
%   volatility for the underlying asset specified in TICKER over N trading
%   days.  If N is not specified, a default of 20 trading days will be
%   used.
%
%   INPUTS
%       ticker --> A string or cell array of strings specifying the ticker
%                  symbols for the underlying assets to use.
%
%       N --> An integer specifying the number of days to use in the
%             volatility calculationg
%
%   OUTPUT
%       The function will return the historical volatility for each of the
%       tickers passed to the function
%
%   NOTES
%       This program uses the function 'hist_stock_data.m', which downloads
%       historical stock data to use for the volatility calculations.
%       Therefore, you must also download this function from my File
%       Exchange and place it in the same directory as this function.
%
%       The historical volatility is calculated by using the closing prices
%       of each trading day.  Additionally, one year of historical stock
%       data will be downloaded, limiting N to a maximum of roughly 252 (as
%       there are about 252 trading days in a year).  If the user wishes to
%       allow larger N, changes must be made to the code when creating the
%       variable 'start_date'.

% Created by Josiah Renfree
% July 20, 2009

% Error checking
if nargin == 0          % If no inputs provided
    error('Please provide at least one ticker symbol')
elseif nargin > 2       % If too many inputs provided
    error('Function accepts no more than 2 inputs')
elseif ~ischar(ticker) && ~iscell(ticker)   % If ticker input is wrong type
    error('Ticker input must be either a string or cell array of strings')
elseif nargin == 1      % If N not supplied, use default
    N = 20;
elseif ~isnumeric(N) || length(N) > 1  % If N is supplied, but is wrong type
    error('N must be a single integer value')
end

% If only one ticker given, convert to cell array
if ~iscell(ticker)
    ticker = {ticker};
end

% Cycle through each ticker and calculate historical volatility
vol = zeros(length(ticker), 1);
for i = 1:length(ticker)
    % Clear for loop variables for next iteration
    clear curr_date start_date data closing log_change stdev

    % Create date strings to pass to hist_stock_data function
    curr_date = datestr(now, 'ddmmyyyy');       % get current date string
    start_date = datestr(now-365, 'ddmmyyyy');  % go back 1 year

    % First step is to download historical stock data for the ticker
    data = hist_stock_data(start_date, curr_date, ticker{i});
    closing = data.Close;   % Use only closing data

    % Calculate the percentage change over the past N trading days
    log_change = log(closing(2:N+1)./closing(1:N));

    % Get standard deviation of that change
    stdev = std(log_change);

    % Now normalize to annual volatility
    vol(i) = stdev*sqrt(252);
end


% Simple 1st order RC transient response:
% File:  rctime.m
% 9/19/02
%
clear;clc
%
K=1e3;uF=1e-6;us=1e-6;ms=1e-3;
%
R1=20*K;R2=40*K;C1=0.5*uF;Ein=1;E1=1;
%
U=1;N=1;M=1;Y=1;
%
A1=[1/R1+1/R2 1;1 0];
%
B2=[0 Ein/R1;E1 0];
%
P=C1;
%
% Template matrix equations:
%
V=A1\B2;H=V(U+1:U+N,1:N+M);AB=inv(P)*H;I=eye(N);

A=AB(1:N,1:N);B=AB(1:N,N+1:N+M);
D=V(Y:Y,1:N);E=V(Y:Y,N+1:N+M);
%
% Display A, B, D, & E
A
B
D
E
%
Rp=R1*R2/(R1+R2);
dt=500*us;kmax=100;Ein=4.5; % Ein can be changed after A, B, D, E have been computed.
%dt=100*us;kmax=500;Ein=4.5; % Try this dt after using the dt above.
Vc=zeros(1,kmax);Vo=zeros(1,kmax); % Vo(k) = Vc(k);
%
for k=2:kmax
   Vc(k)=(A*Vc(k-1)+B*Ein)*dt+Vc(k-1);
   Vo(k)=D*Vc(k)+E*Ein;
   T(k)=k*dt;
   F(k)=(Ein*Rp/R1)*(1-exp(-T(k)/(Rp*C1))); % F(k) = inverse LaPlace tranform
end
%
h=plot(T/ms,Vo,'k',T/ms,F,'r');
set(h,'LineWidth',2);
grid on
xlabel('Time (ms)');
ylabel('Volts');
title('RC Time Response');
legend('Vo(k)','F(k)');
figure(1);
%
% Note that difference between F(k) and the time iteration Vo(k).  This can be reduced by
% decreasing dt with a corresponding increase in kmax to retain the same sweep time.
% For example, if dt = 250us, kmax should be set to 200.


function out = jaccoeffs(f, n, a, b)
%JACCOEFFS   Jacobi polynomial coefficients of a CHEBFUN.
%   A = JACCOEFFS(F, N, ALPHA, BETA) returns the first N+1 coefficients in the
%   Jacobi series expansion of the CHEBFUN F, so that such that F approximately
%   equals A(1) J_0(x) + ... + A(N+1) J_N(x) where J_N(x) denotes the N-th
%   Jacobi polynomial with parameters ALPHA and BETA. A is a column vector.
%
%   If F is smooth (i.e., numel(f.funs) == 1), then A = JACCOEFFS(F, ALPHA,
%   BETA) will assume that N = length(F).
%
%   JACCOEFFS does not support quasimatrices.
%
% See also CHEBCOEFFS, LEGCOEFFS.

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

if ( (numel(f(1).funs) == 1) && (nargin < 4) )
    b = a;
    a = n;
    n = length(f);
elseif ( isempty(n) )
    n = length(f);
end

if ( numel(f) > 1 )
    out = zeros(n, numel(f));
    f = cheb2cell(f);
    for k = 1:numel(f)
        out(:,k) = jaccoeffs(f{k}, n, a, b);
    end
    return
end

%%
% Special cases:
if ( a == 0 && b == 0 )
    out = legcoeffs(f, n);
    return
elseif ( a == -.5 && b == -.5 )
    out = chebcoeffs(f, n, 'kind', 1);
    nn = 0:(n-2);
    scl = repmat([1 ; cumprod((nn'+.5)./(nn'+1))], 1, size(out, 2));
    out = out./scl;
    return
elseif ( a == .5 && b == .5 )
    out = chebcoeffs(f, n, 'kind', 2);
    nn = 0:(n-2);
    scl = repmat([1 ; cumprod((nn'+1.5)./(nn'+1))], 1, size(out, 2));
    out = (1:n)'.*out./scl;
    return
end

%%
if ( numel(f.funs) == 1 )

    % Compute Jacobi coefficients of the single fun.
    out = jaccoeffs(f.funs{1}, n, a, b);

else

    % Jacobi-Vandermonde matrix:
    Enorm = jacpoly(0:n-1, a, b, f.domain);

    % Compute the projection (with correct scaling):
    out = Enorm \ f;

end

end


function error = vennX( data, resolution )
%
% function error = vennX( data, resolution )
%
% vennX - draws an area proportional venn diagram
%
% Draws a venn diagram (either two or three set) using
% circles, where the area of each region is proportional
% to the input values.
%
% INPUT:
%      data - a vector of counts for each set partition
%
%          For a two circle diagram:
%            data is a three element vector of:
%              |A|
%              |A and B|
%              |B|
%
%          For a three circle diagram:
%            data is a seven element vector of:
%               |A|
%               |A and B|
%               |B|
%               |B and C|
%               |C|
%               |C and A|
%               |A and B and C|
%
%       resolution - A measure of accuracy on the image,
%            typical values are within 1/100 to 1/1000 of
%            the maximum partition count.  Note that smaller
%            resolutions take longer compute time.
%
% OUTPUT:
%     error - the difference in area of each partition
%             between the actual area and the input vector
%
% EXAMPLES:
%
%     vennX( [ 106 26 257 ], .05 )
%
%     vennX( [ 75 143 210 ], .1 )
%
%     vennX( [ 16 3 10 6 19 8 3 ], .05 )
%
%
% COMMENTS:
%
%     The implementation is trivial, for the two circle case, two circles
%       are drawn to scale and moved closer and closer together until the
%       overlap is 'near' to the desired intersection. For the three
%       circle case, it is repeated three times, once for each pair of
%       circles.  Hence the two circle case is almost exact, whereas the
%       three circle case has much more error since the area |A and B and C|
%       is derived.  This means that large variations from random, especially
%       close to zero, will have larger errors, for example
%
%           vennX( [ 20 10 20 10 20 10 0], .1 )
%
%       as opposed to
%
%           vennX( [ 20 10 20 10 20 10 10], .1 )
%
% ENHANCEMENTS
%
%     The implementation could be sped up tremendously using a MRA
%     (multi-resolutional analysis) type algorithm.  e.g. start with a
%     resolution of .5 and find the distance between the circles, then use
%     that as a seed for a resolution of .1, then .05, .01, etc.
%
%     The error vector could be used as a measure to 'perturb' the position
%     of the third circle as to minimize the error.  This could be done
%     with a simple gradient descent method.  This would help the
%     exceptions described above where the distribution deviates from
%     random.
%
%     When small mishapen areas are drawn, the text does not match up, e.g.
%        vennX( [ 15 143 210 ], .1 )
%
%
%  Original implementation and method by Jeremy Heil, for the Order of
%  the Red Monkey, and the Tengu
%
%  Oct. 2004
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

   figure;

   if length( data ) == 3
      dist = venn2( data(1), data(2), data(3), resolution );
      error = plot_venn2( data(1), data(2), data(3), resolution, dist );
      error = data - error';
   elseif length( data ) == 7
       %get the pairwise distance of each circle center from each other
       dist_A_B = venn2( data(1)+data(6), data(2)+data(7), data(3)+data(4), resolution );
       dist_B_C = venn2( data(3)+data(2), data(4)+data(7), data(5)+data(6), resolution );
       dist_A_C = venn2( data(1)+data(2), data(6)+data(7), data(4)+data(5), resolution );

       error = plot_venn3( data(1), data(2), data(3), data(4), data(5), data(6), data(7), ...
           resolution, dist_A_B, dist_B_C, dist_A_C );
       error = data - error';
   else
       'vennX error, data vector must be of length 3 or 7'
   end

    %change the colormap so that the background is white
    k = colormap;
    k = [ 1 1 1; k ];
    colormap(k)
    axis off

function error = plot_venn3( a, b, c, d, e, f, g, resolution, dist_A_B, dist_B_C, dist_A_C )

    r1 = sqrt( (a+b+f+g)/pi );
    r2 = sqrt( (b+c+d+g)/pi );
    r3 = sqrt( (d+e+f+g)/pi );

    %
    % Using a little geometry, think of the three circle's centers
    % as vertecies of a triangle.
    %
    y = ( dist_A_C^2 - dist_B_C^2 + dist_A_B^2 ) / 2 / dist_A_B;

    size_x = max( r1 + dist_A_B + r2, 2*r3 );
    size_y = max( r1, r2 ) + sqrt( dist_A_C^2 - y^2 ) + r3;

    %find the circle centers
    center1_x = r1;
    center1_y = max( r1, r2 );
    center2_x = r1 + dist_A_B;
    center2_y = center1_y;
    center3_x = r1 + y;
    center3_y = center1_y + sqrt( dist_A_C^2 - y^2 );

    [X,Y] = meshgrid( 0:resolution:size_x, 0:resolution:size_y );

    %draw the circles
    img = zeros( size(Y,1), size(Y,2) );

    img = img + 2 .* ( (X - center1_x).^2 + (Y - center1_y).^2 < r1^2 );
    img = img + 4 .* ( (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 );
    img = img + 6 .* ( (X - center3_x).^2 + (Y - center3_y).^2 < r3^2 );

    clf
    imagesc(img)
    hold on

    %add the numbers and compute the error for each partition
    error = [];

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 > r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 > r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( a ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 > r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( b ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 > r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 > r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( c ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 > r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 < r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( d ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 > r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 > r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 < r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( e ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 > r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 < r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( f ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 ), ...
           (X - center3_x).^2 + (Y - center3_y).^2 < r3^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( g ) );
    set( h, 'FontWeight', 'bold' )

function error = plot_venn2( a, b, c, resolution, dist )

    r1 = sqrt( (a+b)/pi );
    r2 = sqrt( (b+c)/pi );

    size_x = r1 + dist + r2;
    size_y = max( 2*r1, 2*r2 );

    center1_x = r1;
    center1_y = size_y/2;
    center2_x = r1 + dist;
    center2_y = size_y/2;;

    [X,Y] = meshgrid( 0:resolution:size_x, 0:resolution:size_y );

    %draw the two circles and the overlap region
    img = zeros( size(Y,1), size(Y,2) );

    img = img + 2 .* ( (X - center1_x).^2 + (Y - center1_y).^2 < r1^2 );
    img = img + 4 .* ( (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 );

    imagesc(img)
    hold on

    %
    % We want to draw the numbers at the center of mass
    % do this by computing the average x and y coordinates of
    % the center of each partition piece.
    %
    % Compute the error for each partition as the difference
    % between the area we meant to draw and the actual area
    % that was drawn
    %
    error = [];
    tmp = and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 > r2^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( a ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( b ) );
    set( h, 'FontWeight', 'bold' )

    tmp = and( ...
           (X - center1_x).^2 + (Y - center1_y).^2 > r1^2, ...
           (X - center2_x).^2 + (Y - center2_y).^2 < r2^2 );
    [ i,j ] = find( tmp > 0 );
    error = [ error; sum(sum(tmp)) * resolution^2 ];
    text_x = mean(j);
    text_y = mean(i);
    h = text( text_x, text_y, num2str( c ) );
    set( h, 'FontWeight', 'bold' )

function dist = venn2( a, b, c, resolution )
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %VENN2
    %  dist = venn2( a, b, c, resolution )
    %
    % Computes the distance between the centers of
    % the two venn diagram circles.
    %
    % a          - values of A
    % b          - value of A and B
    % c          - value of B
    % resolution - measure of error
    %
    % dist       - the distance between the two centers
    %
    %  Does this by plotting the two circles in an
    % image with the specified resolution and
    % moving the centers towards each other until
    % the area of intersection is nearest the value
    % of b
    %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    r1 = sqrt( (a+b)/pi );
    r2 = sqrt( (b+c)/pi );

    size_x = 2*r1+2*r2;
    size_y = max( 2*r1, 2*r2 );

    center1_x = r1;
    center1_y = size_y/2;
    center2_x = 2*r1 + r2;
    center2_y = size_y/2;;

    [X,Y] = meshgrid( 0:resolution:size_x, 0:resolution:size_y );

    for new_center = (2*r1 + r2):-resolution:r1

        img = zeros( size(Y,1), size(Y,2) );
        img = and( (X - center1_x).^2 + (Y - center1_y).^2 < r1^2, ...
            (X - new_center).^2 + (Y - center2_y).^2 < r2^2 );

        if sum(sum(img)) * resolution^2 > b
            break
        end
    end

    dist = new_center - center1_x;


function [L] = ilogit(t)
% Calculate the inverse logit function corresponding to the value t
%
% :Usage:
% ::
%
%     function [L] = ilogit(t)
%
% :Output:
%
%   **L:**
%        exp(t)./(1+exp(t));
%
% ..
%    By Martin Lindquist and Tor Wager
%    Edited 12/12/06
% ..

L = exp(t)./(1+exp(t));


function [MOIndex] = lipschitz(u, y, maxlag, model, fig)
% A method to determine the lag space, based on Lipschitz quotients
%
%% Syntax
% [MOIndex] = lipschitz(u, y, maxlag)
%
%% Description
%  Given a set of corresponding inputs and outputs the function calculates
%  so called Lipschitz number for each combination of m and l where m
%  represents the number of delayed outputs, and l the number of delayed
%  inputs for the case of dynamic system: y(t) = f(y(t-1),...,y(t-l),
%  u(t-1),..., u(t-m)).
%  To small m and l result in a large Lipschitz nuber, while to large lag
%  spaces do not have greater effect on the Lipschitz nuber. In order to
%  determine the proper lag space we have to look for the knee point, where
%  Lipscitz number stops decreasing.
%
% Input:
% * u       ... the system input(column vector)
% * y       ... the system output(column vector)
% * maxlag  ... the max lag space to investigate
% * model   ... optional - 'arx' if we only want to investigate m = l case
%
% Output:
% * MOIndex ... the maxlag by maxlag matrix containing calculated Lipscitz
%               numbers (Model order index) for each combination of m and l

%% Signature
% Written by Tomaz Sustar
% Based on the algorithm by Xiangdong He and Haruhiko Asada

if(nargin<4), model='unknown'; end;

NN = length(y);                                         % number of samples
MOIndex = zeros(maxlag);                    % matrix of lipschitz's indexes

for m=1:maxlag,                                 % number of delayed outputs
  % m,
  for l=0:maxlag,                                 % number of delayed inputs

    % if we are investigating arx model srtucture only, we calculate MOIndex only when m = l
    if(strcmp(model, 'arx') && l ~= m), continue; end;

    lag = max(l,m);       % the greater from m, l
    % Because of the lag we can construct only NN - lag input output pairs
    N    = NN-lag;    % number of input - output pairs.
    p    = floor(0.02*N); % number of Lipschitz quotients used to determine model order index

    [input target] = construct([m l], u, y); % construct regressors and target

    % calculation of Lipschitz quotients

    Q = zeros(N);      % initialize Q matrix for storing Lipschitz qotients

    for i=1:N-1,
      % for each input/output pair calculate the their Lipschitz quotients all
      % further inputs/outputs pairs. In this way all possible Lipschitz
      % quotients q(i,j) are calculated.

      Q(i,i+1:N)=(target(i)-target(i+1:N)).^2 ./ ...
       sum((repmat(input(i,:), N-i, 1)-input(i+1:N,:)).^2, 2);

    end

    Q_max = Q(Q~=0);                                         % remove zeros
    Q_max = (-sort(-Q_max(:)));        % sort qoutients in descending order
    Q_max = sqrt(Q_max(1:p));                  % take p - largest quotients

    n = m+l;
    MOIndex(m,l+1)=prod(sqrt(n)*Q_max)^(1/p); % calculates order index and stores it to the matrix

  end % end for l

end % end for m

% draw some figures

if(~strcmp(model, 'arx'))

  figure('Name', 'Model order index vs. lag space')
  surf(1:maxlag, 0:maxlag,MOIndex');
  view([-600 40]);
  set(gca, 'Zscale','log');
  set(gca, 'XTick', 1:maxlag)
  set(gca, 'XTick', 1:maxlag)
  xlabel('l - number of past outputs')
  ylabel('m - number of past inputs')
  zlabel('Model Order Index')
end

if(nargin > 4)
  figure(fig);
else
  figure('Name', 'Model order index vs. lag space - arx case')
end
semilogy(diag(MOIndex));
xlabel('m = l - number of past inputs and outputs');
ylabel('Model order index');
set(gca, 'XTick', 1:maxlag);
grid on;


function [G1,Gd1,Wd,Wn,Juu,Jud]=randcase(ny,nu,nd)
% RANDCASE  A random case for self-optimizing control
%
%   [G,Gd,Wd,Wn,Juu,Jud] = randcase(ny,nu,nd) produces matrices of a random
%   case for self-optimizing control corresponding to the following
%   optimizing control problem:
%
%   min J(y,u,d)
%   s.t.  y = G*u + Gd*Wd*d + Wn*e
%
%   with Juu = \partial^2 J/\partial u \partial u
%        Jud = \partial^2 J/\partial u \partial d
%
%  These matrices can then be used to test the b3wc program.
%
%  See also b3wc, pb3wc, b3av, pb3av

%  By Yi Cao at Cranfield University, 9th January 2009; 23rd February 2010.
%

% Example.
%{
ny=30;
nu=15;
nd=5;
[G,Gd,Wd,Wn,Juu,Jud] = randcase(ny,nu,nd);
[B,sset,ops,ctime] = b3wc(G,Gd,Wd,Wn,Juu,Jud);
[B1,sset1,ops1,ctime1] = pb3wc(G,Gd,Wd,Wn,Juu,Jud,20);
%}
G1=randn(ny,nu);
Gd1=rand(ny,nd);
Wd=diag(rand(nd,1));
Wn=diag(rand(ny,1));
x=randn(nu,nu+2*ny+nd);
Juu=diag(sum(x.*x,2));
Jud=rand(nu,nd);


function	Xcov = embed_covariance(X,D,tau)
% Covariance matrix in time delay embedding space
%  Xcov = embed_covariance(X,D,tau)
% --- Input
%  X : input signal : [Xdim x Tsample x Ntrial]
%  D : time embedding dimension  (integer)
%  tau : delay time in sample number (integer)
% --- Output
%  Xcov([i,t1],[j,t2]) = Xtau([i,t1],:) * Xtau([j,t2],:)'
%  Xtau([i,t0],t) = X(i ,t + tau*(D - t0)) : [(Xdim*D) x T x Ntrial]
%  T = Tsample - tau*(D-1)
%
% 2008-5-22 Masa-aki Sato

[N ,Tall, Nr] = size(X);

Tdelay = tau*(D-1);

T = Tall - Tdelay;

% Time delayed embedding index
Tbgn = Tdelay + 1 - (0:tau:Tdelay);
Tend = Tbgn + T - 1;

% X-dim index
Iend = (1:D)*N;
Ibgn = Iend - N + 1;

Xcov = zeros(N*D,N*D);

for i=1:D
  for j=1:i
  	XX = reshape(X(:,Tbgn(i):Tend(i),:), N,T*Nr) ...
  	   * reshape(X(:,Tbgn(j):Tend(j),:), N,T*Nr)';

  	Xcov(Ibgn(i):Iend(i), Ibgn(j):Iend(j)) = XX;
  	Xcov(Ibgn(j):Iend(j), Ibgn(i):Iend(i)) = XX';
  end
end

Xcov = (Xcov + Xcov')/2;


function geometry_test0803 ()

%*****************************************************************************80
%
%% TEST0803 tests POLYGON_INRAD_DATA_2D, POLYGON_OUTRAD_DATA_2D, POLYGON_SIDE_DATA_2D;
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 March 2009
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST0803\n' );
  fprintf ( 1, '  For a REGULAR polygon in 2D:\n' );
  fprintf ( 1, '  the inradius, outradius and side are related.\n' );
  fprintf ( 1, '  POLYGON_INRAD_DATA_2D uses the inradius;\n' );
  fprintf ( 1, '  POLYGON_OUTRAD_DATA_2D uses the inradius;\n' );
  fprintf ( 1, '  POLYGON_SIDE_DATA_2D uses the inradius;\n' );

  for n = 3 : 5

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Number of polygonal sides = %d\n', n );

    side = 1.0;

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Assuming SIDE = %f\n', side );

    [ area, radin, radout ] = polygon_side_data_2d ( n, side );

    fprintf ( 1, '    AREA =   %f\n', area );
    fprintf ( 1, '    RADIN =  %f\n', radin );
    fprintf ( 1, '    RADOUT = %f\n', radout );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Assuming RADIN = %f\n', radin );

    [ area, radout, side ] = polygon_inrad_data_2d ( n, radin );

    fprintf ( 1, '    AREA =   %f\n', area );
    fprintf ( 1, '    RADOUT = %f\n', radout );
    fprintf ( 1, '    SIDE =   %f\n', side );

    fprintf ( 1, '\n' );
    fprintf ( 1, '  Assuming RADOUT = %f\n', radout );

    [ area, radin, side ] = polygon_outrad_data_2d ( n, radout );

    fprintf ( 1, '    AREA =   %f\n', area );
    fprintf ( 1, '    RADIN =  %f\n', radin );
    fprintf ( 1, '    SIDE =   %f\n', side );

  end

  return
end


function quad = piecewise_linear_product_quad ( a, b, f_num, f_x, f_v, ...
  g_num, g_x, g_v, quad_num )

%*****************************************************************************80
%
%% PIECEWISE_LINEAR_PRODUCT_QUAD: estimate piecewise linear product integral.
%
%  Discussion:
%
%    We are given two piecewise linear functions F(X) and G(X) and we wish
%    to estimate the value of the integral
%
%      INTEGRAL = Integral ( A <= X <= B ) F(X) * G(X) dx
%
%    The functions F(X) and G(X) are defined as tables of coordinates X and
%    values V.  A piecewise linear function is evaluated at a point X by
%    evaluating the interpolant to the data at the endpoints of the interval
%    containing X.
%
%    It must be the case that A <= B.
%
%    It must be the case that the node coordinates F_X(*) and G_X(*) are
%    given in ascending order.
%
%    It must be the case that:
%
%      F_X(1) <= A and B <= F_X(F_NUM)
%      G_X(1) <= A and B <= G_X(G_NUM)
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real A, B, the limits of integration.
%
%    Input, integer F_NUM, the number of nodes for F.
%
%    Input, real F_X(F_NUM), the node coordinates for F.
%
%    Input, real F_V(F_NUM), the nodal values for F.
%
%    Input, integer G_NUM, the number of nodes for G.
%
%    Input, real G_X(G_NUM), the node coordinates for G.
%
%    Input, real G_V(G_NUM), the nodal values for G.
%
%    Input, integer QUAD_NUM, the number of quadrature points.
%
%    Output, real QUAD, an estimate for the integral of F(X) * G(X)
%    from A to B.
%
  quad = 0.0;

  f_left = 1;
  g_left = 1;

  a2 = a;
  a2 = max ( a2, f_x(1) );
  a2 = max ( a2, g_x(1) );

  b2 = b;
  b2 = min ( b2, f_x(f_num) );
  b2 = min ( b2, g_x(g_num) );

  for i = 1 : quad_num

    xq =  ( (                2 * i - 1 ) * b2 ...
          + ( 2 * quad_num - 2 * i + 1 ) * a2 )  ...
          / ( 2 * quad_num             );

    f_left = r8vec_bracket3 ( f_num, f_x, xq, f_left );

    fq = f_v(f_left) + ( xq - f_x(f_left) ) * ( f_v(f_left+1) - f_v(f_left) ) ...
      / ( f_x(f_left+1) - f_x(f_left) );

    g_left = r8vec_bracket3 ( g_num, g_x, xq, g_left );

    gq = g_v(g_left) + ( xq - g_x(g_left) ) * ( g_v(g_left+1) - g_v(g_left) ) ...
      / ( g_x(g_left+1) - g_x(g_left) );

    quad = quad + fq * gq;

  end

  quad = quad * ( b - a ) / quad_num;

  return
end


function value = r8_fall ( x, n )

%*****************************************************************************80
%
%% R8_FALL computes the falling factorial function [X]_N.
%
%  Discussion:
%
%    Note that the number of "injections" or 1-to-1 mappings from
%    a set of N elements to a set of M elements is [M]_N.
%
%    The number of permutations of N objects out of M is [M]_N.
%
%    Moreover, the Stirling numbers of the first kind can be used
%    to convert a falling factorial into a polynomial, as follows:
%
%      [X]_N = S^0_N + S^1_N * X + S^2_N * X^2 + ... + S^N_N X^N.
%
%  Formula:
%
%    [X]_N = X * ( X - 1 ) * ( X - 2 ) * ... * ( X - N + 1 ).
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 June 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real X, the argument of the falling factorial function.
%
%    Input, integer N, the order of the falling factorial function.
%    If N = 0, FALL = 1, if N = 1, FALL = X.  Note that if N is
%    negative, a "rising" factorial will be computed.
%
%    Output, real VALUE, the value of the falling factorial function.
%
  value = 1.0;

  arg = x;

  if ( 0 < n )

    for i = 1 : n
      value = value * arg;
      arg = arg - 1.0;
    end

  elseif ( n < 0 )

    for i = -1 : -1 : n
      value = value * arg;
      arg = arg + 1.0;
    end

  end

  return
end


function geometry_test2072 ( )

%*****************************************************************************80
%
%% TEST2072 tests TRIANGLE_POINT_NEAR_2D;
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 December 2010
%
%  Author:
%
%    John Burkardt
%
  ntest = 7;

  ptest = [ ...
     0.25,   0.25; ...
     0.75,   0.25; ...
     1.00,   1.00; ...
    11.00,   0.50; ...
     0.00,   1.00; ...
     0.50, -10.00; ...
     0.60,   0.60 ]';
  t = [ ...
    0.0, 1.0; ...
    0.0, 0.0; ...
    1.0, 0.0 ]';

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST2072\n' );
  fprintf ( 1, '  For a triangle in 2D,\n' );
  fprintf ( 1, '  TRIANGLE_POINT_NEAR_2D computes the nearest\n' );
  fprintf ( 1, '  point to a point.\n' );

  r8mat_transpose_print ( 2, 3, t, '  Triangle vertices:' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '           P                PN\n' );
  fprintf ( 1, '\n' );

  for i = 1 : ntest

    p(1:2,1) = ptest(1:2,i);

    [ pn, dist ] = triangle_point_near_2d ( t, p );

    fprintf ( 1, '  %10f  %10f    %10f  %10f\n', p(1:2,1), pn(1:2,1) );

  end

  return
end


function U = fracdiffdemoydelay(alpha,alphad,beta,steps)

% A demo to the article:
% I. Podlubny, A.Chechkin, T. Skovranek, YQ Chen,
% B. M. Vinagre Jara, "Matrix approach to discrete
% fractional calculus II: partial fractional differential
% equations". http://arxiv.org/abs/0811.1355
%
% This function was used in the above article for the
% numerical solution and visualization of Example 5.
% It illustrates the ease of use of the matrix approach
% to discretization of partial differential equations
% with fractional derivatives with respect to the time
% variable with delays. Delays are considered to be multiples
% of a selected time step.
%
% This function solves the time-fractional diffusion-wave equation
% containing one delayed fractional derivative:
%  0.5*u_{t}^(\alpha) (x,t) + 0.5*u_{t}^(\alphad) (x,t-tau*steps)
%        = a2 * u_{xx}^{(2)}(x,t) + f(x,t)
% under zero initial and boundary conditions
%
% For alpha=1, alphad=1, beta=2, steps=0, and f(x,t)=8
% we have the part of the test example from the book:
% W. E. Milne. "Numerical Solution of Differential Equations".
%               New York: Wiley (London: Chapman & Hall), 1953.
%
% which is the classical heat conduction equation
%  u_{t} (x,t) = a2 * u_{xx}(x,t) + f(x,t)

a2=1;       % coefficient from the diffusion equation
L = 1;      % length of spatial interval

% Number of spatial steps + 1 is:
m = 21; % 11, 21

% Number of steps in time + 1 is:
n =148; % 37, 148

h = L / (m-1);          % spatial step
tau = h^2 / (6*a2);     % time step

% generating the matrix for approximation
B1 = ban(alpha,n-1,tau)';       % alpha-th order derivative with respect to time
TD = kron(B1, eye(m));          % time derivative matrix

Bdelay = shift (ban(alphad,n-1+steps,tau)', steps); % delayed derivative of order alphad
TDdelay = kron(Bdelay, eye(m)); % delayed time derivative matrix

B2 = ransym(beta,m,h);          % beta-th order derivative with respect to X
SD = kron(eye(n-1), B2);        % spatial derivative matrix

SystemMatrix = 0.5*TD + 0.5*TDdelay- a2*SD;   % matrix corresponding to discretization
                                      % in space and time

% remove columns with '1' and 'm' from SystemMatrix
S = eliminator (m, [1 m]);
SK = kron(eye(n-1), S);
SystemMatrix_without_columns_1_m = SystemMatrix * SK';

% remove rows with '1' and 'm' from SystemMatrix_without_columns_1_m
S = eliminator (m, [1 m]);
SK = kron(eye(n-1), S);
SystemMatrix_without_rows_columns_1_m = SK * SystemMatrix_without_columns_1_m;

% Right hand side
F = 8*ones(size(SystemMatrix_without_rows_columns_1_m,1),1);

% Solution of the system
Y = SystemMatrix_without_rows_columns_1_m\F;

% Reshape solution array -- values for k-th time step
% are in the k-th column of YS:
YS = reshape(Y,m-2,n-1);
YS = fliplr(YS);

U = YS;

% plot graph
[rows, columns] = size(U);
U = [ zeros(1, columns); U;  zeros(1, columns)];
U = [zeros(1,m)' U];
[XX,YY]=meshgrid(tau*(0:n-1),h*(0:m-1));

mesh(XX,YY,U)
xlabel('t');
ylabel('x');
zlabel('y(x,t)');
title(['\alpha = ', num2str(alpha), ', ', ...
       ' \gamma = ', num2str(alphad), ', ', ...
       ' \beta = ', num2str(beta), ', ', ...
       ' k = ', num2str(steps) ])

set(gca, 'xlim', [0 tau*n], 'zlim', [0 1])
box on


function D = EuDist2(fea_a,fea_b,bSqrt)
%EUDIST2 Efficiently Compute the Euclidean Distance Matrix by Exploring the
%Matlab matrix operations.
%
%   D = EuDist(fea_a,fea_b)
%   fea_a:    nSample_a * nFeature
%   fea_b:    nSample_b * nFeature
%   D:      nSample_a * nSample_a
%       or  nSample_a * nSample_b
%
%    Examples:
%
%       a = rand(500,10);
%       b = rand(1000,10);
%
%       A = EuDist2(a); % A: 500*500
%       D = EuDist2(a,b); % D: 500*1000
%
%   version 2.1 --November/2011
%   version 2.0 --May/2009
%   version 1.0 --November/2005
%
%   Written by Deng Cai (dengcai AT gmail.com)

if ~exist('bSqrt','var')
    bSqrt = 1;
end

if (~exist('fea_b','var')) || isempty(fea_b)
    aa = sum(fea_a.*fea_a,2);
    ab = fea_a*fea_a';

    if issparse(aa)
        aa = full(aa);
    end

    D = bsxfun(@plus,aa,aa') - 2*ab;
    D(D<0) = 0;
    if bSqrt
        D = sqrt(D);
    end
    D = max(D,D');
else
    aa = sum(fea_a.*fea_a,2);
    bb = sum(fea_b.*fea_b,2);
    ab = fea_a*fea_b';

    if issparse(aa)
        aa = full(aa);
        bb = full(bb);
    end

    D = bsxfun(@plus,aa,bb') - 2*ab;
    D(D<0) = 0;
    if bSqrt
        D = sqrt(D);
    end
end


function s = logspace_len(a, b, n, l)

if nargin < 4
    l = n
end

r = exp((log(10^b)-log(10^a)) / (n-1));
s = 10^a * r.^(0:l-1);

end


% Mathematics Q43918
% https://dsp.stackexchange.com/questions/questions/43918
% Determine the Unit Impulse Response of ARMA Filter for 8 First Indices
% References:
%   1.  aa
% Remarks:
%   1.  sa
% TODO:
% 	1.  ds
% Release Notes
% - 1.0.000     25/09/2017
%   *   First release.

%% General Parameters

run('InitScript.m');

figureIdx           = 0; %<! Continue from Question 1
figureCounterSpec   = '%04d';

generateFigures = OFF;

%% Simulation Parameters

numSamples = 8;

% Filter Coefficients
% See MATLAB's Filter Documentation for the sign.
vA = [1; -0.5; -(1 / 8)];
vB = [0; 0; 0.5];

%% Generate Data

% Unit Impulse
vX = zeros([numSamples, 1]);
vX(1) = 1;

%% Simulate Result

vY = filter(vB, vA, vX);

%% Display Results

hFigure         = figure('Position', figPosDefault);
hAxes           = axes();
set(hAxes, 'NextPlot', 'add');
hLineSeries  = line([0:(numSamples - 1)], [vX, vY]);
set(hLineSeries, 'LineWidth', lineWidthNormal);
set(get(hAxes, 'Title'), 'String', {['ARMA Filter Unit Impulse Response']}, ...
    'FontSize', fontSizeTitle);
set(get(hAxes, 'XLabel'), 'String', {['Sample Indices']}, ...
    'FontSize', fontSizeAxis);
set(get(hAxes, 'YLabel'), 'String', {['Value']}, ...
    'FontSize', fontSizeAxis);
hLegend = ClickableLegend({['Unite Impulse'], ['ARMA Filter Response']});

%% Restore Defaults

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


function [k]=fetruss(el,leng,area,c,s)
%--------------------------------------------------------------
%  Purpose:
%     Compute stiffness matrices for the 2-d truss element
%     nodal dof {u_1 v_1 u_2 v_2}
%
%  Synopsis:
%     [k]=fetruss(el,leng,area,c,s)
%
%  Variable Description:
%     k - element stiffness matrix (size of 4x4)
%     el - elastic modulus ( E )
%     leng - element length
%     area - area of truss cross-section
%----------------------------------------------------------------
% syms X1 X2 X3
k=(area*el/leng)*[c*c c*s -c*c -c*s;...
                  c*s s*s -c*s -s*s;...
                  -c*c -c*s c*c c*s;...
                  -c*s -s*s c*s s*s];

github-repos/MATLAB/Sable-mcbench-benchmarks/mcbench-benchmarks-ba13b2f0296ef49491b95e3f984c7c41fccdb6d8/12401-optimize-truss-by-fsd-and-slp/Optimize Truss by FSD and SLP/fetruss.m


function c=ref_rdgt(f,g,a,M)
%REF_RDGT  Reference Real DGT
%   Usage:  c=ref_rdgt(f,g,a,M);
%
%   Linear algebra version of the algorithm. Create big matrix
%   containing all the basis functions and multiply with the transpose.

L=size(f,1);

b=L/M;
N=L/a;

Mhalf=ceil(M/2);

F=zeros(L,M*N);

l=(0:L-1).';

for n=0:N-1

  % Do the unmodulated coefficient.
  F(:,M*n+1)=circshift(g,n*a);

  for m=1:Mhalf-1
    F(:,M*n+2*m)=sqrt(2)*cos(2*pi*m*l/M).*circshift(g,n*a);

    F(:,M*n+2*m+1)=sqrt(2)*sin(2*pi*m*l/M).*circshift(g,n*a);

  end;

  if mod(M,2)==0
    F(:,M*(n+1))=cos(pi*l).*circshift(g,n*a);
  end;

end;

% dot-transpose will work because F is real.
c=F.'*f;


function [azStart,dist,azEnd,latLonWaypoints]=indirectGreatCircleProb(latLonStart,latLonEnd,r,N,algorithm,waypointType,noJumps)
%%INDIRECTGREATCIRCLEPROB Solve the indirect great circle problem. That is,
%                      given two points on a spherical Earth, find the
%                      initial bearing and distance one must travel to
%                      take the shortest (geodesic) path between the
%                      points. Additionaly, this function can compute
%                      waypoints on the path. This type of navigation is
%                      sometimes referred to as "great circle sailing."
%                      When used for navigation, it is less accurate than
%                      an ellipsoidal Earth approximation.
%
%INPUTS: latLonStart The 2XnumPts set of numPts initial points given in
%               latitude and longitude in radians in the format
%               [latitude;longitude] (on a reference sphere, latitude is
%               spherical elevation; longitude is spherical azimuth). If
%               all these points are the same but latLonEnd varies, then a
%               single 2X1 vector can be passed. Extra rows, if passed,
%               will be ignored.
%     latLonEnd The 2XnumPts final points given in latitude and longitude
%               in adians in the format [latitude;longitude]. If all these
%               points are the same but latLonStart varies, then a single
%               2X1 vector can be passed.
%             r The assumed radius of the spherical Earth model. If omitted
%               or an empty matrix is passed, the default of
%               r=osculatingSpher4LatLon(latLonStart) is used.
%             N The number of waypoints, besides the initial and final
%               points on the trajectory, to produce. If omitted or an
%               empty matrix is passed, then no waypoints are generated and
%               latLonWaypoints is an empty matrix.
%     algorithm An optional parameter selecting the algorithm to use.
%               Possible values are:
%               0 Use the algorithm of [2], which avoids issues with
%                 singularities at the poles.
%               1 (The default if omitted or an empty matrix is passed and
%                 waypointType=1) Use the COFI algorithm of [1]. Latitudes
%                 within 2^24*eps(pi/2) of +/-pi/2 (the North and South
%                 poles) will be clipped to that bound. This avoids a
%                 singularity at the poles.
%               2 (The default if omitted or an empty matrix is passed and
%                 waypointType=0) Obtain angles using Equation 5-4b of [3],
%                 which is stable at the poles. Obtaincthe distance using a
%                 cross product formula, which is also used in algorithm 1,
%                 as discussed below.
%    waypointType An optional parameter indicating how the waypoints will
%                 be spaced. Possible values are:
%                 0 (The default if omitted or an empty matrix is passed)
%                   Space the N waypoints between the start and end
%                   uniformly in distance.
%                 1 Space the N waypoints between the start and end
%                   uniformly in longitude. This option is only available
%                   for algorithm 0. If a trajectory is meridional, then
%                   only the starting and stopping points will be returned.
%
%OUTPUTS: azStart The 1XnumPts scalar forward azimuths at the starting
%                 point in radians East of true North on the reference
%                 sphere.
%            dist The 1XnumPts distances on the sphere-approximated Earth
%                 between the starting and stopping points.
%           azEnd The 1XnumPts forward azimuth at the ending point in
%                 radians East of true North on the reference sphere.
% latLonWaypoints A 2X(N+2) set of waypoints on the trajectory.
%                 latLonWaypoints(:,i) is the ith points as
%                 [latitude;longitude] in radians. The first point is
%                 latLonStart and the final points is latLonEnd, though the
%                 points are made to avoid jumps of 2*pi in longitude,
%                 which can mean that the last point in this can be off
%                 from the provided last point by a factor of 2*pi. The
%                 other points are equally spaced along the trajectory. If
%                 the trajectory is meridional and waypointType=1, then
%                 only the starting and ending points will be returned.
%
%Great circles are geodesics on a sphere. A geodesic path between two
%points on a sphere is much simpler to determine as compared to an
%ellipsoid (which is what one gets using the indirectGeodeticProb
%function). For the spherical model, the latitude is taken as the elevation
%and the longitude as the azimuth on the sphere (we assume coordinate
%system 0 in the spher2Cart function). The latitudes and longitudes
%returned as waypoints by this function can be used to piece together an
%_approximate_ geodesic trajectory on the reference ellipsoid. One can
%obtain headings and distances between the reference points using rhumb
%lines.
%
%The azimuthal values returned when one of the points is at the pole
%depends on the longitude value given for the points. The getENUAxes
%function can return East-North-Up axes anywhere on the globe (for a
%sphere, the ellipsoidal flattening is 0). When given a pole, the result is
%the equivalent one would get by taking a point with the same latitude and
%with the latitude magnitude a tiny epsilon less than pi/2.
%
%The implementation of the COFI algorithm of [1] has been modified so that
%the angular difference D is obtained using the angBetweenVecs given F and
%T rather than the technique derived from the dot product relation starting
%in Equation 13 in [1]. This is because the cross product relation used in
%angBetweenVecs is more accurate. This is also used for the distance in
%algorithm 2. Minor changes had to be made to algorithm 1 to deal with
%trajectories going West, since the derivation in [1] is for East-bound
%trajectories.
%
%EXAMPLE 1:
%This is example 2 from [1]. It is a trajectory that crosses the
%international date and and goes from the Northern hemisphere to the
%southern hemisphere. We also compute the reverse path and show that the
%start and end azimuth angles produced in each direction are consistent
%with each other (when the same Earth radius is used eahc time). We then
%plot the trajectory on an image of the spherical Earth. For better
%plotting, the radius of the Earth has been normalized to 1.
% N=500;
% latStart=degMinSec2Rad(37,47.5);
% lonStart=degMinSec2Rad(-122,-27.8);
% latEnd=degMinSec2Rad(-33,-51.7);
% lonEnd=degMinSec2Rad(151,12.7);
%
% latLonStart=[latStart;lonStart];
% latLonEnd=[latEnd;lonEnd];
%
% [azStartFwd,distFwd,azEndFwd,latLonWayPoints]=indirectGreatCircleProb(latLonStart,latLonEnd,1,N);
% [azStartRev,distRev,azEndRev,latLonWayPointsRev]=indirectGreatCircleProb(latLonEnd,latLonStart,1,N);
%
% %All four of these should be approximately zero if the algorithm works
% %forwards and backwards:
% distFwd-distRev
% wrapRange(azStartFwd-wrapRange(azEndRev+pi,-pi,pi),-pi,pi)
% wrapRange(azStartRev-wrapRange(azEndFwd+pi,-pi,pi),-pi,pi)
% max(max(abs(wrapRange(latLonWayPoints-fliplr(latLonWayPointsRev),-pi,pi))))
%
% xStartCart=ellips2Cart([latLonStart;0],1,0);
% xEndCart=ellips2Cart([latLonEnd;0],1,0);
% %Give the points a nonzero elevation so the lines are easier to see.
% pathPoints=ellips2Cart([latLonWayPoints;0.02*ones(1,N+2)],1,0);
%
% figure(1)
% clf
% hold on
% plotMapOnEllipsoid([],1,0);
% scatter3(xStartCart(1),xStartCart(2),xStartCart(3),100,'filled')
% scatter3(xEndCart(1),xEndCart(2),xEndCart(3),100,'filled')
% plot3(pathPoints(1,:),pathPoints(2,:),pathPoints(3,:),'-r','linewidth',4)
% view([-75.368365161957513,3.494544111878512])
%
%EXAMPLE 2:
%This is the same as example 1, except one point is given at the North
%pole.
% N=500;
% latStart=pi/2;%North pole.
% lonStart=degMinSec2Rad(-122,-27.8);
% latEnd=degMinSec2Rad(-33,-51.7);
% lonEnd=degMinSec2Rad(151,12.7);
%
% latLonStart=[latStart;lonStart];
% latLonEnd=[latEnd;lonEnd];
%
% [azStartFwd,distFwd,azEndFwd,latLonWayPoints]=indirectGreatCircleProb(latLonStart,latLonEnd,1,N);
% [azStartRev,distRev,azEndRev,latLonWayPointsRev]=indirectGreatCircleProb(latLonEnd,latLonStart,1,N);
%
% %All four of these should be approximately zero if the algorithm works
% %forwards and backwards:
% distFwd-distRev
% wrapRange(azStartFwd-wrapRange(azEndRev+pi,-pi,pi),-pi,pi)
% wrapRange(azStartRev-wrapRange(azEndFwd+pi,-pi,pi),-pi,pi)
% max(max(abs(wrapRange(latLonWayPoints-fliplr(latLonWayPointsRev),-pi,pi))))
%
% xStartCart=ellips2Cart([latLonStart;0],1,0);
% xEndCart=ellips2Cart([latLonEnd;0],1,0);
% pathPoints=ellips2Cart([latLonWayPoints;0.02*ones(1,N+2)],1,0);
%
% figure(1)
% clf
% hold on
% plotMapOnEllipsoid([],1,0);
% scatter3(xStartCart(1),xStartCart(2),xStartCart(3),100,'filled')
% scatter3(xEndCart(1),xEndCart(2),xEndCart(3),100,'filled')
% plot3(pathPoints(1,:),pathPoints(2,:),pathPoints(3,:),'-r','linewidth',4)
%
%REFERENCES:
%[1] C.-L. Chen, P.-F. Liu, and W.-T. Gong, "A simple approach to great
%    circle sailing: The COFI method," The Journal of Navigation, vol. 67,
%    no. 3, pp. 403-418, May 2014.
%[2] D. F. Crouse, "Singularity-free great-circle sailing," Naval Research
%    Laboratory, Washington, DC, Tech. Rep. NRL/5340/MR-2021/4, 26
%    Jul. 2021.
%[3] J. P. Snyder, "Map projections-a working manual," U.S. Geological
%    Survey, Tech. Rep. 1395, 1987.
%
%August 2019 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<7||isempty(noJumps))
    noJumps=true;
end

if(nargin<6||isempty(waypointType))
    waypointType=0;
end

if(nargin<5||isempty(algorithm))
    if(waypointType==1)
        algorithm=1;
    else
        algorithm=2;
    end
end

if(nargin<4)
    N=[];%Generate no waypoints.
end

if(nargin<3||isempty(r))
    r=osculatingSpher4LatLon(latLonStart);
end

if(nargout<3)
    N=[];%Do not generate waypoints.
end

numPts1=size(latLonStart,2);
numPts2=size(latLonEnd,2);
numPts=max(numPts1,numPts2);

if(numPts1>numPts2)
    latLonEnd=repmat(latLonEnd,[1,numPts]);
elseif(numPts2>numPts1)
    latLonStart=repmat(latLonStart,[1,numPts]);
end

azStart=zeros(1,numPts);
dist=zeros(1,numPts);
azEnd=zeros(1,numPts);
if(~isempty(N))
    latLonWaypoints=zeros(2,N+2,numPts);
else
    latLonWaypoints=[];
end

switch(algorithm)
    case 0
        if(waypointType~=0)
            error('This algorithm only supports waypointType=0.');
        end

        for k=1:numPts
            [azStart(k),dist(k),azEnd(k),latLonWaypointsCur]=indirectGreatCircleProbCrouse(latLonStart(1:2,k),latLonEnd(1:2,k),r,N);
            if(~isempty(N))
                latLonWaypoints(:,:,k)=latLonWaypointsCur;
            end
        end
    case 1
        for k=1:numPts
            [azStart(k),dist(k),azEnd(k),latLonWaypointsCur]=indirectGreatCircleProbChen(latLonStart(1:2,k),latLonEnd(1:2,k),r,N,waypointType);
            if(~isempty(N))
                latLonWaypoints(:,:,k)=latLonWaypointsCur;
            end
        end
    case 2
        for k=1:numPts
            [azStart(k),dist(k),azEnd(k),latLonWaypointsCur]=indirectGreatCircleProbSnyder(latLonStart(1:2,k),latLonEnd(1:2,k),r,N);
            if(~isempty(N))
                latLonWaypoints(:,:,k)=latLonWaypointsCur;
            end
        end
    otherwise
        error('Unknown algorithm chosen.')
end

if(~isempty(N)&&noJumps&&N>0)
    cumOffset=0;
    for k=1:numPts
        for j=2:(N+2)
            diffVal=latLonWaypoints(2,j)+cumOffset-latLonWaypoints(2,j-1);
            if(diffVal>pi)
                cumOffset=cumOffset-2*pi;
            elseif(diffVal<-pi)
                cumOffset=cumOffset+2*pi;
            end
            latLonWaypoints(2,j)=latLonWaypoints(2,j)+cumOffset;
        end
    end
end
end

function [azStart,dist,azEnd,latLonWayPoints]=indirectGreatCircleProbChen(latLonStart,latLonEnd,r,N,waypointType)
%%INDIRECTGREATCIRCLEPROBCHEN Solve the indirect great circle problem using
%                   the algorithm of [1], except the angular difference D
%                   is obtained using the angBetweenVecs given F and T.
%
%Starting latitude values within 2^24*eps(pi/2); of the pole will be
%clipped to be 2^24*eps(pi/2); away from the pole. This reduces problems
%with singularities at the poles at the cost of a loss of accuracy compared
%to elsewhere on the globe.
%
%REFERENCES:
%[1] C.-L. Chen, P.-F. Liu, and W.-T. Gong, "A simple approach to great
%    circle sailing: The COFI method," The Journal of Navigation, vol. 67,
%    no. 3, pp. 403-418, May 2014.
%
%August 2019 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Latitude at the start.
LF=latLonStart(1);
%Deal with locations very close to the North or South pole by offsetting
%them just enough to avoid finite precision issues.
epsVal=2^24*eps(pi/2);
if(abs(LF-pi/2)<epsVal)
    LF=pi/2-epsVal;
elseif(abs(LF+pi/2)<epsVal)
    LF=pi/2+epsVal;
end

%Latitude at the destination.
LT=latLonEnd(1);

%Difference in longitude. If DLo is positive, then the shortest path is
%going East. If it is negative, then the shortest path is going west.
DLo=wrapRange(latLonEnd(2)-latLonStart(2),-pi,pi);

goingWest=(DLo<0);

sinLF=sin(LF);
cosLF=cos(LF);
sinLT=sin(LT);
cosLT=cos(LT);

lonStart=latLonStart(2);
cosLS=cos(lonStart);
sinLS=sin(lonStart);

lonEnd=latLonEnd(2);
cosLE=cos(lonEnd);
sinLE=sin(lonEnd);

%The Cartesian starting point (unit sphere).
F=[cosLS*cosLF;
   sinLS*cosLF;
   sinLF];

%The Cartesian ending point (unit sphere).
T=[cosLE*cosLT;
   sinLE*cosLT;
   sinLT];

%This is more accurate than using the cosine formula that is implicit in
%Equations 13 and 15 in [1].
D=angBetweenVecs(F,T);
if(D==0)
   %Special case: The starting and ending points are the same.
    azStart=NaN;%Undefined direction.
    dist=0;
    azEnd=NaN;%Undefined direction.
    latLonWayPoints=repmat(latLonStart,[1,N+2]);
    return
end

cosD=cos(D);
sinD=sin(D);

%From Equation 17 in [1].
cosC=(sinLT-sinLF*cosD)/(cosLF*sinD);

%Deal with finite precision issues.
cosC=min(1,max(-1,cosC));
C=acos(cosC);

%The sign adjustment for going west is not mentioned in [1].
%Alternatively, one could get sinC=cosLT*sin(DLo)/sinD; and then use the
%atan2 function.
if(goingWest)
    azStart=-C;
else
    azStart=C;
end
dist=D*r;

%%%%%%%%%%%%%
%%%%The Azimuth at the End
%%%%%%%%%%%%%

%To get the azimuth at the end, use Equation 17 in [1] switching the
%beginning and the end; this flips the sign of D, so the sign of sinD
%flips. Then, flip the direction of the result 180 degrees if we are going
%West.
cosCEnd=-(sinLF-sinLT*cosD)/(cosLT*sinD);
%Deal with finite precision issues.
cosCEnd=max(-1,min(1,cosCEnd));
azEnd=acos(cosCEnd);
if(goingWest)
    azEnd=-azEnd;
end

%%%%%%%%%%%%%
%%%%Waypoints
%%%%%%%%%%%%%
if(~isempty(N))
    %If waypoints are desired.
    latLonWayPoints=zeros(2,N+2);
    latLonWayPoints(:,1)=latLonStart;
    latLonWayPoints(:,N+2)=latLonEnd;
    if(waypointType==0)
        %Waypoints uniformly spaced in distance.
        step=D/(N+1);
        DFX=step:step:(step*N);

        cosDFX=cos(DFX);
        sinDFX=sin(DFX);

        %Equation 19 in [1].
        sinLX=sinLF.*cosDFX+cosLF.*sinDFX.*cosC;
        cosLX=sqrt(1-sinLX.^2);%Equivalent to cosLX=cos(asin(sinLX));

        %Equation 21 in [1].
        cosDLoFX=(cosDFX-sinLF.*sinLX)./(cosLF.*cosLX);

        %Deal with finite precision issues.
        cosDLoFX=max(-1,min(1,cosDLoFX));
        if(goingWest)
            lonPoints=wrapRange(latLonStart(2)-acos(cosDLoFX),-pi,pi);
        else
            lonPoints=wrapRange(latLonStart(2)+acos(cosDLoFX),-pi,pi);
        end
        latLonWayPoints(:,2:(N+1))=[asin(sinLX);lonPoints];
    else
        %Waypoints uniformly spaced in longitude.
        DLonFT=wrapRange(lonEnd-lonStart,-pi,pi);

        if(DLonFT==0)
            %Meridonal trajectory.
            latLonWayPoints=[latLonStart,latLonEnd];
            return
        end

        deltaSign=sign(DLonFT);

        step=DLonFT/(N+1);
        DLoFX=abs(step:step:(step*N));
        cosDLoFX=cos(DLoFX);
        sinDLoFX=sin(DLoFX);

        sinC=sin(C);

        %Equation 38 in [1].
        tanLX=(cosC*sinDLoFX+sinLF*sinC*cosDLoFX)/(cosLF*sinC);

        latLonWayPoints(:,2:(N+1))=[atan(tanLX);wrapRange(lonStart+deltaSign*DLoFX,-pi,pi)];
    end
else
    latLonWayPoints=[];
end
end

function [azStart,dist,azEnd,latLonWayPoints]=indirectGreatCircleProbCrouse(latLonStart,latLonEnd,r,N)
%%INDIRECTGREATCIRCLEPROBCROUSE Solve the indirect great circle problem
%               using the algorithm of [1].
%
%REFERENCES:
%[1] D. F. Crouse, "Singularity-free great-circle sailing," Naval Research
%    Laboratory, Washington, DC, Tech. Rep. NRL/5340/MR-2021/4, 26
%    Jul. 2021.
%
%August 2019 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Convert the latitude-longitude values to unit vectors.
u1=spher2Cart([latLonStart(2);latLonStart(1)]);
u2=spher2Cart([latLonEnd(2);latLonEnd(1)]);

%Rotate the vectors both onto the equator.
[vec1Rot,vec2Rot,R]=rot2Vecs2CommonPlane(u1,u2);

%The geodesic goes along the equator in the rotated coordinate system in
%the tangent plane. We need to find the shortest direction around the
%equator. To do this, we shall get the azimuth angles.
az1=atan2(vec1Rot(2),vec1Rot(1));
az2=atan2(vec2Rot(2),vec2Rot(1));
DLo=wrapRange(az2-az1,-pi,pi);
goingWest=(DLo<0);

%The distance traveled between the points.
dist=abs(DLo)*r;

%Unit vectors in the traveling directions are thus either the positive or
%the negative of the East unit direction vector at the starting and ending
%points.
uENU1=getENUAxes([0;az1],false,1,0);
uENU2=getENUAxes([0;az2],false,1,0);

if(goingWest)
    uDir1=-uENU1(:,1);
    uDir2=-uENU2(:,1);
else
    uDir1=uENU1(:,1);
    uDir2=uENU2(:,1);
end

%Now, we shall undo the rotations to get the unit direction vectors in the
%original Cartesian coordinate system.
uDir1=R'*uDir1;
uDir2=R'*uDir2;

%Given the unit vectors in the original Cartesian coordinate system, we
%need to get the azimuth angle. The azimuth angle is in terms of degrees
%East of North, so we need to project into the East-North plane.
%Get the new set of ENU basis vectors in the  original coordinate system
uENU1=getENUAxes(latLonStart,false,1,0);
uENU2=getENUAxes(latLonEnd,false,1,0);

EProj=dot(uDir1,uENU1(:,1));
NProj=dot(uDir1,uENU1(:,2));
azStart=atan2(EProj,NProj);

EProj=dot(uDir2,uENU2(:,1));
NProj=dot(uDir2,uENU2(:,2));
azEnd=atan2(EProj,NProj);

if(~isempty(N))%If waypoints are desired.
    distPts=linspace(0,dist,N+2);
    latLonWayPoints=directGreatCircleProb(latLonStart,azStart,distPts,r);
    %This ensures that the longitudes match even if the starting and/or
    %stopping points are at the poles.
    latLonWayPoints(:,1)=latLonStart;
    latLonWayPoints(:,N+2)=latLonEnd;
else
    latLonWayPoints=[];
end
end

function [azStart,dist,azEnd,latLonWayPoints]=indirectGreatCircleProbSnyder(latLonStart,latLonEnd,r,N)
%%INDIRECTGREATCIRCLEPRBSNYDER This function calls greatCircleDistance with
%   algorithm 0 selected, which should be the most stable solution. Then,
%   it calls greatCircleAzimuth with algorithm 2 selected, which is the
%   very simple formula in Equation 5-4b in [1].
%
%REFERENCES:
%[1] J. P. Snyder, "Map projections-a working manual," U.S. Geological
%    Survey, Tech. Rep. 1395, 1987.
%
%December 2021 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

%Latitude at the start.
phi1=latLonStart(1);
%Latitude at the destination.
phi2=latLonEnd(1);

lambda1=latLonStart(2);
lambda2=latLonEnd(2);
cosPhi1=cos(phi1);
sinPhi1=sin(phi1);
cosPhi2=cos(phi2);
sinPhi2=sin(phi2);

cosLambda1=cos(lambda1);
sinLambda1=sin(lambda1);
cosLambda2=cos(lambda2);
sinLambda2=sin(lambda2);
deltaLambda=lambda2-lambda1;
cosDeltaLambda=cos(deltaLambda);
sinDeltaLambda=sin(deltaLambda);

%The Cartesian starting point (unit sphere).
F=[cosLambda1*cosPhi1;
   sinLambda1*cosPhi1;
   sinPhi1];
%The Cartesian ending point (unit sphere).
T=[cosLambda2*cosPhi2;
   sinLambda2*cosPhi2;
   sinPhi2];
dist=r*angBetweenVecs(F,T);

azStart=atan2(cosPhi2*sinDeltaLambda,cosPhi1*sinPhi2-sinPhi1*cosPhi2*cosDeltaLambda);
azEnd=atan2(-cosPhi1*sinDeltaLambda,cosPhi2*sinPhi1-sinPhi2*cosPhi1*cosDeltaLambda);
azEnd=wrapRange(azEnd+pi,-pi,pi);

if(~isempty(N))%If waypoints are desired.
    distPts=linspace(0,dist,N+2);
    latLonWayPoints=directGreatCircleProb(latLonStart,azStart,distPts,r);
    %This ensures that the longitudes match even if the starting and/or
    %stopping points are at the poles.
    latLonWayPoints(:,1)=latLonStart;
    latLonWayPoints(:,N+2)=latLonEnd;
else
    latLonWayPoints=[];
end
end

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


function y=bcrecur(a, n)
%
% Computation of the fractional difference coefficients
% by the recurrence relation
%           bc(j)=(1-(a+1)/j)*bc(j-1),
%  a - order of the fractional difference
%  n - required number of coefficients
%
%  Computation of bcrecur(k,k) takes (3*k+1) flops.
%
%  Copyright (C) Igor Podlubny
%  15 Nov 1994
%
%  See also:
%  [1] Podlubny, I.: Fractional Differential Equations.
%      Academic Press, San Diego, 1999, 368 pages, ISBN 0125588402.

y=cumprod([1, 1 - ((a+1) ./ (1:n))]);


function subpak_test08 ( )

%*****************************************************************************80
%
%% TEST08 tests FAC_DIV, FAC_GCD, FAC_LCM, FAC_MUL, FAC_TO_I4, I4_TO_FAC.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 April 2009
%
%  Author:
%
%    John Burkardt
%
  prime_num = 5;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'TEST08\n' );
  fprintf ( 1, '  For products of prime factors:\n' );
  fprintf ( 1, '  FAC_DIV computes a quotient;\n' );
  fprintf ( 1, '  FAC_MUL multiplies;\n' );
  fprintf ( 1, '  FAC_LCM computes the LCM;\n' );
  fprintf ( 1, '  FAC_GCD computes the GCD;\n' );
  fprintf ( 1, '  I4_TO_FAC converts an integer;\n' );
  fprintf ( 1, '  FAC_TO_I4 converts to an integer.\n' );
  fprintf ( 1, '  FAC_TO_RAT converts to a ratio.\n' );

  i1 = 720;
  i2 = 42;

  npower1 = i4_to_fac ( i1, prime_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Representation of I1 = %d\n', i1 );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower1 );

  npower2 = i4_to_fac ( i2, prime_num );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Representation of I2 = %d\n', i2 );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower2 );

  npower3 = fac_lcm ( prime_num, npower1, npower2 );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  LCM of I1, I2:\n' );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower3 );

  npower3 = fac_gcd ( prime_num, npower1, npower2 );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  GCD of I1, I2:\n' );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower3 );

  npower3 = fac_mul ( prime_num, npower1, npower2 );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Product of I1, I2:\n' );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower3 );

  npower3 = fac_div ( prime_num, npower2, npower1 );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Quotient of I2 / I1:\n' );
  fprintf ( 1, '\n' );

  fac_print ( prime_num, npower3 );

  [ top, bot ] = fac_to_rat ( prime_num, npower3 );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Quotient as a rational: %d / %d\n', top, bot );

  return
end


 function x = ir_idct2(y)
%function x = ir_idct2(y)
%|
%| Compute 2D inverse DCT of many images
%| (matlab idct2 can handle only one image)
%|
%| in
%|	y [M N (many)]	2D (M by N) DCT coefficients for many images
%|
%| out
%|	x [M N (many)]	corresponding synthesized 2D images
%|
%| 2016 Anish Lahiri
%| 2016-08-024 modified by JF to include test and comments

if nargin < 1, ir_usage, end
if streq(y, 'test'), ir_idct2_test, return, end

[nx, ny, np] = size(y);
x = reshape(y, nx, []); % [M *]
x = idct(x); % [M *] 1D along 1st dim
x = permute(reshape(x, nx, ny, np), [2,1,3]); % [M N np]
x = reshape(x, ny, []); % [N *]
x = idct(x); % [N *] 1D along 2nd dim
x = permute(reshape(x, ny, nx, np), [2 1 3]); % [M N np]
x = reshape(x, size(y));

function ir_idct2_test
m = 8;
n = 10;
nrep = 100;
rng(0);
y = rand(m, n, nrep);
x1 = ir_idct2(y);
x2 = zeros(size(x1));
for ii=1:nrep
	x2(:,:,ii) = idct2(y(:,:,ii));
end
equivs(x1, x2)

y1 = ir_dct2(x1);
equivs(y, y1)

if im % show all the 2D basis functions
	n = 8;
	y = eye(n^2);
	y2 = reshape(y, n, n, []);
	x2 = ir_idct2(y2);
	im plc 1 2
	im(1, x2, '2D: correct')

	x1 = idct(y);
	x12 = reshape(x1, n, n, []);
	im(2, x12, '1D: incorrect')
end


function cMap = makeColorMap(varargin)
%% MAKECOLORMAP makes smoothly varying colormaps
% a = makeColorMap(beginColor, middleColor, endColor, numSteps);
% a = makeColorMap(beginColor, endColor, numSteps);
% a = makeColorMap(beginColor, middleColor, endColor);
% a = makeColorMap(beginColor, endColor);
%
% all colors are specified as RGB triples
% numSteps is a scalar saying howmany points are in the colormap
%
% Examples:
%
% peaks;
% a = makeColorMap([1 0 0],[1 1 1],[0 0 1],40);
% colormap(a)
% colorbar
%
% peaks;
% a = makeColorMap([1 0 0],[0 0 1],40);
% colormap(a)
% colorbar
%
% peaks;
% a = makeColorMap([1 0 0],[1 1 1],[0 0 1]);
% colormap(a)
% colorbar
%
% peaks;
% a = makeColorMap([1 0 0],[0 0 1]);
% colormap(a)
% colorbar

% Reference:
% A. Light & P.J. Bartlein, "The End of the Rainbow? Color Schemes for
% Improved Data Graphics," Eos,Vol. 85, No. 40, 5 October 2004.
% http://geography.uoregon.edu/datagraphics/EOS/Light&Bartlein_EOS2004.pdf

defaultNum = 100;
errorMessage = 'See help MAKECOLORMAP for correct input arguments';

if nargin == 2 %endPoints of colormap only
    color.start  = varargin{1};
    color.middle = [];
    color.end    = varargin{2};
    color.num    = defaultNum;
elseif nargin == 4 %endPoints, midPoint, and N defined
    color.start  = varargin{1};
    color.middle = varargin{2};
    color.end    = varargin{3};
    color.num    = varargin{4};
elseif nargin == 3 %endPoints and num OR endpoints and Mid
    if numel(varargin{3}) == 3 %color
        color.start  = varargin{1};
        color.middle = varargin{2};
        color.end    = varargin{3};
        color.num    = defaultNum;
    elseif numel(varargin{3}) == 1 %numPoints
        color.start  = varargin{1};
        color.middle = [];
        color.end    = varargin{2};
        color.num    = varargin{3};
    else
        error(errorMessage)
    end
else
    error(errorMessage)
end

if color.num <= 1
    error(errorMessage)
end

if isempty(color.middle) %no midPoint
    cMap = interpMap(color.start, color.end, color.num);
else %midpointDefined
    [topN, botN] = sizePartialMaps(color.num);
    cMapTop = interpMap(color.start, color.middle, topN);
    cMapBot = interpMap(color.middle, color.end, botN);
    cMap = [cMapTop(1:end-1,:); cMapBot];
end

function cMap = interpMap(colorStart, colorEnd, n)

for i = 1:3
    cMap(1:n,i) = linspace(colorStart(i), colorEnd(i), n);
end

function [topN, botN] = sizePartialMaps(n)
n = n + 1;

topN =  ceil(n/2);
botN = floor(n/2);
% Copyright 2008 - 2009 The MathWorks, Inc.


function M = spherefactory(n, m, gpuflag)
% Returns a manifold struct to optimize over unit-norm vectors or matrices.
%
% function M = spherefactory(n)
% function M = spherefactory(n, m)
% function M = spherefactory(n, m, gpuflag)
%
% Manifold of n-by-m real matrices of unit Frobenius norm.
% By default, m = 1, which corresponds to the unit sphere in R^n. The
% metric is such that the sphere is a Riemannian submanifold of the space
% of nxm matrices with the usual trace inner product, i.e., the usual
% metric.
%
% Set gpuflag = true to have points, tangent vectors and ambient vectors
% stored on the GPU. If so, computations can be done on the GPU directly.
%
% See also: obliquefactory spherecomplexfactory

% This file is part of Manopt: www.manopt.org.
% Original author: Nicolas Boumal, Dec. 30, 2012.
% Contributors:
% Change log:
%
%   Oct. 8, 2016 (NB)
%       Code for exponential was simplified to only treat the zero vector
%       as a particular case.
%
%   Oct. 22, 2016 (NB)
%       Distance function dist now significantly more accurate for points
%       within 1e-7 and less from each other.
%
%   July 20, 2017 (NB)
%       Following conversations with Bruno Iannazzo and P.-A. Absil,
%       the distance function is now even more accurate.
%
%   Sep. 7, 2017 (NB)
%       New isometric vector transport available in M.isotransp,
%       contributed by Changshuo Liu.
%
%   April 17, 2018 (NB)
%       ehess2rhess: Used to compute projection of ehess, then subtract a
%       multiple of u (which is assumed tangent.) Now, similarly to what
%       happens in stiefelfactory, we first subtract the multiple of u from
%       ehess, then we project. Mathematically, these operations are the
%       same. Numerically, the former version used to be better because tCG
%       in trustregions had some drift near fine convergence. Now that the
%       drift in tCG has been fixed, it is reasonable to apply the
%       projection last, to ensure best tangency of the output.
%
%   July 18, 2018 (NB)
%       Added the inverse retraction (M.invretr) for the sphere.
%
%   Aug. 3, 2018 (NB)
%       Added GPU support: just set gpuflag = true.
%
%   Jan. 8, 2021 (NB)
%       Added tangent2ambient/tangent2ambient_is_identity pair.

    if ~exist('m', 'var') || isempty(m)
        m = 1;
    end
    if ~exist('gpuflag', 'var') || isempty(gpuflag)
        gpuflag = false;
    end

    % If gpuflag is active, new arrays (e.g., via rand, randn, zeros, ones)
    % are created directly on the GPU; otherwise, they are created in the
    % usual way (in double precision).
    if gpuflag
        array_type = 'gpuArray';
    else
        array_type = 'double';
    end

    if m == 1
        M.name = @() sprintf('Sphere S^%d', n-1);
    else
        M.name = @() sprintf('Unit F-norm %dx%d matrices', n, m);
    end

    M.dim = @() n*m-1;

    M.inner = @(x, d1, d2) d1(:)'*d2(:);

    M.norm = @(x, d) norm(d, 'fro');

    M.dist = @dist;
    function d = dist(x, y)

        % The following code is mathematically equivalent to the
        % computation d = acos(x(:)'*y(:)) but is much more accurate when
        % x and y are close.

        chordal_distance = norm(x - y, 'fro');
        d = real(2*asin(.5*chordal_distance));

        % Note: for x and y almost antipodal, the accuracy is good but not
        % as good as possible. One way to improve it is by using the
        % following branching:
        % % if chordal_distance > 1.9
        % %     d = pi - dist(x, -y);
        % % end
        % It is rarely necessary to compute the distance between
        % almost-antipodal points with full accuracy in Manopt, hence we
        % favor a simpler code.

    end

    M.typicaldist = @() pi;

    M.proj = @(x, d) d - x*(x(:)'*d(:));

    M.tangent = M.proj;

    M.tangent2ambient_is_identity = true;
    M.tangent2ambient = @(X, U) U;

    % For Riemannian submanifolds, converting a Euclidean gradient into a
    % Riemannian gradient amounts to an orthogonal projection.
    M.egrad2rgrad = M.proj;

    M.ehess2rhess = @ehess2rhess;
    function rhess = ehess2rhess(x, egrad, ehess, u)
        rhess = M.proj(x, ehess - (x(:)'*egrad(:))*u);
    end

    M.exp = @exponential;

    M.retr = @retraction;
    M.invretr = @inverse_retraction;

    M.log = @logarithm;
    function v = logarithm(x1, x2)
        v = M.proj(x1, x2 - x1);
        di = M.dist(x1, x2);
        % If the two points are "far apart", correct the norm.
        if di > 1e-6
            nv = norm(v, 'fro');
            v = v * (di / nv);
        end
    end

    M.hash = @(x) ['z' hashmd5(x(:))];

    M.rand = @() random(n, m, array_type);

    M.randvec = @(x) randomvec(n, m, x, array_type);

    M.zerovec = @(x) zeros(n, m, array_type);

    M.lincomb = @matrixlincomb;

    M.transp = @(x1, x2, d) M.proj(x2, d);

    % Isometric vector transport of d from the tangent space at x1 to x2.
    % This is actually a parallel vector transport, see Ch. 5 in
    % http://epubs.siam.org/doi/pdf/10.1137/16M1069298
    % "A Riemannian Gradient Sampling Algorithm for Nonsmooth Optimization
    %  on Manifolds", by Hosseini and Uschmajew, SIOPT 2017
    M.isotransp = @(x1, x2, d) isometricTransp(x1, x2, d);
    function Td = isometricTransp(x1, x2, d)
        v = logarithm(x1, x2);
        dist_x1x2 = norm(v, 'fro');
        if dist_x1x2 > 0
            u = v / dist_x1x2;
            utd = u(:)'*d(:);
            Td = d + (cos(dist_x1x2)-1)*utd*u ...
                    -  sin(dist_x1x2)  *utd*x1;
        else
            % x1 == x2, so the transport is identity
            Td = d;
        end
    end

    M.pairmean = @pairmean;
    function y = pairmean(x1, x2)
        y = x1+x2;
        y = y / norm(y, 'fro');
    end

    M.vec = @(x, u_mat) u_mat(:);
    M.mat = @(x, u_vec) reshape(u_vec, [n, m]);
    M.vecmatareisometries = @() true;

    % Automatically convert a number of tools to support GPU.
    if gpuflag
        M = factorygpuhelper(M);
    end

end

% Exponential on the sphere
function y = exponential(x, d, t)

    if nargin == 2
        % t = 1
        td = d;
    else
        td = t*d;
    end

    nrm_td = norm(td, 'fro');
    y = x*cos(nrm_td) + td*sinxoverx(nrm_td);

end

% Retraction on the sphere
function y = retraction(x, d, t)

    if nargin == 2
        % t = 1;
        td = d;
    else
        td = t*d;
    end

    y = x + td;
    y = y / norm(y, 'fro');

end

% Given x and y two points on the manifold, if there exists a tangent
% vector d at x such that Retr_x(d) = y, this function returns d.
function d = inverse_retraction(x, y)

    % Since
    %   x + d = y*||x + d||
    % and x'd = 0, multiply the above by x' on the left:
    %   1 + 0 = x'y * ||x + d||
    % Then solve for d:

    d = y/(x(:)'*y(:)) - x;

end

% Uniform random sampling on the sphere.
function x = random(n, m, array_type)

    x = randn(n, m, array_type);
    x = x / norm(x, 'fro');

end

% Random normalized tangent vector at x.
function d = randomvec(n, m, x, array_type)

    d = randn(n, m, array_type);
    d = d - x*(x(:)'*d(:));
    d = d / norm(d, 'fro');

end


function value = p10_f ( dim_num, point_num, x )

%*****************************************************************************80
%
%% P10_F evaluates the integrand for problem 10.
%
%  Dimension:
%
%    DIM_NUM arbitrary.
%
%  Region:
%
%    0 <= X(1:DIM_NUM) <= 1
%
%  Integrand:
%
%    sum ( abs ( x(1:dim_num) - 0.5 ) )
%
%  Exact Integral:
%
%    DIM_NUM / 4
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 June 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Philip Davis, Philip Rabinowitz,
%    Methods of Numerical Integration,
%    Second Edition,
%    Dover, 2007,
%    ISBN: 0486453391,
%    LC: QA299.3.D28.
%
%    Thomas Patterson,
%    [Integral #4],
%    On the Construction of a Practical Ermakov-Zolotukhin
%    Multiple Integrator,
%    in Numerical Integration: Recent Developments, Software
%    and Applications,
%    edited by Patrick Keast, Graeme Fairweather,
%    D. Reidel, 1987, pages 269-290,
%    LC: QA299.3.N38.
%
%    Arthur Stroud,
%    Approximate Calculation of Multiple Integrals,
%    Prentice Hall, 1971,
%    ISBN: 0130438936,
%    LC: QA311.S85.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the dimension of the argument.
%
%    Input, integer POINT_NUM, the number of points.
%
%    Input, real X(DIM_NUM,POINT_NUM), the evaluation points.
%
%    Output, real VALUE(POINT_NUM), the integrand values.
%
  value(1:point_num) = 0.0;

  for point = 1 : point_num
    value(point) = sum ( abs ( x(1:dim_num,point) - 0.5 ) );
  end

  p10_i4 ( 'I', '#', point_num );

  return
end


function index = tileIndex(tile)
% Return the index of a 2-by-2 binary configuration tile.
%
%   INDEX = tileIndex(TILE)
%   Compute thes index of a tile, given as a 2-by-2 binary image, by adding
%   powers of two multiplied by values of the tile.
%   [0 0;0 0] has index 0
%   [1 0;0 0] has index 1
%   [0 1;0 0] has index 2
%   [1 1;0 0] has index 3
%   [0 0;1 0] has index 4
%   ...
%   [1 1;1 1] has index 15
%
%   Example
%   tileIndex
%
%   See also
%     createTile, tileIndex3d
%

% ------
% Author: David Legland
% e-mail: david.legland@inrae.fr
% Created: 2009-05-25,    using Matlab 7.7.0.471 (R2008b)
% Copyright 2009 INRA - Cepia Software Platform.

tile = tile > 0;
index = tile(1,1) + 2*tile(1,2) + 4*tile(2,1) + 8*tile(2,2);