function [ u, nullty, ifault ] = cholesky ( a, n, nn )

%*****************************************************************************80
%
%% CHOLESKY computes the Cholesky factorization of a PDS matrix.
%
%  Discussion:
%
%    For a positive definite symmetric matrix A, the Cholesky factor U
%    is an upper triangular matrix such that A = U' * U.
%
%    This routine was originally named "CHOL", but that conflicts with
%    the name of a built in MATLAB routine.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 February 2008
%
%  Author:
%
%    Original FORTRAN77 version by Michael Healy.
%    Modifications by AJ Miller.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Michael Healy,
%    Algorithm AS 6:
%    Triangular decomposition of a symmetric matrix,
%    Applied Statistics,
%    Volume 17, Number 2, 1968, pages 195-197.
%
%  Parameters:
%
%    Input, real A((N*(N+1))/2), a positive definite matrix
%    stored by rows in lower triangular form as a one dimensional array,
%    in the sequence
%    A(1,1),
%    A(2,1), A(2,2),
%    A(3,1), A(3,2), A(3,3), and so on.
%
%    Input, integer N, the order of A.
%
%    Input, integer NN, the dimension of the array used to store A,
%    which should be at least (N*(N+1))/2.
%
%    Output, real U((N*(N+1))/2), an upper triangular matrix,
%    stored by columns, which is the Cholesky factor of A.
%
%    Output, integer NULLTY, the rank deficiency of A.  If NULLTY is zero,
%    the matrix is judged to have full rank.
%
%    Output, integer IFAULT, an error indicator.
%    0, no error was detected;
%    1, if N < 1;
%    2, if A is not positive semi-definite.
%    3, if NN < (N*(N+1))/2.
%
%  Local Parameters:
%
%    Local, real ETA, should be set equal to the smallest positive
%    value such that 1.0 + ETA is calculated as being greater than 1.0 in the
%    accuracy being used.
%

%
%  Initialize output.
%
  u = [];
  nullty = 0;
  ifault = 0;

  eta = 1.0E-09;

  if ( n <= 0 )
    ifault = 1;
    return
  end

  if ( nn < floor ( ( n * ( n + 1 ) ) / 2 ) )
    ifault = 3;
    return
  end

  u(1:nn) = 0.0;
  j = 1;
  k = 0;
  ii = 0;
%
%  Factorize column by column, ICOL = column number.
%
  for icol = 1 : n

    ii = ii + icol;
    x = eta * eta * a(ii);
    l = 0;
    kk = 0;
%
%  IROW = row number within column ICOL.
%
    for irow = 1 : icol

      kk = kk + irow;
      k = k + 1;
      w = a(k);
      m = j;

      for i = 1 : irow - 1
        l = l + 1;
        w = w - u(l) * u(m);
        m = m + 1;
      end

      l = l + 1;

      if ( irow == icol )
        break
      end

      if ( u(l) ~= 0.0 )

        u(k) = w / u(l);

      else

        u(k) = 0.0;

        if ( abs ( x * a(k) ) < w * w )
          ifault = 2;
          return
        end

      end

    end
%
%  End of row, estimate relative accuracy of diagonal element.
%
    if ( abs ( w ) <= abs ( eta * a(k) ) )

      u(k) = 0.0;
      nullty = nullty + 1;

    else

      if ( w < 0.0 )
        ifault = 2;
        return
      end

      u(k) = sqrt ( w );

    end

    j = j + icol;

  end

  return
end


% Gauss-Seidel 迭代法（分量形式）求解方程组
clear;
% 输入值
A = [10, -1, -2; -1, 10, -2; -1, -1, 5];
b = [7.2; 8.3; 4.2];
tol = 1e-5;
N = 100;
x = [0; 0; 0];
x_backup = [0; 0; 0];
y = [0; 0; 0];
%
A_ = A;
for i = 1 : length(A)
    A_(i,i) = 0;
end

for i = 0 : N
    for j = 1 : length(A)
        y(j,1) = (b(j) - A_(j,:) * x) / A(j,j);
        x_backup(j) = x(j);   % 备份“老值”
        x(j) = y(j);     % “新值” 替换 “老值”
    end
    if (max(abs(x_backup - y)) < tol)
        fprintf('迭代次数: %d\n', i);
        fprintf('方程组的根: %10.8f\n', y);
        break;
    end
end
if i == N
    fprintf('迭代方法失败\n');
end


function [ fmin, a, b ] = p00_fmin ( a, b, problem, tol )

%*****************************************************************************80
%
%% P00_FMIN seeks a minimizer of a scalar function of a scalar variable.
%
%  Discussion:
%
%    FMIN seeks an approximation to the point where F attains a minimum on
%    the interval (A,B).
%
%    The method used is a combination of golden section search and
%    successive parabolic interpolation.  Convergence is never much
%    slower than that for a Fibonacci search.  If F has a continuous
%    second derivative which is positive at the minimum (which is not
%    at A or B), then convergence is superlinear, and usually of the
%    order of about 1.324....
%
%    The function F is never evaluated at two points closer together
%    than EPS * ABS ( FMIN ) + (TOL/3), where EPS is approximately the
%    square root of the relative machine precision.  If F is a unimodal
%    function and the computed values of F are always unimodal when
%    separated by at least EPS * ABS ( XSTAR ) + (TOL/3), then FMIN
%    approximates the abcissa of the global minimum of F on the
%    interval [A, B] with an error less than 3 * EPS * ABS ( FMIN ) + TOL.
%    If F is not unimodal, then FMIN may approximate a local, but
%    perhaps non-global, minimum to the same accuracy.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    09 February 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Richard Brent,
%    Algorithms for Minimization without Derivatives,
%    Prentice Hall, 1973.
%
%    David Kahaner, Cleve Moler, Steven Nash,
%    Numerical Methods and Software,
%    Prentice Hall, 1988.
%
%  Parameters
%
%    Input, real A, B, the left and right endpoints of the initial interval.
%
%    Input, integer PROBLEM, the index of a problem.
%
%    Input, real TOL, the desired length of the interval of
%    uncertainty of the final result.  TOL must not be negative.
%
%    Output, real FMIN, the abcissa approximating the
%    minimizer of f.
%
%    Output, real A, B, the lower and upper bounds for the minimizer.
%
  c = 0.5 * ( 3.0 - sqrt ( 5.0 ) );
%
%  C is the squared inverse of the golden ratio.
%
%  EPSILON is the square root of the relative machine precision.
%
  epsilon = sqrt ( eps );
%
%  Initialization.
%
  v = a + c * ( b - a );
  w = v;
  x = v;
  e = 0.0;
  fx = p00_f ( problem, x );
  fv = fx;
  fw = fx;
%
%  The main loop starts here.
%
  while ( 1 )

    midpoint = 0.5 * ( a + b );
    tol1 = epsilon * abs ( x ) + tol / 3.0;
    tol2 = 2.0 * tol1;
%
%  Check the stopping criterion.
%
    if ( abs ( x - midpoint ) <= ( tol2 - 0.5 * ( b - a ) ) )
      break
    end
%
%  Is golden-section necessary?
%
    if ( abs ( e ) <= tol1 )
      if ( midpoint <= x )
        e = a - x;
      else
        e = b - x;
      end

      d = c * e;
%
%  Consider fitting a parabola.
%
    else

      r = ( x - w ) * ( fx - fv );
      q = ( x - v ) * ( fx - fw );
      p = ( x - v ) * q - ( x - w ) * r;
      q = 2.0 * ( q - r );
      if ( 0.0 < q )
        p = -p;
      end
      q = abs ( q );
      r = e;
      e = d;
%
%  Choose a golden-section step if the parabola is not advised.
%
      if ( ...
        ( abs ( 0.5 * q * r ) <= abs ( p ) ) | ...
        ( p <= q * ( a - x ) ) | ...
        ( q * ( b - x ) <= p ) )

        if ( midpoint <= x )
          e = a - x;
        else
          e = b - x;
        end

        d = c * e;
%
%  Choose a parabolic interpolation step.
%
      else

        d = p / q;
        u = x + d;

        if ( ( u - a ) < tol2 )
          d = abs ( tol1 ) * r8_sign ( midpoint - x );
        end

        if ( ( b - u ) < tol2 )
          d = abs ( tol1 ) * r8_sign ( midpoint - x );
        end

     end

   end
%
%  F must not be evaluated too close to X.
%
    if ( tol1 <= abs ( d ) )
      u = x + d;
    end

    if ( abs ( d ) < tol1 )
      u = x + abs ( tol1 ) * r8_sign ( d );
    end

    fu = p00_f ( problem, u );
%
%  Update the data.
%
    if ( fu <= fx )

      if ( x <= u )
        a = x;
      else
        b = x;
      end

      v = w;
      fv = fw;
      w = x;
      fw = fx;
      x = u;
      fx = fu;
      continue

    end

    if ( u < x )
      a = u;
    else
      b = u;
    end

    if ( fu <= fw | w == x )
      v = w;
      fv = fw;
      w = u;
      fw = fu;
    elseif ( fu <= fv | v == x | v == w )
      v = u;
      fv = fu;
    end

  end

  fmin = x;

  return
end


function circVar=findCircVar(x,w)
%%FINDCIRCVAR Given a set of samples of a circular distribution, determine
%             the circular variance. As in Chapter 2.3.1 of [1], this is
%             just 1 minus the resultant length of the first trigonometric
%             moment.
%INPUTS: x The 1XN or NX1 vector of possibly weighted samples.
%        w The NX1 weights associated with the samples. If this parameter
%          is omitted or an empty matrix is passed, then the samples are
%          uniformly weighted.
%
%OUTPUTS: circVar The circular variance of the measurements.
%
%The mean resultant length is found using findTrigMomentFromSamp and is
%then subtracted from 1.
%
%REFERENCES
%[1] K. V. Mardia and P. E. Jupp, Directional Statistics. Chichester: John
%    Wiley and Sons, 2000.
%
%April 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<2)
    w=[];
end

[~,~,RS]=findTrigMomentFromSamp(1,x,w);
circVar=1-RS;

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 FR = factorialratio(A,B)
% FACTORIALRATIO - ratio of factorial numbers
%
%   FR = FACTORIALRATIO (A,B) calculates the ratio between products of
%   factorials specified by A and B.  A and B are lists of positive
%   integers, with N and M elements, respectively. The number of values in
%   each list may differ. The factorial ratio is based on the following formula:
%
%              (A1! * A2! * ... * AN!)
%      FR  =  -------------------------
%              (B1! * B2! * ... * BM!)
%
%    However, an approach is taken that increases the accuracy when A or B
%    contain larger values, as mentioned in the help of FACTORIAL.
%
%    Examples:
%
%      f1 = factorialratio([10 8 6],[9 6 5]) ;
%      f2 = 10 * 8 * 7 * 6 ; % by hand
%      f3 = (factorial(10) * factorial(8) * factorial(6)) ./ ...
%            (factorial(9) * factorial(6) * factorial(5)) ;
%      disp('f1, f2, f3 = ') ; disp([f1 f2 f3])
%
%
%      % Also for larger values FACTORIALRATIO works correctly
%      f1 = factorialratio(150,143) ;
%      f2 = prod(144:150) ; % by hand
%      % where FACTORIAL lacks precision
%      f3 = factorial(150) ./ factorial(143) ;
%      disp('f1, f2, f3 = ') ; disp([f1 f2 f3])
%      disp('   Differences with f2 = ') ; disp([f1-f2 f2-f2 f3-f2])
%
%      % and even for extreme numbers things turn out well
%      f1 = factorialratio(30000,29998) ;
%      f2 = (30000 * 29999) ; % by hand
%      % whereas calls to FACTORIAL fail miserably ...
%      f3 = factorial(30000) ./ factorial(29998) ;
%      disp('f1, f2, f3 = ') ; disp([f1 f2 f3])
%
%    Note that, for instance, factorialratio(200,1) also fails, of course.
%    For such occasions other engines have to be used.
%
%    See also PROD, FACTORIAL, GAMMALN

% for Matlab R13 and up
% version 2.0 (oct 2012)
% (c) Jos van der Geest
% email: jos@jasen.nl

% History
% 1.0 (feb 2009) - created for (later) use in a statistical test
% 1.1 (feb 2009) - fixed minor bug in error checking
% 2.0 (oct 2012) - fixed bug "maxE > 1" which should be "maxE > 0". Thanks
%                  to 'Charles' for pointing this out.

