function [ w, e, er, qm ] = chkqfs ( t, wts, mlt, nt, nwts, ndx, key, mop, ...
  mex, kind, alpha, beta, lo, w )

%*****************************************************************************80
%
%% chkqfs() checks the polynomial accuracy of a quadrature formula.
%
%  Discussion:
%
%    This routine will optionally print weights, and results of a moments test.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    05 January 2010
%
%  Author:
%
%    Original FORTRAN77 version by Sylvan Elhay, Jaroslav Kautsky.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    Sylvan Elhay, Jaroslav Kautsky,
%    Algorithm 655: IQPACK, FORTRAN Subroutines for the Weights of
%    Interpolatory Quadrature,
%    ACM Transactions on Mathematical Software,
%    Volume 13, Number 4, December 1987, pages 399-415.
%
%  Input:
%
%    real T(NT), the knots.
%
%    real WTS(NWTS), the weights.
%
%    integer MLT(NT), the multiplicity of the knots.
%
%    integer NT, the number of knots.
%
%    integer NWTS, the number of weights.
%
%    integer NDX(NT), used to index the array WTS.
%    If KEY = 1, then NDX need not be preset.  For more details see the
%    comments in CAWIQ.
%
%    integer KEY, indicates the structure of the WTS
%    array.  It will normally be set to 1.  This will cause the weights to be
%    packed sequentially in array WTS.  For more details see the comments
%    in CAWIQ.
%
%    integer MOP, the expected order of precision of the
%    quadrature formula.
%
%    integer MEX, the number of moments to be tested.
%    MEX must be at least 1.  Set MEX = 1 and LO < 0 for no moment check.
%
%    integer KIND, the rule.
%    0, unknown weight function (the user must set the first MEX moments in
%       array W in this case.)
%    1, Legendre,             (a,b)       1.0
%    2, Chebyshev Type 1,     (a,b)       ((b-x)*(x-a))^(-0.5)
%    3, Gegenbauer,           (a,b)       ((b-x)*(x-a))^alpha
%    4, Jacobi,               (a,b)       (b-x)^alpha*(x-a)^beta
%    5, Generalized Laguerre, (a,+oo)     (x-a)^alpha*exp(-b*(x-a))
%    6, Generalized Hermite,  (-oo,+oo)   |x-a|^alpha*exp(-b*(x-a)^2)
%    7, Exponential,          (a,b)       |x-(a+b)/2.0|^alpha
%    8, Rational,             (a,+oo)     (x-a)^alpha*(x+b)^beta
%    9, Chebyshev Type 2,     (a,b)       ((b-x)*(x-a))^(+0.5)
%
%    real ALPHA, the value of Alpha, if needed.
%
%    real BETA, the value of Beta, if needed.
%
%    integer LO, selects the action to carry out.
%     > 0, print weights and moment tests.
%     = 0, print nothing. compute moment test.
%     < 0, print weights only. don't compute moment tests.
%
%    real W(MEX), the moments array.  This is input
%    only if KIND = 0.
%
%  Output:
%
%    real W(MEX), the moments array.
%
%    real E(MEX), ER(MEX), the absolute and relative
%    errors of the quadrature formula applied to (x-del)^n.
%
%    real QM(MEX), the values of the quadrature formula
%    applied to (X-DEL)^N.
%