% check the input arguments
error(nargchk(2,2,nargin)) ;
if isempty(A) || isempty(B) || ...
    ~isnumeric(A) || ~isnumeric(B) || ...
    any(A(:)<0) || any(fix(A(:)) ~= A(:)) || ...
    any(B(:)<0) || any(fix(B(:)) ~= B(:))
    error('Inputs should be numerical arrays with positive integers.')
end

% Example for terminology used in comments:
%   FR = factorialratio([6 4],[3 2 1])      call
%      = (6! * 4!) / (3! * 2!)              numerators / denominators  (ignoring ones)
%      = 6*5*4*3*2*4*3*2 / 3*2*2            expanded factorial (showing all factors > 1)
%         [6 5 4 3 2] .^ [1 1 1 2 2]
%      = ----------------------------       as powers (factors and exponents)
%         [6 5 4 3 2] .^ [0 0 0 1 2]
%
%      = [6 5 4 3 2] .^ [1 1 1 1 0]         rewritten

% only values larger than 2 have an effect as both 1! and 0! equal 1
% we can subtract 1 if we do not forget to add 1 later
A = A(A>1) - 1 ;
B = B(B>1) - 1 ;

% what is the largest element?
maxE = max([A(:) ; B(:) ; 0]) ;

if maxE > 0 && ~isequal(A,B),
    % Create a 2 by m array holding the elements of A and B:
    % - the first column refers to the numerators of the ratio (A)
    % - the second column refers to the denominators of the ratio (B)
    R = sparse(A,1,1,maxE,2) + sparse(B,2,1,maxE,2) ;

    % By flipping, cumsumming (over columns) and flipping again ...
    R = flipud(cumsum(flipud(R))) ;
    % ... we get numbers that indicate how many times a factor is present in
    % the expanded ratio. R(X,1) indicates the number of times (X+1) is present in
    % the numerator in the expanded ratio, and R(X,2) the number of times
    % (X+1) is present in the denominator. The difference will give us the
    % exponent for taking the power of the value (X+1).
    R = (R(:,1) - R(:,2)).' ;    % exponents
    X = 2:(maxE+1) ;             % base numbers (we now do need to add the 1)

    % We only used the nonzero entries, since X^0 = 1, and this may affect
    % the time used for ...
    q = find(R) ;
    % ... getting the total product
    FR = prod(X(q).^R(q)) ; %
else
    % All elements were less than 2, or A equals B
    FR = 1 ;
end


function e = line_cvt_energy ( n, a, b, x )

%*****************************************************************************80
%
%% LINE_CVT_ENERGY computes the CVT energy for a given set of generators.
%
%  Discussion:
%
%    Given a set of generators G over the line [A,B], then the energy
%    is defined as
%      E = integral ( a <= x <= b ) ( x - g(x) )^2 dx
%    where g(x) is the nearest generator to the point x.
%
%    For the 1D case, this integral can be evaluated exactly as the
%    sum of integrals over each subinterval:
%
%      E(i) = integral ( xl <= x <= xr ) ( x - x(i) )^2 dx
%           = ( ( x(i) - xl )^3 + ( xr - x(i) )^3 ) / 3
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    28 July 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of generators.
%
%    Input, real A, B, the left and right endpoints.
%
%    Input, real X(N), the generator locations.
%
%    Output, real E, the energy of the generator distribution.
%
  e = 0.0;

  for j = 1 : n

    if ( j == 1 )
      xl = a;
    else
      xl = ( x(j-1) + x(j) ) / 2.0;
    end

    if ( j == n )
      xr = b;
    else
      xr = ( x(j) + x(j+1) ) / 2.0;
    end

    e = e + ( ( x(j) - xl )^3 + ( xr - x(j) )^3  ) / 3.0;

  end

  return
end


function [ x, seed ] = normal_01_sample ( seed )

%*****************************************************************************80
%
%% NORMAL_01_SAMPLE samples the standard normal probability distribution.
%
%  Discussion:
%
%    The standard normal probability distribution function (PDF) has
%    mean 0 and standard deviation 1.
%
%    The Box-Muller method is used.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 August 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer SEED, a seed for the random number generator.
%
%    Output, X, a sample of the standard normal PDF.
%
%    Output, integer SEED, an updated seed for the random number generator.
%
  [ r1, seed ] = r8_uniform_01 ( seed );
  [ r2, seed ] = r8_uniform_01 ( seed );
  x = sqrt ( -2.0 * log ( r1 ) ) * cos ( 2.0 * pi * r2 );

  return
end


function [y,yp] = fatan(x)
% FATAN  Arctangent function with optional derivative.
%        [Y,YP] = FATAN(X) returns Y=atan(X) and
%        (optionally) YP = 1/(1+X^2)
%
%
y = atan(x);
if nargout == 2
    yp = 1/(1+x^2);
end


function value = ball_unit_volume_3d ( )

%*****************************************************************************80
%
%% BALL_UNIT_VOLUME_3D computes the volume of a unit ball in 3D.
%
%  Integration region:
%
%    Points (X,Y,Z) such that
%
%      X**2 + Y**2 + Z**2 <= 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    26 May 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Output, real BALL_UNIT_VOLUME_3D, the volume of the ball.
%
  value = ( 4.0E+00 / 3.0E+00 ) * pi;

  return
end


function lambda = lambda_measure ( dim_num, n, z )

%*****************************************************************************80
%
%% LAMBDA_MEASURE determines the pointset quality measure LAMBDA.
%
%  Discussion:
%
%    The LAMBDA measure of point distribution quality for a set Z of
%    N points in an DIM_NUM-dimensional region is defined as follows:
%
%    Let
%
%      GAMMA(I) = minimum ( 1 <= J <= N, I /= J ) distance ( Z(I), Z(J) )
%
%    and let
%
%      GAMMA_AVE = sum ( 1 <= I <= N ) GAMMA(I) / N
%
%    then
%
%      LAMBDA = sqrt ( sum ( 1 <= I <= N ) ( GAMMA(I) - GAMMA_AVE )**2 / N )
%        / GAMMA_AVE
%
%    An ideally regular mesh would have GAMMA(I) = GAMMA_AVE for all I,
%    so that LAMBDA would be 0.  Under this measure, the mesh with the
%    smaller value of LAMBDA is to be preferred.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 November 2004
%
%  Author:
%
%    Max Gunzburger
%    John Burkardt
%
%  Reference:
%
%    Max Gunzburger and John Burkardt,
%    Uniformity Measures for Point Samples in Hypercubes.
%
%  Parameters:
%
%    Input, integer DIM_NUM, the spatial dimension.
%
%    Input, integer N, the number of points.
%
%    Input, real Z(DIM_NUM,N), the points.
%
%    Output, real LAMBDA, the LAMBDA quality measure.
%
%  Local parameters:
%
%    Local, real GAMMA_MAX, the maximum, over all points,
%    of the minimum distance to a distinct point.
%
%    Local, real GAMMA_MIN, the minimum, over all points,
%    of the minimum distance to a distinct point.
%

%
%  Take care of ridiculous cases.
%
  if ( n <= 1 )
    lambda = 0.0;
    return
  end
%
%  Compute the minimum spacing between distinct points of the set.
%
  gamma = pointset_spacing ( dim_num, n, z );
%
%  Average the minimum spacing.
%
  gamma_ave = sum ( gamma(1:n) ) / n;
%
%  Compute a weighted variance.
%
  if ( gamma_ave <= 0.0 )
    lambda = r8_huge ( );
  else
    lambda = sqrt ( sum ( ( gamma(1:n) - gamma_ave ).^2 ) / n ) / gamma_ave;
  end

  return
end


function Adj = polygon(N, d, rad)
% Adj = polygon(N, d, rad)
% Plots the regular polygon {N/d} with vertices on a circle of radius
% 'rad'. The output 'Adj' is the adjacency matrix of the corresponding
% graph.
%
% Description:
% ------------
% Let d < N be a positive integer and define p = N/d.
% Let y_{1} be a point on the unit circle. Let R be clockwise
% rotation by the angle t = 2*pi/p. The generalized regular
% polygon {p} is given by the points y_{i+1} = R * y_{i}, and edges
% between points i and i+1.
%
% Example:
% --------
% polygon(9, 4, 1);
%
%
% Nima Moshtagh (nima@seas.upenn.edu)
% University of Pennsylvania
%
% Sept. 2007
%

% check the values of 'd' and 'N'. They must be integers.
if (d - round(d)) ~= 0 || (N - round(N)) ~= 0
    display('error: Input parameters N and d must be integers!');
    return;
elseif d > N,
        display('error: d must be less than or equal to N.');
        return
else
    p = N/d;
    t = 2*pi/p;
end

% generate the vertices.
%theta = [pi/N : 2*pi/N : 2*pi];
theta = [0 : 2*pi/N : 2*pi]
Pos = rad * exp(i*theta);

X = real(Pos);
Y = imag(Pos);

% plot the vertices on a circle
plot(X,Y,'o');
axis([-2*rad 2*rad -2*rad 2*rad]);

A = zeros(N);
for j = 1:N,
    % compute the position of the neighboring vertix
    node = exp(i*t) *Pos(j);
    xx = real(node);
    yy = imag(node);

    % find the index of the neighboring vertix
    indx = mod(j+d,N);
    if indx == 0,
        indx = N;
    end
    A(j,indx) = 1;
    % connect the vertices
    line([X(j) xx], [Y(j) yy]);
end
axis equal
% the Adjacency matrix
Adj = A + A';


function fx = p10_fun ( n, x )

%*****************************************************************************80
%
%% P10_FUN evaluates the integrand for problem 10.
%
%  Interval:
%
%    0 <= x <= 1
%
%  Integrand:
%
%    1 / ( 1 + x )
%
%  Antiderivative:
%
%    ln ( 1 + x )
%
%  Exact Integral:
%
%    ln ( 2 )
%
%  Approximate Integral (25 digits):
%
%    0.6931471805599453094172321...
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    03 November 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    David Kahaner,
%    Comparison of Numerical Quadrature Formulas,
%    in Mathematical Software, edited by John R Rice,
%    Academic Press, 1971.
%
%  Parameters:
%
%    Input, integer N, the number of evaluation points.
%
%    Input, real X(N), the evaluation points.
%
%    Output, real FX(N), the integrand values.
%
  fx = 1.0 ./ ( 1.0 + x );

  return
end


function root = newton(f,g,xo,epsilon)
% Program : newton.m
%
% Purpose : find the root of a given single variable function within the
%           given interval
%
% Author :  Aamir Alaud Din
% Date :    20.09.2013
%
% Inputs :  At least three input arguments are required viz., function,
%           derivative of the function, and initial guess
%
% Syntax :  root = newton(f,g,xo)
%           where f is an inline function and is continuous in the given
%           interval
%           e.g., f = inline('sin(x)','x');
%           g is the first derivative of f in the form of inline function
%           and is continuous in the given interval
%           e.g., g = inline('cos(x)','x');
%           xo is the initial guess which lies in the given interval
%
% Example:  root = newton(f,g,5)
%           The fourth input argument is the stopping criteria
%           If the function value deceeds epsilon, the loop terminates
%           giving the root. Default is 1e-6.
%
% Syntax :  root = newton(f,g,xo,epsilon)
%           where f, g, xo, and epsilon are explained above.
%
% Example:  root = bisection(f,g,-2,1e-9)

if (nargin < 3)
    error('Less input arguments provided.');

elseif (nargin == 3)
    epsilon = 1e-6;
    Iter = 0;
    fprintf('Iteration\t\t   xo\t\t   x1\t\t\tf(x)\t\t\tg(x)\n');
    fprintf('=========\t\t ======\t\t ======\t\t===========\t\t===========\t\t\n');
    while (abs(f(xo)) >= epsilon)
        Iter = Iter + 1;
        if (g(xo) == 0)
            fprintf('g(xo) is zero on iteration number %d',Iter);
            fprintf('\n');
            disp('We can''t compute the root');
            return;
        end
        x1 = xo - (f(xo)/g(xo));
        fprintf('%3d',Iter);
        fprintf('%20.4f',xo);
        fprintf('%12.4f',x1);
        fprintf('%16.4f',f(xo));
        fprintf('%16.4f',g(xo));
        fprintf('\n');
        xo = x1;
    end
    root = xo;
elseif (nargin == 4)
    Iter = 0;
    fprintf('Iteration\t\t   xo\t\t   x1\t\t\tf(x)\t\t\tg(x)\n');
    fprintf('=========\t\t ======\t\t ======\t\t===========\t\t===========\t\t\n');
    while (abs(f(xo)) >= epsilon)
        Iter = Iter + 1;
        if (g(xo) == 0)
            fprintf('g(xo) is zero on iteration number %d',Iter);
            fprintf('\n');
            disp('We can''t compute the root');
            return;
        end
        x1 = xo - (f(xo)/g(xo));
        fprintf('%3d',Iter);
        fprintf('%20.4f',xo);
        fprintf('%12.4f',x1);
        fprintf('%16.4f',f(xo));
        fprintf('%16.4f',g(xo));
        fprintf('\n');
        xo = x1;
    end
    root = xo;
end


%% Ex. 11 Another example for the usage of index for a matrix

A = [3 5; 2 4];
norm1 = 0;
for m = 1:2
for n = 1:2
 norm1 = norm1+A(m,n)^2;
end
end
norm1 = sqrt(norm1)

%Output:
%    norm1 = 7.348
% Remark: This program calculates the Euclidean norm of the A matrix


function C=discSinCosTrans(x,type)
%%DISCSINCOSTRANS Compute the 1D discrete sine or cosine transformation of
%              a given array. All 16 standard types of sine and cosine
%              transforms are available plus a unitary version of the type
%              II even cosine transform.
%
%INPUTS: x  An (N+1)X1 or 1X(N+1) real or complex vector whose discrete
%           sine or cosine transform is desired.
%     type  A string specifying the type of discrete sine or cosine
%           transform desired. If omitted or an empty matrix is passed, the
%           default is 'CIIe'. Possible values are:
%           'CIe' Perform a type I even discrete cosine transform. The
%                 item in element k of the result is
%                 x(0)+(-1)^k*X(N-1)+2*sum_{j=1}^{N-2}x(j)*cos(pi*j*k/(N-1))
%                 where all indexation is form 0.
%           'CIIe' Perform a type II even discrete cosine transform. The
%                 item in element k of the result is the sum from n=0 to
%                 N-1 of
%                 2*x(n)*cos(pi*k*(n+1/2)/N), where all indexation is from
%                 0.
%         'CIIeU' This is the same as type CIIe, except for scaling. The
%                 scaling is
%                 CU(1)=CII(1)/(2*sqrt(N));
%                 CU(2:end)=CII(2:end)*0.5*sqrt(2/N); where CIIe is the
%                 type 2 transform and CU is the unitary transform.
%         'CIIIe' Perform a type III even discrete cosine transform.
%          'CIVe' Perform a type IV even discrete cosine transform.
%           'CIo' Perform a type I odd discrete cosine transform.
%          'CIIo' Perform a type II odd discrete cosine transform.
%         'CIIIo' Perform a type III odd discrete cosine transform.
%          'CIVo' Perform a type IV odd discrete cosine transform.
%           'SIe' Perform a type I even discrete sine transform.
%          'SIIe' Perform a type II even discrete sine transform.
%         'SIIIe' Perform a type III even discrete sine transform.
%          'SIVe' Perform a type IV even discrete sine transform.
%         'SIIIe' Perform a type III even discrete sine transform.
%          'SIVe' Perform a type IV even discrete sine transform.
%           'SIo' Perform a type I odd discrete sine transform.
%          'SIIo' Perform a type II odd discrete sine transform.
%         'SIIIo' Perform a type III odd discrete sine transform.
%          'SIVo' Perform a type IV odd discrete sine transform.
%
%OUTPUTS: C The (N+1)X1 or 1X(N+1) real discrete cosine or sine
%           transformation of x.
%
%The algorithms are implemented using the generalized discrete Fourier
%transform (GDFT) based upon the relations of the sequences and the GDFT
%that are given in [1]. The definition of the unitary version of the type
%II transformation is taken from [2].
%
%The inverse of this function is invDiscSinCosTrans.
%
%REFERENCES:
%[1] S. Martucci, "Symmetric convolution and the discrete sine and cosine
%    transforms," IEEE Transactions on Signal Processing, vol. 42, no. 5,
%    pp. 1038-1051, May 1994.
%[2] J. Makhoul, "A fast cosine transform in one and two dimensions," IEEE
%    Transactions on Acoustics, Speech, and Signal Processing, vol. ASSP-
%    28, no. 1, pp. 27-34, Feb. 1980.
%
%December 2016 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if(nargin<2)
    type='CIIe';
end

N=length(x);
if(size(x,1)==N)
    colVec=true;
else
    colVec=false;
end

x=x(:);
switch(type)
    case 'CIIeU'
        %Perform the CIIe transform
        C=genDFT([x;flip(x)],0,1/2);
        C=C(1:N);

        %Modify the weighting.
        C(1)=C(1)/(2*sqrt(N));
        C(2:end)=C(2:end)*0.5*sqrt(2/N);
    case 'CIe'
        C=fft([x;x((N-1):-1:2)]);
        C=C(1:N);
    case 'CIIe'
        C=genDFT([x;flip(x)],0,1/2);
        C=C(1:N);
    case 'CIIIe'
        C=genDFT([x;0;-flip(x(2:end))],1/2,0);
        C=C(1:N);
    case 'CIVe'
        C=genDFT([x;-flip(x)],1/2,1/2);
        C=C(1:N);
    case 'CIo'
        C=fft([x;flip(x(2:end))]);
        C=C(1:N);
    case 'CIIo'
        C=genDFT([x;flip(x(1:(end-1)))],0,1/2);
        C=C(1:N);
    case 'CIIIo'
        C=genDFT([x;-flip(x(2:end))],1/2,0);
        C=C(1:N);
    case 'CIVo'
        C=genDFT([x;0;-flip(x)],1/2,1/2);
        C=C(1:N);
    case 'SIe'
        C=1j*fft([0;x;0;-flip(x)]);
        C=C(2:(N+1));
    case 'SIIe'
        C=1j*genDFT([x;-flip(x)],0,1/2);
        C=C(2:(N+1));
    case 'SIIIe'
        C=1j*genDFT([0;x(1:end);flip(x(1:(end-1)))],1/2,0);
        C=C(1:N);
    case 'SIVe'
        C=1j*genDFT([x;flip(x)],1/2,1/2);
        C=C(1:N);
    case 'SIo'
        C=1j*fft([0;x;-flip(x)]);
        C=C(2:(N+1));
    case 'SIIo'
        C=1j*genDFT([x;0;-flip(x)],0,1/2);
        C=C(2:(N+1));
    case 'SIIIo'
        C=1j*genDFT([0;x;flip(x)],1/2,0);
        C=C(1:N);
    case 'SIVo'
        C=1j*genDFT([x;flip(x(1:(end-1)))],1/2,1/2);
        C=C(1:N);
    otherwise
        error('Discrete cosine transform type not suported.')
end

%Get rid of finite precision errors. We know that if the purely input is
%real or imaginary, then the output must be the same.
if(isreal(x))
	C=real(C);
elseif(isImag(x))
    C=1j*imag(C);
end

if(~colVec)
    C=C.';
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.


classdef ChiSquareD
%%CHISQUARED Functions to handle the central or non-central chi-squared
%            distributions. These distributions arise when summing the
%            squares of independent normal random variables. The result is
%            central if the mean of the normal random variables was zero.
%Implemented methods are: mean, var, PDF, CDF, invCDF (only for the central
%                         chi squared distribution), rand, (only for the
%                         central chi squared distribution) entropy
%
%DEPENDENCIES: GammaD.m
%
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

methods(Static)

function val=mean(nu,lambda)
%%MEAN Obtain the mean of chi squared probability distribution.
%
%INPUTS: nu The number of degrees of freedom of the chi-squared
%           distribution. Note that nu>0.
%    lambda The non-centrality parameter of the distribution. In the
%           central chi-squared distribution, this is zero.
%
%OUTPUTS: val The mean of the chi squared distribution under consideration.
%
%The noncentral chi-squared distribution is descirbed in [1].
%
%REFERENCES:
%[1] Weisstein, Eric W. "Noncentral Chi-Squared Distribution." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(nargin<2||isempty(lambda))
        lambda=0;
    end

    val=nu+lambda;
end

function val=var(nu,lambda)
%%VAR Obtain the variance of chi squared probability distribution for the
%     given number of degrees of freedom.
%
%INPUTS: nu The number of degrees of freedom of the chi-square
%           distribution. Note that nu>0.
%    lambda The non-centrality parameter of the distribution. In the
%           central chi-squared distribution, this is zero.
%
%OUTPUTS: val The variance of the chi squared distribution under
%             consideration.
%
%The noncentral chi-squared distribution is descirbed in [1].
%
%REFERENCES:
%[1] Weisstein, Eric W. "Noncentral Chi-Squared Distribution." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
%
%October 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(nargin<2||isempty(lambda))
        lambda=0;
    end

    val=2*nu+4*lambda;
end

function val=PDF(x,nu,lambda)
%%PDF Evaluate the chi squared probability distribution function (PDF) at
%     the desired points.
%
%INPUTS: x The point(s) at which the chi-squared PDF is to be evaluated.
%          Note that x>=0 for nonzero probabilities.
%       nu The number of degrees of freedom of the chi-square distribution.
%          Note that nu>0.
%   lambda The non-centrality parameter of the distribution. In the central
%          chi-squared distribution, this is zero.
%
%OUTPUTS: val The value(s) of the chi squared PDF evaluated at x.
%
%The noncentral chi-squared distribution is descirbed in [1].
%
%When lambda is very small but nonzero, the PDF function could run into
%problems due to the logarithm of lambda. The logarithms were used instead
%of a simpler form to lessen the numerical instability. If an invalid value
%for the noncentral distribution is obtained, it is assumed that it is due
%to using an extremely small nonzero value of lambda, and the result is
%approximated using lambda=0.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Noncentral Chi-Squared Distribution." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(nargin<3||isempty(lambda))
        lambda=0;
    end

    if(lambda==0)
        val=(1/(2^(nu/2)*gamma(nu/2))).*x.^((nu-2)/2).*exp(-x/2);
    else
        val=0.5*exp(-(x+lambda)/2+(nu/4-0.5)*(log(x)-log(lambda))).*besseli(nu/2-1,sqrt(lambda*x));

        if(~isfinite(val))
            val=(1/(2^(nu/2)*gamma(nu/2))).*x.^((nu-2)/2).*exp(-x/2);
        end
    end

    val(x<0)=0;
end

function prob=CDF(x,nu,lambda)
%%CDF Evaluate the cumulative distribution function (CDF) of the central or
%     noncentral chi-squared distribution at desired points.
%
%INPUTS: x The point(s) at which the chi-squared CDF is to be evaluated.
%          Note that x>0 for nonzero values.
%       nu The number of degrees of freedom of the chi-square distribution.
%          Note that nu>0. When lambda is not zero, the CDF function is
%          numerically stabler when nu is an integer.
%   lambda The non-centrality parameter of the distribution. In the central
%          chi-squared distribution, this is zero.
%
%OUTPUTS: prob The value(s) of the CDF of the chi-squared distribution with
%              nu degrees of freedom and noncentrality parameter lambda
%              evaluated at x.
%
%The CDF of the central chi squared function with nu degrees of freedom
%evaluated at x is just a special case of the incomplete gamma function, as
%described at [1]. The incomplete gamma function is built into Matlab
%without the use of any toolboxes. When the noncentrality parameter is
%nonzero, the CDF is evaluated in terms of the equivalent noncentral gamma
%distribution. The noncentral gamma algorithm is documented further in
%GammaD.m.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Noncentral Chi-Squared Distribution." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.
%Updated to use the noncentral gamma distribution's function
%December 2014 David A. Karnick, Naval Research Laboratory, Washington D.C.

    if(nargin<3||isempty(lambda))
        lambda=0;
    end

    if(lambda==0)
        prob=gammainc(x/2,nu/2);
    else
        prob=GammaD.CDF(x,nu/2,2,lambda);
    end
    prob(x<=0)=0;
end

function val=invCDF(prob,nu)
%%INVCDF Evaluate the inverse of the cumulative distribution function (CDF)
%        of the central chi squared distribution. This is only implemented
%        for the central chi-squared distribution.
%
%INPUTS: prob The probability or probabilities (0<=prob<=1) at which the
%             argument of the CDF is desired.
%          nu The number of degrees of freedom of the chi-squared
%             distribution. Note that nu>0.
%
%OUTPUTS: val The argument(s) of the CDF that would give the probability or
%             probabilities in prob.
%
%The CDF of the chi squared function with nu degrees of freedom evaluated
%at x is just a special case of the incomplete gamma function, as described
%on Mathworld at [1]. The inverse incomplete gamma function is built into
%Matlab without the use of any toolboxes and thus is called here.
%
%REFERENCES:
%[1] Weisstein, Eric W. "Noncentral Chi-Squared Distribution." From
%    MathWorld--A Wolfram Web Resource.
%    http://mathworld.wolfram.com/NoncentralChi-SquaredDistribution.html
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    val=2*gammaincinv(prob,nu/2);
end