%
%  KIND may be set to -1 to allow printing of moments only.
%
%  This feature is only used internally, by CHKQF.
%
  kindp = max ( 0, kind );

  if ( lo ~= 0 && kind ~= -1 )

    if ( kindp ~= 0 )

      fprintf ( 1, '\n' );
      fprintf ( 1, '  Interpolatory quadrature formula\n' );
      fprintf ( 1, '\n' );
      fprintf ( 1, ...
        '  Type  Interval       Weight function               Name\n' );
      fprintf ( 1, '\n' );
      if ( kindp == 1 )
        fprintf ( 1, ...
          '    1    (-1,+1)            1.0                    Legendre\n' );
      elseif ( kindp == 2 )
        fprintf ( 1, ...
          '    2    (-1,+1)    ((b-x)*(x-a))^(-0.5)          Chebyshev Type 1\n' );
      elseif ( kindp == 3 )
        fprintf ( 1, ...
          '    3    (-1,+1)    ((b-x)*(x-a))^alpha           Gegenbauer\n' );
      elseif ( kindp == 4 )
        fprintf ( 1, ...
          '    4    (-1,+1)  (b-x)^alpha*(x-a)^beta          Jacobi\n' );
      elseif ( kindp == 5 )
        fprintf ( 1, ...
          '    5   (0,oo)   (x-a)^alpha*exp(-b*(x-a))      Gen Laguerre\n' );
      elseif ( kindp == 6 )
        fprintf ( 1, ...
          '    6  (-oo,oo) |x-a|^alpha*exp(-b*(x-a)^2)  Gen Hermite\n' );
      elseif ( kindp == 7 )
        fprintf ( 1, ...
          '    7    (-1,+1)    |x-(a+b)/2.0|^alpha        Exponential\n' );
      elseif ( kindp == 8 )
        fprintf ( 1, ...
          '    8   (0,oo)    (x-a)^alpha*(x+b)^beta         Rational\n' );
      elseif ( kindp == 9 )
        fprintf ( 1, ...
          '    9    (-1,+1)    ((b-x)*(x-a))^(+0.5)          Chebyshev Type 2\n' );
      end

      if ( 3 <= kindp && kindp <= 8 )
        fprintf ( 1, '                  alpha      %f\n', alpha );
      end

      if ( kindp == 4 || kindp == 8 )
        fprintf ( 1, '                  beta       %f\n', beta );
      end

    end

    if ( kind ~= -1 )
      prec = eps;
      fprintf ( 1, '\n' );
      fprintf ( 1, '  Machine precision = %e\n', prec );
    end

    fprintf ( 1, '\n' );
    fprintf ( 1, ...
      '           Knots               Mult                Weights\n' );
    fprintf ( 1, '\n' );

    for i = 1 : nt
      k = abs ( ndx(i) );
      if ( k ~= 0 )
        fprintf ( 1, '%4d%26.17g%4d%26.17g\n', i, t(i), mlt(i), wts(k) );
        for j = k + 1 : k + mlt(i) - 1
          fprintf ( 1, '                                  %26.17g\n', wts(j) );
        end
      end
    end

  end

  if ( lo < 0 )
    w = [];
    e = [];
    er = [];
    qm = [];
    return
  end

  if ( kindp ~= 0 )

    w = wm ( mex, kindp, alpha, beta );

  end

  qm(1:mex) = 0.0;
  erest = 0.0;

  for k = 1 : nt

    tmp = 1.0;
    l = abs ( ndx(k) );
    if ( l == 0 )
      continue
    end

    erest = erest + abs ( wts(l) );
    for j = 1 : mex
      qm(j) = qm(j) + tmp * wts(l);
      tmpx = tmp;
      px = 1.0;
      for jl = 2 : min ( mlt(k), mex - j + 1 )
        kjl = j + jl - 1;
        tmpx = tmpx * ( kjl - 1 );
        qm(kjl) = qm(kjl) + tmpx * wts(l+jl-1) / px;
        if ( key <= 0 )
          px = px * jl;
        end
      end
      tmp = tmp * t(k);
    end

  end

  e = zeros ( mex );
  for k = 1 : mex
    e(k) = w(k) - qm(k);
  end

  er = zeros ( mex );
  for k = 1 : mex
    er(k) = e(k) / ( abs ( w(k) ) + 1.0 );
  end
%
%  For some strange weight functions W(1) may vanish.
%
  erest = erest / ( abs ( w(1) ) + 1.0 );
%
%  Exit if user does not want printed output.
%
  if ( lo == 0 )
    return
  end

  m = mop + 1;
  mx = min ( mop, mex );

  emx = max ( abs ( e(1:mx) ) );
  emn = min ( abs ( e(1:mx) ) );
  erx = max ( abs ( er(1:mx) ) );
  ern = min ( abs ( er(1:mx) ) );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Comparison of moments\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Order of precision %d\n', mop );
  fprintf ( 1, '  Errors :    Absolute    Relative\n' );
  fprintf ( 1, '  ---------+-------------------------\n' );
  fprintf ( 1, '  Minimum :%12.3g%12.3g\n', emn, ern );
  fprintf ( 1, '  Maximum :%12.3g%12.3g\n', emx, erx );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Weights ratio       %13.3g\n', erest );

  if ( m <= mex )

    ek = e(m);
    for j = 1 : mop
      ek = ek / j;
    end

    fprintf ( 1, '  Error in %2dth power %13.3g\n', mop, e(m) );
    fprintf ( 1, '  Error constant      %13.3g\n', ek );

  end

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Moments:\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, ...
    '            True             from QF            Error      Relative\n' );
  fprintf ( 1, '\n' );
  for j = 1 : mx
    fprintf ( 1, '%4d%19.10g%19.10g%12.3g%12.3g\n', ...
      j, w(j), qm(j), e(j), er(j) );
  end
  fprintf ( 1, '\n' );
  for j = m : mex
    fprintf ( 1, '%4d%19.10g%19.10g%12.3g%12.3g\n', ...
      j, w(j), qm(j), e(j), er(j) );
  end

  return
end