function vals=rand(N,nu,lambda)
%%RAND Generate chi-squared distributed random variables with the given
%      parameters.
%
%INPUTS: N If N is a scalar, then rand returns an NXN matrix of random
%          variables. If N=[M,N1] is a two-element row vector, then rand
%          returns an MXN1 matrix of random variables.
%       nu The number of degrees of freedom of the chi-squared
%          distribution. Note that nu>0. If lambda is not zero, nu >=1.
%   lambda The non-centrality parameter of the distribution. In the central
%          chi-squared distribution, this is zero. If this parameter is
%          omitted or an empty matrix is passed, then 0 is used.
%
%OUTPUTS: vals A matrix whose dimensions are determined by N of the
%              generated chi-squared random variables.
%
%The algorithm for the central chi squared distribution is an
%implementation of the inverse transform algorithm of Chapter 5.1 of [1].
%When the noncentral distribution is used, the random variables are
%generated by summing the squares of normally distributed random variables.
%
%A non-central chi squared distribution is the sum of a chi-squared
%distribution with nu-1 degrees of freedom plus the squared of a normal
%distribution with mean sqrt(lambda) and standard deviation 1. This is how
%the noncentral distribution is generated and why it is required that
%nu>=1.
%
%REFERENCES:
%[1] S. M. Ross, Simulation, Ed. 4, Amsterdam: Elsevier, 2006.
%
%September 2013 David F. Crouse, Naval Research Laboratory, Washington D.C.

    if(nargin<3||isempty(lambda))
        lambda=0;
    end

    if(isscalar(N))
        dims=[N, N];
    else
        dims=N;
    end

    if(lambda==0)
        U=rand(dims);
        vals=ChiSquareD.invCDF(U,nu);
    else
        U=rand(dims);
        vals=ChiSquareD.invCDF(U,nu-1)+(sqrt(lambda)+randn(N)).^2;
    end
end

function entropyVal=entropy(nu)
%%ENTROPY Obtain the differential entropy of the central chi squared
%         distribution given in nats. The differential entropy of a
%         continuous distribution is entropy=-int_x p(x)*log(p(x)) dx where
%         the integral is over all values of x. Units of nats mean that the
%         natural logarithm is used in the definition. Unlike the Shannon
%         entropy for discrete variables, the differential entropy of
%         continuous variables can be both positive and negative.
%
%INPUTS: nu The number of degrees of freedom of the chi-squared
%           distribution. Note that nu>0
%
%OUTPUTS: entropyVal The value of the differential entropy in nats.
%
%Differential entropy is defined in Chapter 8 of [1].
%
%REFERENCES:
%[1] T. M. Cover and J. A. Thomas, Elements of Information Theory, 2nd ed.
%    Hoboken, NJ: Wiley-Interscience, 2006.
%
%April 2018 David F. Crouse, Naval Research Laboratory, Washington D.C.

    entropyVal=nu/2+log(2)+gammaln(nu/2)+(1-nu/2)*psi(nu/2);
end
end
end

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


function varargout = createRhombododecahedron()
%CREATERHOMBODODECAHEDRON Create a 3D mesh representing a rhombododecahedron.
%
%   [V, E, F] = createRhombododecahedron
%   V is a 14-by-3 array with vertex coordinate,
%   E is a 12-by-2 array containing indices of neighbour vertices,
%   F is a 8-by-3 array containing vertices array of each face.
%
%   [V, F] = createRhombododecahedron;
%   Returns only the vertices and the face vertex indices.
%
%   MESH = createRhombododecahedron;
%   Returns the data as a mesh structure, with fields 'vertices', 'edges'
%   and 'faces'.
%
%   Example
%   [v, e, f] = createRhombododecahedron;
%   drawMesh(v, f);
%
%
%   See also
%   meshes3d, drawMesh

%   ---------
%   author : David Legland
%   e-mail: david.legland@inra.fr
%   INRA - TPV URPOI - BIA IMASTE
%   created the 10/02/2005.
%

%   HISTORY
%   04/01/2007: remove unused variables

nodes = [0 0 2;...
    1 -1 1;1 1 1;-1 1 1;-1 -1 1;...
    2 0 0;0 2 0;-2 0 0;0 -2 0;...
    1 -1 -1;1 1 -1;-1 1 -1;-1 -1 -1;...
    0 0 -2];

edges = [...
    1 2;1 3;1 4;1 5;...
    2 6;2 9;3 6;3 7;4 7;4 8;5 8;5 9;...
    6 10;6 11;7 11;7 12;8 12;8 13;9 10;9 13; ...
    10 14;11 14;12 14;13 14];

faces = [...
    1 2 6 3;...
    1 3 7 4;...
    1 4 8 5;...
    1 5 9 2;...
    2 9 10 6;...
    3 6 11 7;...
    4 7 12 8;...
    5 8 13 9;...
    6 10 14 11;...
    7 11 14 12;...
    8 12 14 13;...
    9 13 14 10];

% format output
varargout = formatMeshOutput(nargout, nodes, edges, faces);


function a = ris ( n )

%*****************************************************************************80
%
%% RIS returns the RIS matrix.
%
%  Discussion:
%
%    This is sometimes called the "dingdong" matrix, invented by F N Ris.
%
%  Formula:
%
%    A(I,J) = 1 / ( 3 + 2 * N - 2 * I - 2 * J )
%
%  Example:
%
%    N = 5
%
%    1/9  1/7  1/5  1/3   1
%    1/7  1/5  1/3   1   -1
%    1/5  1/3   1   -1  -1/3
%    1/3   1   -1  -1/3 -1/5
%     1   -1  -1/3 -1/5 -1/7
%
%  Properties:
%
%    A is a Cauchy matrix.
%
%    A is a Hankel matrix: constant along anti-diagonals.
%
%    A is symmetric: A' = A.
%
%    Because A is symmetric, it is normal.
%
%    Because A is normal, it is diagonalizable.
%
%    The eigenvalues of A cluster around PI/2 and -PI/2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    20 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    John Nash,
%    Compact Numerical Methods for Computers: Linear Algebra and
%    Function Minimisation,
%    John Wiley, 1979, page 210.
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  for i = 1 : n
    for j = 1 : n
      a(i,j) = 1.0 / ( 3 + 2 * n - 2 * i - 2 * j );
    end
  end

  return
end


function [ c_est, r_est, c_err, r_err ] = sphere_random_centralize ( ...
  m, n, c, r )

%*****************************************************************************80
%
%% SPHERE_RANDOM_CENTRALIZE estimates the center of a sphere.
%
%  Discussion:
%
%    We generate N points on the M dimensional sphere of center C and radius R.
%    We seek to estimate the values of C and R.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    19 April 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the spatial dimension.
%
%    Input, integer N, the number of random points to generate.
%
%    Input, real C(M,1), the center.
%
%    Input, real R, the radius.
%
%    Output, real C_EST(M,1), R_EST, the estimated center and radius.
%
%    Output, real C_ERR, R_ERR, the errors in the estimates.
%
  c = c(:);
  x = sphere_surface_sample ( m, n, c, r );

  c_est = sum ( x, 2 ) / n;
  c_err = norm ( c - c_est );

  r_mat = x - repmat ( c_est, 1, n );
  r_mat = r_mat.^2;
  r_mat = sum ( r_mat, 1 );
  r_mat = sqrt ( r_mat );
  r_est = sum ( r_mat ) / n;
  r_err = abs ( r - r_est );

  return
end


% Create Noise Signal and embed sine wave in it at a random location
npts=5000; % # points in signal
srate=1000; % sample rate (Hz)
dur=npts/srate; % signal duration in sec
amp_n=3.5; % noise amplitude
amp_t=1.0; % sine wave amplitude
freq=100; % sine wave frequency
sinepts=400; % # points in sine wave

t=[0:npts-1]/srate; % signal time base
sine_t=[0:sinepts-1]/srate; % sine wave time base
noise=(rand(1,npts)-.5)*amp_n; %noise signal
sinewave=amp_t*(sin(2*pi*freq*sine_t)); % sine wave
% random location of sinewave
sinepos=floor(rand(1,1)*(npts-sinepts))+1;
signal = noise; % make signal equal to noise
endsine = sinepos + sinepts-1; %calc index end of sine wave
% add sinewave to signal starting at index sinepos
signal(sinepos:endsine) = signal(sinepos:endsine) + sinewave;

% Plot signal
subplot(5,1,1)
plot(t,signal);
hold on
%plot red dot on location of sine wave start
plot(sinepos/srate,0,'.r');
hold off
title('Original Signal');

% Step 1: Filter signal
hbandwidth=5; %half bandwidth
nyquist=srate/2;
ntaps=200;
hpf=(freq-hbandwidth)/nyquist;
lpf=(freq+hbandwidth)/nyquist;
[b,a]=fir1(ntaps, [hpf lpf]); %calc filter coefficients
signal_f=filter(b,a,signal); %filter signal
subplot(5,1,2)
plot(t,signal_f); %plot filtered signal
hold on
%plot red dot on location of sine wave
plot(sinepos/srate,0,'.r');
hold off
title('Step 1. Filter Signal');

signal_r=abs(signal_f); %abs value of filtered signal
subplot(5,1,3)
plot(t,signal_r); %plot filtered signal
hold on
%plot red dot on location of sine wave
plot(sinepos/srate,0,'.r');
hold off
title('Step 2. Rectify Signal');

% Step 3: Low-pass filter rectified signal
lpf=10/nyquist; % low-pass filter corner frequency
npoles=6;
[b,a]=butter(npoles, lpf); % Butterworth filter coeff
signal_env=filter(b,a,signal_r); %Filter signal
subplot(5,1,4)
plot(t,signal_env); %plot filtered signal
hold on
%plot red dot on location of sine wave
plot(sinepos/srate,0,'.r');
hold off
title('Step 3. Envelope Signal');

% Step 4: Threshold signal
threshold=amp_t/2;
gated=(signal_env>threshold);
subplot(5,1,5)
plot(t,signal_env); %plot filtered signal
hold on
%plot red dot on location of sine wave
plot(sinepos/srate,0,'.r');
plot(t, gated, 'r'); % plot threshold signal
hold off
title('Step 4. Threshold Signal');
xlabel('Time (s)');

d_gated=diff(gated);
plot(d_gated);

find(d_gated==1)

find(d_gated == -1)

abs(find(d_gated==1) - find(d_gated == -1))


function E = r8mat_expm2 ( A )

%*****************************************************************************80
%
%% R8MAT_EXPM2 uses the Taylor series for the matrix exponential.
%
%  Discussion:
%
%    Formally,
%
%      exp ( A ) = I + A + 1/2 A^2 + 1/3! A^3 + ...
%
%    This function sums the series until a tolerance is satisfied.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 March 2011
%
%  Author:
%
%    Cleve Moler, Charles Van Loan
%
%  Reference:
%
%    Cleve Moler, Charles VanLoan,
%    Nineteen Dubious Ways to Compute the Exponential of a Matrix,
%    Twenty-Five Years Later,
%    SIAM Review,
%    Volume 45, Number 1, March 2003, pages 3-49.
%
%  Parameters:
%
%    Input, real A(N,N), the matrix.
%
%    Output, real E(N,N), the estimate for exp(A).
%
  E = zeros ( size ( A ) );
  F = eye ( size ( A ) );
  k = 1;

  while ( 0 < norm ( E + F - E, 1 ) )
    E = E + F;
    F = A * F / k;
    k = k + 1;
  end

  return
end


function b = r8vec_sht ( n, a  )

%*****************************************************************************80
%
%% R8VEC_SHT computes a "slow" Hartley transform of an R8VEC.
%
%  Discussion:
%
%    The discrete Hartley transform B of a set of data A is
%
%      B(I) = 1/sqrt(N) * Sum ( 0 <= J <= N-1 ) A(J) * CAS(2*PI*I*J/N)
%
%    Here, the data and coefficients are indexed from 0 to N-1.
%
%    With the above normalization factor of 1/sqrt(N), the Hartley
%    transform is its own inverse.
%
%    This routine is provided for illustration and testing.  It is inefficient
%    relative to optimized routines.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    27 February 2010
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Ralph Hartley,
%    A More Symmetrical Fourier Analysis Applied to Transmission Problems,
%    Proceedings of the Institute of Radio Engineers,
%    Volume 30, pages 144-150, 1942.
%
%  Parameters:
%
%    Input, integer ( kind = 4 ) N, the number of data values.
%
%    Input, real A(N), the data to be transformed.
%
%    Output, real B(N), the transformed data.
%
  b(1:n) = 0.0;

  for i = 1 : n
    for j = 1 : n
      theta = 2.0 * pi * mod ( ( i - 1 ) * ( j - 1 ), n ) / n;
      b(i) = b(i) + a(j) * ( cos ( theta ) + sin ( theta ) );
    end
  end

  b(1:n) = b(1:n) / sqrt ( n );

  return
end


function F = ml_Fmeasure(cluster_labels, class_labels)
%ML_FMEASURE Compute the Fmeasure for clustering with external validity
%
%
%   http://www.uni-weimar.de/medien/webis/teaching/lecturenotes/machine-learning/unit-en-cluster-analysis-evaluation.pdf
%   slide number 23-26
%
%   Macro average F-measure
%
%   Fm is an N x M matrix (N number of classes, M number of clusters) where
%   Fm(i,j) is the F-measure of the jth cluster computed with respect to
%   the ith class
%
%
%   input -----------------------------------------------------------------
%
%       - cluster_labels : N x 1 vector of cluster labels given by the clustering algorithm
%       (N is the size of data)
%
%       - class_labels : N x 1 vector of class labels (ground truth)
%
%   output ----------------------------------------------------------------
%
%       - F = macro averaged F-measure

nbOfClusters = length(unique(cluster_labels));
nbOfClasses  = length(unique(class_labels));
sizeClasses  = zeros(nbOfClasses,1);

Fm = zeros(nbOfClasses,nbOfClusters);

unique_cluster_labels = unique(cluster_labels);
unique_class_labels   = unique(class_labels);

% for i = 1:nbOfClasses
%     for j = 1:nbOfClusters
%         N=0;
%         for k = 1:length(cluster_labels)
%             if(cluster_labels(k) == j && class_labels(k) == i)
%                 N = N+1;
%             end
%         end
%         Precision = N/length(find(cluster_labels==j));
%         Recall = N/length(find(class_labels==i));
%         Fm(i,j) = 2*Precision*Recall/(Precision+Recall);
%     end
% end

for i = 1:nbOfClasses
    for j = 1:nbOfClusters
        N=0;
        for k = 1:length(cluster_labels)
            if(cluster_labels(k) == unique_cluster_labels(j) && class_labels(k) == unique_class_labels(i))
                N = N+1;
            end
        end
        Precision = N/length(find(cluster_labels==unique_cluster_labels(j)));
        Recall = N/length(find(class_labels==unique_class_labels(i)));
        Fm(i,j) = 2*Precision*Recall/(Precision+Recall);
    end
end

for m = 1:nbOfClasses
    sizeClasses(m,:) = length(find(class_labels==unique_class_labels(m)));
end

F = sum(max(Fm,[],2).*sizeClasses)/sum(sizeClasses);

end


function [ X ] = uniformCircle(c,R,N)
%  X  = uniformCircle(c,R,N)
% inputs : c = [c1,c2] center of the circle, R radius, N number of points
% output : X of size Nx2, points uniformly distributed on the cricle
theta = 2*pi*rand(N,1);
X = [c(1)+R*cos(theta) c(2)+R*sin(theta)];

end


function c = opoly(x,y,n)
%
%   opolyfit     OPOLYFIT(x,y,n) finds the n coefficients of a polynomial
%		 formed from the data in row vector x that fits the data
%		 in row vector y in a least-squares sense. Orthogonal
%		 polynomials are used to improve accuracy. See also polyfit.
%
%		 c = opolyfit(x,y,n)
%		 c  ---	coefficient vector, size n
%
%		 References:
%		 G. E. Forsythe, "Generation and use of orthogonal poly-
%		 nomials for data fitting on a digital computer",
%		 J. SIAM, 5(1957), 74-88.
%
%		 P. F. Hultquist, "Numerical Methods for Engineers and
%		 Computer Scientists", Benjamin-Cummings, 1988.
%
%		 Copyright 1992. Gordon	J. Frazer, Signal Processing Research
%		 Laboratory, and Roy J. Hughes, Laboratory for Instrumental and
%		 Developmental Chemistry, QUT, Brisbane, AUSTRALIA, 1992.
%		 Email:	g.frazer@qut.edu.au or	r.hughes@qut.edu.au
n=n+1; % To make it similar to MATLAB polyfit.m

if n<1
 error('polynomial order too small, must be greater than or equal to one');
end
if n+1>length(x)
 error('polynomial order too large for number of data points');
end
% normalise y to improve numerical stability
yscale=0.5/max(abs(y));
yy=yscale*y;
% initialise opoloyfit
gamma_0=length(x);
alpha_0=mean(x);
PC=zeros(n);
PC(1,1)=1;
a=zeros(1,n);
a(1)=mean(yy);
% calculate the	first iteration	manually
PC(2,1:2)=conv([1,-alpha_0],PC(1,1));
gamma_k=sum(polyval(PC(2,1:2),x).*polyval(PC(2,1:2),x));
beta_k=gamma_k/gamma_0;
alpha_k=sum(x.*(polyval(PC(2,1:2),x).*polyval(PC(2,1:2),x)))/gamma_k;
a(2)=sum(yy.*polyval(PC(2,1:2),x))/gamma_k;
% calculate for	the remaining polynomial orders
for k=2:n-1
 PC(k+1,1:k+1)=conv([1,-alpha_k],PC(k,1:k))-beta_k*[0,0,PC(k-1,1:k-1)];
 gamma_km1=gamma_k;
 gamma_k=sum(polyval(PC(k+1,1:k+1),x).*polyval(PC(k+1,1:k+1),x));
 beta_k=gamma_k/gamma_km1;
 alpha_k=sum(x.*(polyval(PC(k+1,1:k+1),x).*polyval(PC(k+1,1:k+1),x)))/gamma_k;
 a(k+1)=sum(yy.*polyval(PC(k+1,1:k+1),x))/gamma_k;
end
% combine the a's to simplify the polynomial
for i=1:n
 PC(i,:)=a(i)*PC(i,:);
end
for i=1:n
 cc(i)=sum(diag(PC,i-n));
end
% unnormalise c	by the y scale factor
c=(1/yscale)*cc;


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

% circular convolution

% mod(-m,N)
N=4;
for m=0:3
p(m+1)=mod(-m,N);
end
p

% circular time-reversed sequence
h=[1,1,0.5,2];
for m=0:3
hs(1+m)=h(1+p(m+1));
end
hs'
stem(0:N-1,hs);
axis([-.4 3.4 -.2 2.2])
legend('h_s(m)=h[((-m))_N]')

% circular convolution
clear y;
figure
N=4;
x=[1,0,2.5,1.5];
m=0:N-1;
stem(m,x);
axis([-.4 3.4 -.2 2.9])
legend('x[m]')
n=0;
hsn=circshift(hs',n);
stem(m,hsn);
axis([-.4 3.4 -.2 2.2]);
legend('h[((n-m))_N],n=0')
y(n+1)=sum( x.*hsn')
% or  alternatively
% y(n+1)=x*hsn;

figure
m=0:N-1;
stem(m,x);
axis([-.4 3.4 -.2 2.9])
legend('x[m]')

figure
n=1;
hsn=circshift(hs',n);
stem(m,hsn);
axis([-.4 3.4 -.2 2.2]);
legend(' h[((n-m))_N], n=1')
y(n+1)=sum(x.*hsn')

figure
n=2;
hsn=circshift(hs',n);
stem(m,hsn);
axis([-.4 3.4 -.2 2.2]);
legend(' h[((n-m))_N], n=2')
y(n+1)=sum(x.*hsn')

figure
n=3;
hsn=circshift(hs',n);
stem(m,hsn);
axis([-.4 3.4 -.2 2.2]);
legend('h[((n-m))_N], n=3')
y(n+1)=x*hsn

figure
stem(m,y)
axis([-.4 3.4 -.2 7.2]);
title('circular convolution')
legend(' y[n] ')


function a = c4mat_test ( n )

%*****************************************************************************80
%
%% C4MAT_TEST sets up a test matrix.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    04 April 2014
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, complex A(N,N), the Fourier matrix.
%
  complex_i = complex ( 0.0, 1.0 );

  for i = 1 : n
    for j = 1 : n

      angle = 2.0 * pi * ( i - 1 ) * ( j - 1 ) / n;

      a(i,j) = exp ( complex_i * angle ) / sqrt ( n );

    end
  end

  return
end


function A = probBasedRandomGraph(N,P)
%PROBBASEDRANDOMGRAPH Generates a graph with random connections whose
%                     probability is based on pair-wise probabilities.
%
%INPUTS:
% N: The number of nodes in the graph.
% P: A N-by-N matrix containing probabilities of pair-wise connections. If
%    an undirected graph is desired, this should be an upper triangular
%    matrix. Otherwise, a directed graph is assumed.
%
%OUTPUT:
% A: The N-by-N adjacency matrix for the realized graph. This has 2 on the
%    diagonal for self-loops to count both ends of the edges.
%
%EXAMPLE 1: Generate a random digraph using randomly generated pairwise
%           probabilities.
% rng(42)
% P = rand(10);
% A = probBasedRandomGraph(10,P);
% g = digraph(A);
% plot(g,"MarkerSize",indegree(g))
%
%EXAMPLE 2: Generate a random undirected graph using randomly generated
%           pairwise probabilities.
% rng(42)
% P = triu(rand(10));
% A = probBasedRandomGraph(10,P);
% g = graph(A);
% plot(g,"MarkerSize",degree(g))
%
%August 2022 Codie T. Lewis, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

if any(P>1 | P<0)
    error('Edge probabilities must be in [0,1]')
end

if istriu(P)
    directed = false;
elseif istril(P)
    P = P';
    directed = false;
else
    directed = true;
end

r = rand(N);
A = zeros(N);
if directed
    for i = 1:N
        for j = 1:N
            if r(i,j)<P(i,j)
                if i~=j
                    A(i,j) = 1;
                else
                    A(i,j) = 2;
                end
            end
        end
    end
else %undirected
    for i = 1:N
        for j = i:N
            if r(i,j)<P(i,j)
                A(i,j) = 1;
            end
        end
    end
    A = A+A';
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 varargout = rosenbrock(x)
%ROSENBROCK Rosenbrock's 'banana' function in 2D

if nargin == 0
    varargout{1} = [-2,-1];                 % LB
    varargout{2} = [2,3];                   % UB
    varargout{3} = [0,3000];                % Zlim
    varargout{4} = [-26.5,60];              % view
    varargout{5} = [1,1];                   % xmin
    varargout{6} = 'Rosenbrock function';   % name
    varargout{7} = [-0.5,2.5];              % default x0
    return;
end

if size(x,2) == 1; x = x'; end

varargout{1} = 100*(x(:,2)-x(:,1).^2).^2+(1-x(:,1)).^2;
if nargout > 1
    varargout{2} = [-400*(x(:,2)-x(:,1).^2).*x(:,1)-2*(1-x(:,1)), 200*(x(:,2)-x(:,1).^2)];
end

end


% Implementation of a simple version of the Dijkstra shortest path algorithm
% Returns the distances from a single vertex to all others, doesn't save the path
%
% INPUTS: adjacency matrix, adj (nxn), start node s (index between 1 and n)
% OUTPUTS: shortest path length from the start node to all other nodes, 1xn
%
% Note: Works for a weighted/directed graph.
% GB: last updated, September 28, 2012

function d = simpleDijkstra(adj,s)

n=length(adj);
d = inf*ones(1,n); % distance s-all nodes
d(s) = 0;    % s-s distance
T = 1:n;    % node set with shortest paths not found yet

while not(isempty(T))
    [dmin,ind] = min(d(T));
    for j=1:length(T)
        if adj(T(ind),T(j))>0 && d(T(j))>d(T(ind))+adj(T(ind),T(j))
            d(T(j))=d(T(ind))+adj(T(ind),T(j));
        end
    end
    T = setdiff(T,T(ind));
end


function trans = rotationOz(varargin)
%ROTATIONOZ return 4x4 matrix of a rotation around z-axis
%
%   TRANS = rotationOz(THETA);
%   Returns the transform matrix corresponding to a rotation by the angle
%   THETA (in radians) around the Oz axis. A rotation by an angle of PI/2
%   would transform the vector [1 0 0] into the vector [0 1 0].
%
%   The returned matrix has the form:
%   [cos(THETA) -sin(THETA)  0  0]
%   [sin(THETA)  cos(THETA)  0  0]
%   [    0           0       1  0]
%   [    0           0       0  1]
%
%   TRANS = rotationOz(ORIGIN, THETA);
%   TRANS = rotationOz(X0, Y0, Z0, THETA);
%   Also specifies origin of rotation. The result is similar as performing
%   translation(-X0, -Y0, -Z0), rotation, and translation(X0, Y0, Z0).
%
%
%   See also:
%   transforms3d, transformPoint3d, rotationOx, rotationOy
%
%   ---------
%
%   author : David Legland
%   INRA - TPV URPOI - BIA IMASTE
%   created the 06/04/2004.
%

%   HISTORY
%   2008/11/24 changed convention for angle
%   30/04/2009 deprecate: use createRotationOz instead

% deprecation warning
warning('geom3d:deprecated', ...
    [mfilename ' is deprecated, use ''createRotationOz'' instead']);

% call current implementation
trans = createRotationOz(varargin{:});


function [dist, pos] = distancePointEdge(point, edge)
%DISTANCEPOINTEDGE Minimum distance between a point and an edge.
%
%   DIST = distancePointEdge(POINT, EDGE);
%   Return the euclidean distance between edge EDGE and point POINT.
%   EDGE has the form: [x1 y1 x2 y2], and POINT is [x y].
%
%   If EDGE is N-by-4 array, result is 1-by-4 array computed for each edge.
%   If POINT is a N-by-2 array, the result is a N-by-1 array.
%   If both POINT and EDGE are array, the result is computed for each
%   point-edge couple, and stored into a NP-by-NE array.
%
%   [DIST POS] = distancePointEdge(POINT, EDGE);
%   Also returns the position of closest point on the edge. POS is
%   comprised between 0 (first point) and 1 (last point).
%
%   Eaxmple
%     % Distance between a point and an edge
%     distancePointEdge([3 4], [0 0 10 0])
%     ans =
%         4
%
%     % Distance between several points and one edge
%     points = [10 15; 15 10; 30 10];
%     edge   = [10 10 20 10];
%     distancePointEdge(points, edge)
%     ans =
%         5
%         0
%        10
%
%     % Distance between a point a several edges
%     point = [14 33];
%     edges  = [10 30 20 30; 20 30 20 40;20 40 10 40;10 40 10 30];
%     distancePointEdge(point, edges)
%     ans =
%         3    6    7    4
%
%
%   See also
%   edges2d, points2d, distancePoints, distancePointLine
%

% ------
% Author: David Legland
% E-mail: david.legland@nantes.inra.fr
% Created: 2004-04-07
% Copyright 2004-2022 INRA - BIA-BIBS

% direction vector of each edge (row vectors)
vx = (edge(:, 3) - edge(:,1))';
vy = (edge(:, 4) - edge(:,2))';

% squared length of edges, with a check of validity
delta = vx .* vx + vy .* vy;
invalidEdges = delta < eps;
delta(invalidEdges) = 1;

% difference of coordinates between point and edge first vertex
% (NP-by-NE arrays)
dx  = bsxfun(@minus, point(:, 1), edge(:, 1)');
dy  = bsxfun(@minus, point(:, 2), edge(:, 2)');

% compute position of points projected on the supporting line, by using
% normalised dot product (NP-by-NE array)
pos = bsxfun(@rdivide, bsxfun(@times, dx, vx) + bsxfun(@times, dy, vy), delta);

% ensure degenerated edges are correclty processed (consider the first
% vertex is the closest)
pos(:, invalidEdges) = 0;

% change position to ensure projected point is located on the edge
pos(pos < 0) = 0;
pos(pos > 1) = 1;

% compute distance between point and its projection on the edge
dist = hypot(bsxfun(@times, pos, vx) - dx, bsxfun(@times, pos, vy) - dy);


function b = isPointInTriangle(point, p1, p2, p3)
%ISPOINTINTRIANGLE Test if a point is located inside a triangle
%
%   B = isPointInTriangle(POINT, V1, V2, V3)
%   POINT is a 1-by-2 row vector containing coordinates of the test point,
%   V1, V2 and V3 are 1-by-2 row vectors containing coordinates of triangle
%   vertices. The function returns 1 is the point is inside or on the
%   boundary of the triangle, and 0 otherwise.
%
%   B = isPointInTriangle(POINT, VERTICES)
%   Specifiy the coordinates of vertices as a 3-by-2 array.
%
%   If POINT contains more than one row, the result B has as many rows as
%   the input POINT.
%
%
%   Example
%     % vertices of the triangle
%     p1 = [0 0];
%     p2 = [10 0];
%     p3 = [5 10];
%     tri = [p1;p2;p3];
%     % check if points are inside
%     isPointInTriangle([0 0], tri)
%     ans =
%         1
%     isPointInTriangle([5 5], tri)
%     ans =
%         1
%     isPointInTriangle([10 5], tri)
%     ans =
%         0
%     % check for an array of points
%     isPointInTriangle([0 0;1 0;0 1], tri)
%     ans =
%         1
%         1
%         0
%
%   See also
%   polygons2d, isPointInPolygon, isCounterClockwise
%
%
% ------
% Author: David Legland
% e-mail: david.legland@grignon.inra.fr
% Created: 2011-05-16,    using Matlab 7.9.0.529 (R2009b)
% Copyright 2011 INRA - Cepia Software Platform.

% if triangle vertices are given as a single array, extract vertices
if nargin == 2
    p2 = p1(2, :);
    p3 = p1(3, :);
    p1 = p1(1, :);
end

% check triangle orientation
isDirect = isCounterClockwise(p1, p2, p3);

% check location of point with respect to each side
if isDirect
    b12 = isCounterClockwise(p1, p2, point) >= 0;
    b23 = isCounterClockwise(p2, p3, point) >= 0;
    b31 = isCounterClockwise(p3, p1, point) >= 0;
else
    b12 = isCounterClockwise(p1, p2, point) <= 0;
    b23 = isCounterClockwise(p2, p3, point) <= 0;
    b31 = isCounterClockwise(p3, p1, point) <= 0;
end

% combines the 3 results
b = b12 & b23 & b31;


function Z = projectData(X, U, K)
%PROJECTDATA Computes the reduced data representation when projecting only
%on to the top k eigenvectors
%   Z = projectData(X, U, K) computes the projection of
%   the normalized inputs X into the reduced dimensional space spanned by
%   the first K columns of U. It returns the projected examples in Z.
%

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

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the projection of the data using only the top K
%               eigenvectors in U (first K columns).
%               For the i-th example X(i,:), the projection on to the k-th
%               eigenvector is given as follows:
%                    x = X(i, :)';
%                    projection_k = x' * U(:, k);
%

Ureduce = U(:, 1:K);

for i=1:size(X, 1)
    z = Ureduce' * X(i, :)';
    Z(i, :) = z;
end;

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

end


function x = twos2dec(t)

% TWOS2DEC Convert binary string two's complement to decimal integer.
%
% Usage: X = TWOS2DEC(T)
%
% Converts the two's complement representation as a string given by T to
% decimal integers X. T can be a character array or cell string. Input
% multiple numbers into T along the rows, and the output will be as a
% column vector. Similarly to BIN2DEC, leading spaces in T are sign
% extended (so treated as either 0 or 1 depending on the first non space
% character), and embedded and trailing spaces are removed.
%
% Example:
%     >> twos2dec(['010 111'; ' 010111'; '101011 '; ' 10   1'])
%
%     ans =
%
%         23
%         23
%        -21
%         -3
%
% Inputs:
%   -T: string two's complement numbers to convert to decimal integers.
%
% Outputs:
%   -X: decimal representation of T.
%
% See also: DEC2TWOS, FIX2DEC, DEC2FIX, BIN2DEC, HEX2DEC, BASE2DEC.

error(nargchk(1, 1, nargin));
if iscellstr(t)
    t = char(t);
end

% Convert to numbers.
x = bin2dec(t);

% Get the number of bits as the number of 0's and 1's in each row.
nbits = sum(t == '0' | t == '1', 2);

% Case for negative numbers.
xneg = log2(x) >= nbits - 1;
% xneg = bitshift(x, -(nbits - 1)) == 1;
if any(xneg)
    x(xneg) = -( bitcmp(x(xneg), nbits(xneg)) + 1 );
end


function y = logMvGamma(x, d)
% Compute logarithm multivariate Gamma function
% which is used in the probability density function of the Wishart and inverse Wishart distributions.
% Gamma_d(x) = pi^(d(d-1)/4) \prod_(j=1)^d Gamma(x+(1-j)/2)
% log(Gamma_d(x)) = d(d-1)/4 log(pi) + \sum_(j=1)^d log(Gamma(x+(1-j)/2))
% Input:
%   x: m x n data matrix
%   d: dimension
% Output:
%   y: m x n logarithm multivariate Gamma
% Written by Michael Chen (sth4nth@gmail.com).
y = d*(d-1)/4*log(pi)+sum(gammaln(x(:)+(1-(1:d))/2),2);
y = reshape(y,size(x));


function value = i4vec_norm_l0 ( n, a )

%*****************************************************************************80
%
%% I4VEC_NORM_L0 returns the l0 "norm" of an I4VEC.
%
%  Discussion:
%
%    An I4VEC is a vector of I4's.
%
%    The l0 "norm" simply counts the number of nonzero entries in the vector.
%    It is not a true norm, but has some similarities to one.  It is useful
%    in the study of compressive sensing.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    01 June 2012
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of entries in the vector.
%
%    Input, integer A(N), the vector.
%
%    Output, integer I4VEC_NORM_L0, the value of the norm.
%
  value = sum ( a(1:n) ~= 0 );

  return
end


function [U, S] = pca(X)
%PCA Run principal component analysis on the dataset X
%   [U, S, X] = pca(X) computes eigenvectors of the covariance matrix of X
%   Returns the eigenvectors U, the eigenvalues (on diagonal) in S
%

% Useful values
[m, n] = size(X);

% You need to return the following variables correctly.
U = zeros(n);
S = zeros(n);

% ====================== YOUR CODE HERE ======================
% Instructions: You should first compute the covariance matrix. Then, you
%               should use the "svd" function to compute the eigenvectors
%               and eigenvalues of the covariance matrix.
%
% Note: When computing the covariance matrix, remember to divide by m (the
%       number of examples).
%

Sigma = X'*X/m;

[U,S] = svd(Sigma);

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

end


function p = predict(Theta1, Theta2, X)
%PREDICT Predict the label of an input given a trained neural network
%   p = PREDICT(Theta1, Theta2, X) outputs the predicted label of X given the
%   trained weights of a neural network (Theta1, Theta2)

% Useful values
m = size(X, 1);
num_labels = size(Theta2, 1);

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

% ====================== YOUR CODE HERE ======================
% Instructions: Complete the following code to make predictions using
%               your learned neural network. You should set p to a
%               vector containing labels between 1 to num_labels.
%
% Hint: The max function might come in useful. In particular, the max
%       function can also return the index of the max element, for more
%       information see 'help max'. If your examples are in rows, then, you
%       can use max(A, [], 2) to obtain the max for each row.
%

a1 = [ones(m, 1) X];

z2 = a1 * Theta1';
a2 = sigmoid(z2);

a2 = [ones(m, 1) a2];
z3 = a2 * Theta2';
hypo = sigmoid(z3);
[probability indices] = max(hypo');
p = indices';

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

end


function [J, grad] = lrCostFunction(theta, X, y, lambda)
%LRCOSTFUNCTION Compute cost and gradient for logistic regression with
%regularization
%   J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using
%   theta as the parameter for regularized logistic regression and the
%   gradient of the cost w.r.t. to the parameters.

% Initialize some useful values
m = length(y); % number of training examples

% You need to return the following variables correctly
J = 0;
grad = zeros(size(theta));

% ====================== YOUR CODE HERE ======================
% Instructions: Compute the cost of a particular choice of theta.
%               You should set J to the cost.
%               Compute the partial derivatives and set grad to the partial
%               derivatives of the cost w.r.t. each parameter in theta
%
% Hint: The computation of the cost function and gradients can be
%       efficiently vectorized. For example, consider the computation
%
%           sigmoid(X * theta)
%
%       Each row of the resulting matrix will contain the value of the
%       prediction for that example. You can make use of this to vectorize
%       the cost function and gradient computations.
%
% Hint: When computing the gradient of the regularized cost function,
%       there're many possible vectorized solutions, but one solution
%       looks like:
%           grad = (unregularized gradient for logistic regression)
%           temp = theta;
%           temp(1) = 0;   % because we don't add anything for j = 0
%           grad = grad + YOUR_CODE_HERE (using the temp variable)
%

sigmo = sigmoid(X * theta);

Jreg = lambda / (2 * m) * (theta' * theta - theta(1) .^2);

J = 1 / m * (-y' * log(sigmo) - (1 - y)' * log(1 - sigmo)) + Jreg;

temp = theta;
temp(1) = 0;
gradreg = lambda / m * temp;

grad = 1 / m * X' * (sigmo - y) + gradreg;

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

grad = grad(:);

end


function l = l1pp ( n, h )

%*****************************************************************************80
%
%% L1PP stores the 1D PP Laplacian as a full matrix.
%
%  Discussion:
%
%    The N grid points are assumed to be evenly spaced by H.
%
%    For N = 5, the discrete Laplacian with periodic boundary conditions
%    has the matrix form L:
%
%       2 -1  0  0 -1
%      -1  2 -1  0  0
%       0 -1  2 -1  0
%       0  0 -1  2 -1
%      -1  0  0 -1  2
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    29 October 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer N, the number of points.
%    N must be at least 3.
%
%    Input, real H, the spacing between points.
%
%    Output, real L(N,N), the Laplacian matrix.
%
  if ( n < 3 )
    fprintf ( 1, '\n' );
    fprintf ( 1, 'L1PP - Fatal error!\n' );
    fprintf ( 1, '  N < 3.\n' );
    error ( 'L1PP - Fatal error!' );
  end

  l = zeros ( n, n );

  i = 1;
  l(1,1) =  2.0 / h / h;
  l(1,2) = -1.0 / h / h;
  l(1,n) = -1.0 / h / h;

  for i = 2 : n - 1
    l(i,i-1) = -1.0 / h / h;
    l(i,i) =    2.0 / h / h;
    l(i,i+1) = -1.0 / h / h;
  end

  i = n;
  l(n,1) =   -1.0 / h / h;
  l(n,n-1) = -1.0 / h / h;
  l(n,n) =    2.0 / h / h;

  return
end


function [ thetaVec,sVec ] = getEllipseLengthVector( a,b, theta0,theta1 )
%% About:
% This function is used to return the length of the ellipse as a function
% of the angle theta.

%% Inputs:
% theta0, theta1: start/end angle of the arc of the ellipse (from the parametric equation of the ellipse)
% a,b: the big and the small radious of the ellipse.

% Mohammad SAFEEA 10-Nov-2017

thetaSpan = [theta0 theta1];
s0 = 0;
opts = odeset('RelTol',1e-2,'AbsTol',1e-4);
[thetaVec,sVec] = ode45(@(theta,s) ((a*a*sin(theta)*sin(theta)+b*b*cos(theta)*cos(theta))^0.5), thetaSpan, s0,opts);

end


function pde = sincosdata3
%% SINCOSDATA3 trigonometric data for Poisson equation in 3-D
%
%     u = cos(pi*x)*cos(pi*y)*cos(pi*z);
%     f = - Delta u = 3*pi^2*cos(pi*x)*cos(pi*y)*cos(pi*z);
%     Du = (-pi*sin(pi*x)*cos(pi*y)*cos(pi*z),
%           -pi*cos(pi*x)*sin(pi*y)*cos(pi*z),
%           -pi*cos(pi*x)*cos(pi*y)*sin(pi*z));
%
% Copyright (C) Long Chen. See COPYRIGHT.txt for details.

pde = struct('f',@f,'exactu',@exactu,'g_D',@g_D,'Du',@Du,'g_N',@g_N, 'phi', @phi);

    % load data (right hand side function)
    function s = f(p)
    x = p(:,1); y = p(:,2); z = p(:,3);
    s = 3*pi^2*cos(pi*x).*cos(pi*y).*cos(pi*z);
    end
    % exact solution
    function s = exactu(p)
    x = p(:,1); y = p(:,2); z = p(:,3);
    s = cos(pi*x).*cos(pi*y).*cos(pi*z); % for neumann boundary condition, int_u =0
    end
    % Dirichlet boundary condition
    function s = g_D(p)
    s = exactu(p);
    end
    % Neumann boundary condtion
    function f = g_N(p)
    f = zeros(size(p,1),1);
    x = p(:,1); y = p(:,2); z = p(:,3);
    uprime = [-pi*sin(pi*x).*cos(pi*y).*cos(pi*z) ...
              -pi*cos(pi*x).*sin(pi*y).*cos(pi*z) ...
              -pi*cos(pi*x).*cos(pi*y).*sin(pi*z)];
    downbd = (abs(z)<eps); % n = (0,0,-1)
    f(downbd) = -uprime(downbd,3);
    upbd = (abs(z-1)<eps);% n = (0,0,1)
    f(upbd) = uprime(upbd,3);
    leftbd = (abs(x)<eps); % n = (-1,0,0)
    f(leftbd) = -uprime(leftbd,1);
    rightbd = (abs(x-1)<eps); % n = (1,0,0)
    f(rightbd) = uprime(rightbd,1);
    backbd = (abs(y-1)<eps); % n =(0,1,0)
    f(backbd) = uprime(backbd,2);
    frontbd = (abs(y)<eps); % n = (0,-1,0)
    f(frontbd) = -uprime(frontbd,2);
    end
    % Derivative of the exact solution
    function s = Du(p)
    x = p(:,1); y = p(:,2); z = p(:,3);
    s(:,1) = -pi*sin(pi*x).*cos(pi*y).*cos(pi*z);
    s(:,2) = -pi*cos(pi*x).*sin(pi*y).*cos(pi*z);
    s(:,3) = -pi*cos(pi*x).*cos(pi*y).*sin(pi*z);
    end
    function s = phi(p) % level set function
        x = p(:,1); y = p(:,2); z =p(:,3);
        s = x.^2 + y.^2 +z.^2 - 0.75^2;
    end
end


function varargout = easom(X)
% Easom function
%
%   EASOM([x1, x2]) returns the value of the Easom function at the
%   specified points. [x1] and [x2] may be vectors. The search
%   domain is
%
%               -100 < x_i < 100
%
%   The global minimum is
%
%               f(x1, x2) = f(pi, pi) = -1.

% Author: Rody P.S. Oldenhuis
% Delft University of Technology
% E-mail: oldenhuis@dds.nl
% Last edited 20/Jul/2009

    % if no input is given, return dimensions, bounds and minimum
    if (nargin == 0)
        varargout{1} = 2;  % # dims
        varargout{2} = [-100, -100]; % LB
        varargout{3} = [+100, +100]; % UB
        varargout{4} = [pi,pi]; % solution
        varargout{5} = -1; % function value at solution (too complicated)

    % otherwise, output function value
    else

        % keep values in the serach interval
        X(X < -100) = inf;     X(X > 100) = inf;

        % split input vector X into x1, x2
        if size(X, 1) == 2
            x1 = X(1, :);        x2 = X(2, :);
        else
            x1 = X(:, 1);        x2 = X(:, 2);
        end

        % output function value
        varargout{1} = -cos(x1).*cos(x2).*exp(-((x1-pi).^2 + (x2-pi).^2));

    end

end


function varargout = styblinskitang(X)
% Styblinski-Tang function
%
%   STYBLINSKYTANG([x1, x2, ..., xn]) returns the value of the
%   Styblinski-Tang at the specified points. All [xi] may be vectors.
%   The search domain is
%
%               -5 < x_i < 5
%
%   The global minimum is
%
%               f(x1, x2, ..., xn) =
%               f(-2.903534, -2.903534, ..., -2.903534) = -39.16599 * n

% Author: Rody P.S. Oldenhuis
% Delft University of Technology
% E-mail: oldenhuis@dds.nl
% Last edited 20/Jul/2009

    % if no input is given, return dimensions, bounds and minimum
    if (nargin == 0)
        varargout{1} = inf;  % # dims
        varargout{2} = -5; % LB
        varargout{3} = +5; % LB
        varargout{4} = -2.903534018185960e+000; % solution
        varargout{5} = -3.916616570377142e+001; % *(#dims) .. function value at solution

    % otherwise, output function value
    else

        % keep all values in the search domain
        X(X < -5) = inf;  X(X > 5) = inf;

        % NOTE: orientation can not be determined automatically
        % defaults to columnsums...
        varargout{1} = sum(X.^4 - 16*X.^2 + 5*X, 1)/2;

    end

end


function f = flops_inv(n)
% FLOPS_INV    Flops for matrix inversion.
% FLOPS_INV(n) returns the number of flops for inv(rand(n,n)).
% For n=1,2 the number of flops is exact.
% For n>2, the number of flops is estimated by assuming the matrix is
% decomposed via LU or Cholesky and then inverted by back-substitution.
% See flops_solve.

% Written by Tom Minka

if n == 2
  % inv([a b; c d]) = [d -b; -c a]/(ad-bc)
  % 3 flops for determinant, 1 divide, 4 multiplies, 1 negation
  % thanks to Zhang Xiaoying for pointing out this special case.
  f = 3+flops_div + 5;
else
  f = flops_solve(n,n,n);
end


function y = gvar(x,n)
%GVAR Variance of a grouped sample.
%  In some scientific works, once the data have been gathered from a
%  population of interest, it is often difficult to get a sense of what
%  the data indicate when they are presented in an unorganized fashion.
%  Assembling the raw data into a meaningful form, such as a frequency
%  distribution, makes the data easier to understand and interpret. It is
%  in the context of frequency distributions that the importance of
%  conveying in a succinct way numerical information contained in the data
%  is encountered.
%  So, grouped data is data that has been organized into groups known as
%  classes.  The raw dataset can be organized by constructing a table
%  showing the frequency distribution of the variable (whose values are
%  given in the raw dataset). Such a frequency table is often referred to
%  as grouped data.
%  Here, we developed a m-code to calculate the variance of a grouped data.
%  One can input the returns or modified vectors n and xout containing the
%  frequency counts and the bin locations of the hist m-function, in a
%  column form matrix.
%  Normalizes Y by (N-1), where N is the sample size.  This is an unbiased
%  estimator of the variance of the population from which X is drawn.
%  Y = VAR(X,1) normalizes by N and produces the second moment of the
%  sample about its mean. VAR(X,0) is the same as VAR(X).
%
%  Variance calculation uses the formula,
%
%
%              V =  Sum(F*(MC - M)^2)/D
%
%  where:
%  F  = class frequency
%  MC = mark class
%  M = grouped mean
%  D = N - 1 or N, whether normalizes by n-1 or by n
%  N = sample size [=sum(F)]
%
%  Syntax: function y = gvar(x)
%
%  Inputs:
%       x - data matrix (Size of matrix must be n-by-2; absolut frequency=
%           column 1, class mark=column 2)
%       n - [normalized by n-1] = 0 (default), [normalized by n] = 1
%  Outputs:
%       y  - variance of the values in x
%
%  Example: Suppose we have the next frequency table:
%
%                     ----------------
%                       MC         F
%                     ----------------
%                        5         6
%                       15        16
%                       25        24
%                       35        25
%                       45        17
%                     ----------------
%
%  Taken from:
%  http://mlsc.lboro.ac.uk/resources/statistics/var_stand_deviat_group.pdf
%
%  Where we are interested to get the variance value normalized by n.
%
%  Data input:
%  x=[5 6;15 16;25 24;35 25;45 17];
%
%  Calling on Matlab the function:
%          y = gvar(x,1)
%
%  Answer is:
%
%  y = 138.7268
%
%  Created by A. Trujillo-Ortiz and R. Hernandez-Walls
%             Facultad de Ciencias Marinas
%             Universidad Autonoma de Baja California
%             Apdo. Postal 453
%             Ensenada, Baja California
%             Mexico.
%             atrujo@uabc.edu.mx
%
%  Copyright (C)  September 18, 2012.
%
%  To cite this file, this would be an appropriate format:
%  Trujillo-Ortiz, A. and R. Hernandez-Walls. (2012).
%     gvar:Varience of a grouped sample. [WWW document].
%     URL http://www.mathworks.com/matlabcentral/fileexchange/
%     38281-gvar
%
%  Reference:
%  Jayaraman, K. (1999), A Statistical Manual for Foresty Research. Foresty
%             Research Support Programme for Asia and the Pacific. FAO-
%             Corporate Document Repository. Forestry Statistics and Data
%             Collection.
%             URL http://www.fao.org/DOCREP/003/X6831E/X6831E00.HTM
%             PDF ftp://ftp.fao.org/docrep/fao/003/X6831E/X6831E00.pdf
%

if  nargin < 2,
    n = 0; %default
end

c = size(x,2);

if c ~= 2
    error('stats:gvar:BadData','X must have two colums.');
end

mc = x(:,1); %class mark
f = x(:,2); %absolut frequency
s = sum(f.*mc);
m = s/sum(f);
ss = sum(f.*(mc - m).^2);

if n == 0; %default
    d = sum(f) - 1;
else n = 1;
    d = sum(f);
end

y = ss/d;

return,


function [X_norm, mu, sigma] = featureNormalize(X)
%FEATURENORMALIZE Normalizes the features in X
%   FEATURENORMALIZE(X) returns a normalized version of X where
%   the mean value of each feature is 0 and the standard deviation
%   is 1. This is often a good preprocessing step to do when
%   working with learning algorithms.

mu = mean(X);
X_norm = bsxfun(@minus, X, mu);

sigma = std(X_norm);
X_norm = bsxfun(@rdivide, X_norm, sigma);

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

end


function volume = sphere_imp_zone_volume_3d ( r, h1, h2 )

%*****************************************************************************80
%
%% SPHERE_IMP_ZONE_VOLUME_3D computes the volume of a spherical zone in 3D.
%
%  Discussion:
%
%    An implicit sphere in 3D satisfies the equation:
%
%      sum ( ( P(1:DIM_NUM) - CENTER(1:DIM_NUM) )**2 ) = R**2
%
%    Draw any radius of the sphere and note the point P where the radius
%    intersects the sphere.  Now choose two points on the radius line, a
%    distance H1 and H2 from the point P.  Consider all the points on or within
%    the sphere whose projection onto the radius lies between these two points.
%    These points constitute the spherical zone, which can also be considered
%    the difference of two spherical caps.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    07 February 2005
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, real R, the radius of the sphere.
%
%    Input, real H1, H2, the distances that define the
%    thickness of the zone.  H1 and H2 must be between 0 and 2 * R.
%
%    Output, real VOLUME, the volume of the spherical zone
%
  h11 = min ( h1, h2 );
  h11 = max ( h11, 0.0 );

  if ( 2.0 * r <= h11 )
    volume = 0.0;
    return
  end

  h22 = max ( h1, h2 );
  h22 = min ( h22, 2.0 * r );

  if ( h22 <= 0.0 )
    volume = 0.0;
    return
  end

  volume = ( 1.0 / 3.0 ) * pi * ( ...
      h22 * h22 * ( 3.0 * r - h22 ) ...
    - h11 * h11 * ( 3.0 * r - h11 ) );

  return
end


function [airfoildata] = PerformRegression(data)
% Relate the coefficients of the drag polar to Re as parabolic functions.
% Drag polar is Cd = a0 + a1*alpha + a2*alpha^2
% The contents of airfoildata are the coefficients resulting from the
% polynomial regression with respect to Reynolds number:
%'NACA 4 or 5 digit' | 3 coefficients for a0 |
% 3 coefficients for a1 | 3 coefficients for a2 |
% 3 coefficients for alpha_stall
% so that:
% a0 = b1 + b2*log10(Re) + b3*log10(Re)^2
% a1 = c1 + c2*log10(Re) + c3*log10(Re)^2
% a2 = d1 + d2*log10(Re) + d3*log10(Re)^2
% and:
% alphastall = k1 + k2*log10(Re) + k3*log10(Re)^2

for i = 1:length(data)
    if length(data(i).Re) >= 2
        airfoildata{1}{i} = data(i).airfoil;
        airfoildata{2}{i} = [ones(size(data(i).Re)) log10(data(i).Re) log10(data(i).Re).^2]\[data(i).a0];
        airfoildata{3}{i} = [ones(size(data(i).Re)) log10(data(i).Re) log10(data(i).Re).^2]\[data(i).a1];
        airfoildata{4}{i} = [ones(size(data(i).Re)) log10(data(i).Re) log10(data(i).Re).^2]\[data(i).a2];
        airfoildata{5}{i} = [ones(size(data(i).Re)) log10(data(i).Re) log10(data(i).Re).^2]\[data(i).alphastall];
    end
end


function [ w, xy ] = triangle_unit_o07 ( )

%*****************************************************************************80
%
%% TRIANGLE_UNIT_O07 returns a 7 point quadrature rule for the unit triangle.
%
%  Discussion:
%
%    This rule is precise for monomials through degree 5.
%
%    The integration region is:
%
%      0 <= X
%      0 <= Y
%      X + Y <= 1.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    16 April 2009
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Carlos Felippa,
%    A compendium of FEM integration formulas for symbolic work,
%    Engineering Computation,
%    Volume 21, Number 8, 2004, pages 867-890.
%
%  Parameters:
%
%    Output, real W(7), the weights.
%
%    Output, real XY(2,7), the abscissas.
%
  w(1:7,1) = [ ...
    0.12593918054482715260, ...
    0.12593918054482715260, ...
    0.12593918054482715260, ...
    0.13239415278850618074, ...
    0.13239415278850618074, ...
    0.13239415278850618074, ...
    0.22500000000000000000 ];

  xy(1:2,1:7) = [ ...
    0.79742698535308732240,  0.10128650732345633880; ...
    0.10128650732345633880,  0.79742698535308732240; ...
    0.10128650732345633880,  0.10128650732345633880; ...
    0.059715871789769820459,  0.47014206410511508977; ...
    0.47014206410511508977,  0.059715871789769820459; ...
    0.47014206410511508977,  0.47014206410511508977; ...
    0.33333333333333333333,  0.33333333333333333333 ]';

  return
end


function a = pascal2 ( n )

%*****************************************************************************80
%
%% PASCAL2 returns the PASCAL2 matrix.
%
%  Formula:
%
%    If ( I = 1 or J = 1 )
%      A(I,J) = 1
%    else
%      A(I,J) = A(I-1,J) + A(I,J-1)
%
%  Example:
%
%    N = 5
%
%    1 1  1  1  1
%    1 2  3  4  5
%    1 3  6 10 15
%    1 4 10 20 35
%    1 5 15 35 70
%
%  Properties:
%
%    A is a "chunk" of the Pascal binomial combinatorial triangle.
%
%    A is positive definite.
%
%    A is symmetric: A' = A.
%
%    Because A is symmetric, it is normal.
%
%    Because A is normal, it is diagonalizable.
%
%    A is integral, therefore det ( A ) is integral, and
%    det ( A ) * inverse ( A ) is integral.
%
%    A is nonsingular.
%
%    det ( A ) = 1.
%
%    A is unimodular.
%
%    Eigenvalues of A occur in reciprocal pairs.
%
%    The condition number of A is approximately 16^N / ( N*PI ).
%
%    The elements of the inverse of A are integers.
%
%    A(I,J) = (I+J-2)! / ( (I-1)! * (J-1)! )
%
%    The Cholesky factor of A is a lower triangular matrix R,
%    such that A = R * R'.  The matrix R is a Pascal
%    matrix of the type generated by subroutine PASCAL.  In other
%    words, PASCAL2 = PASCAL * PASCAL'.
%
%    If the (N,N) entry of A is decreased by 1, the matrix is singular.
%
%    Gregory and Karney consider a generalization of this matrix as
%    their test matrix 3.7, in which every element is multiplied by a
%    nonzero constant K.  They point out that if K is the reciprocal of
%    an integer, then the inverse matrix has all integer entries.
%
%    The family of matrices is nested as a function of N.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    18 October 2007
%
%  Author:
%
%    John Burkardt
%
%  Reference:
%
%    Robert Brawer, Magnus Pirovino,
%    The linear algebra of the Pascal matrix,
%    Linear Algebra and Applications,
%    Volume 174, 1992, pages 13-23.
%
%    Robert Gregory, David Karney,
%    Example 3.7,
%    A Collection of Matrices for Testing Computational Algorithms,
%    Wiley, 1969, page 32,
%    LC: QA263.G68.
%
%    Nicholas Higham,
%    Accuracy and Stability of Numerical Algorithms,
%    Society for Industrial and Applied Mathematics,
%    Philadelphia, PA, USA, 1996; section 26.4.
%
%    Sam Karlin,
%    Total Positivity, Volume 1,
%    Stanford University Press, 1968.
%
%    Morris Newman, John Todd,
%    The evaluation of matrix inversion programs,
%    Journal of the Society for Industrial and Applied Mathematics,
%    Volume 6, Number 4, pages 466-476, 1958.
%
%    Heinz Rutishauser,
%    On test matrices,
%    Programmation en Mathematiques Numeriques,
%    Centre National de la Recherche Scientifique,
%    1966, pages 349-365.
%
%    John Todd,
%    Basic Numerical Mathematics, Vol. 2: Numerical Algebra,
%    Academic Press, 1977, page 172.
%
%    HW Turnbull,
%    The Theory of Determinants, Matrices, and Invariants,
%    Blackie, 1929.
%
%  Parameters:
%
%    Input, integer N, the order of A.
%
%    Output, real A(N,N), the matrix.
%
  a = zeros ( n, n );

  for i = 1 : n
    for j = 1 : n

      if ( i == 1 )
        a(i,j) = 1.0;
      elseif ( j == 1 )
        a(i,j) = 1.0;
      else
        a(i,j) = a(i,j-1) + a(i-1,j);
      end

    end
  end

  return
end


function [phi,dphi]=pt2TetrahedronCoords3D(x,v)
%%PT2TETRAHEDRONCOORDS3D Convert a 3D point to barycentric coordinates in
%      a tetrahedron using the relative areas of subtetrahedra, as
%      discussed at the beginning of [1]. A signed tetrahedral volume area
%      is used so that points outside of the tetrahedron can also be
%      represented (albeit with some negative weights).
%
%INPUTS: x The 3XnumPts set of points to convert into tetrahedral
%          coordinates.
%        v The 3X4 set of vertices of the tetrahedron.
%
%OUTPUTS: phi A 4XnumPts set of the coordinates in the triangle.
%        dphi A 4X3XnumPts set of derivatives of the elements of phi
%             (rows) taken with respect to the elements of x (columns) for
%             each input measurement (3rd dimension).
%
%In [1], the coordinates are defined as the ratio of the volume of a number
%of sub-tetrahedra (with x as a vertex) and the tetrahedron given in v.
%Here, things differ a little bit in that signed tetrahedral volumes are
%used with a very specific ordering. This allows this function to work
%with points inside the tetrahedron (with all positive weights) as well as
%with points outside the tetrahdron (with some negative weights).
%
%EXAMPLE 1:
%In this example, the coordinates of three points are found and the points
%are recreated from the phi values. The residual error of the reverse
%conversion is seen to be on the order of finite precision errors.
% x=sqrt(3)/3;
% h=sqrt(6)/3;
% d=sqrt(3)/6;
% v=[x,  -d,  -d, 0;
%    0, 1/2,-1/2, 0;
%    0,   0,   0, h];
% xPts=[[0;0;0.5],[x;0;0],[1;1;1]];
% phi=pt2TetrahedronCoords3D(xPts,v);
% xBack=barycentricCoords2Pt(phi,v);
% ResidualErr=max(max(abs(xBack-xPts)))
%
%EXAMPLE 2:
%In this example, we verify that the derivative is consistent with
%numerical differentiation. The absolute error is consistent with what one
%might expect due to finite precision limitations.
% v=randn(3,4);
% x=randn(3,1);
% [~,dphi]=pt2TetrahedronCoords3D(x,v);
% f=@(y)pt2TetrahedronCoords3D(y,v);
% dPhiNumDiff=numDiff(x,f,4);
% RelErr=max(max(abs((dphi-dPhiNumDiff)./dPhiNumDiff)))
%
%REFERENCES:
%[1] M. S. Floater, "Generalized barycentric coordinates and applications,"
%    Acta Numerica, vol. 24, pp. 161-214, 1 May 2015.
%
%December 2021 David F. Crouse, Naval Research Laboratory, Washington D.C.
%(UNCLASSIFIED) DISTRIBUTION STATEMENT A. Approved for public release.

a=v(:,1);
b=v(:,2);
c=v(:,3);
d=v(:,4);

numX=size(x,2);
phi=zeros(4,numX);
dphi=zeros(4,3,numX);
for curX=1:numX
    [Va,dVa]=tetrahedronVolume([b,x(:,curX),d,c],false,2);
    [Vb,dVb]=tetrahedronVolume([a,x(:,curX),c,d],false,2);
    [Vc,dVc]=tetrahedronVolume([a,x(:,curX),d,b],false,2);
    [Vd,dVd]=tetrahedronVolume([a,x(:,curX),b,c],false,2);

    %Nominally, V=tetrahedronVolume(v,false); should equal Va+Vb+Vc+Vd.
    %However, to ensure that phi is normalized to more significant digits,
    %we compute V directly from the sum rather than computing it once
    %outside this loop and reusing it.
    V=Va+Vb+Vc+Vd;

    phi(:,curX)=[Va;Vb;Vc;Vd]/V;

    dphi(:,:,curX)=[dVa;
                    dVb;
                    dVc;
                    dVd]/V;
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.