function [ c, ic1,ic2, nc, an1, an2, ncp, d, itran, indx ] = qtran ( a, m, ...
  n, c, k, ic1, ic2, nc, an1, an2, ncp, d, itran, indx )

%*****************************************************************************80
%
%% QTRAN carries out the quick transfer stage.
%
%  Discussion:
%
%    This is the quick transfer stage.
%
%    IC1(I) is the cluster which point I belongs to.
%    IC2(I) is the cluster which point I is most likely to be
%    transferred to.
%
%    For each point I, IC1(I) and IC2(I) are switched, if necessary, to
%    reduce within-cluster sum of squares.  The cluster centers are
%    updated after each step.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 February 2008
%
%  Author:
%
%    Original FORTRAN77 version by John Hartigan, Manchek Wong.
%    MATLAB version by John Burkardt.
%
%  Reference:
%
%    John Hartigan, Manchek Wong,
%    Algorithm AS 136:
%    A K-Means Clustering Algorithm,
%    Applied Statistics,
%    Volume 28, Number 1, 1979, pages 100-108.
%
%  Parameters:
%
%    Input, real A(M,N), the points.
%
%    Input, integer M, the number of points.
%
%    Input, integer N, the number of spatial dimensions.
%
%    Input/output, real C(K,N), the cluster centers.
%
%    Input, integer K, the number of clusters.
%
%    Input/output, integer IC1(M), the cluster to which each
%    point is assigned.
%
%    Input/output, integer IC2(M), used to store the cluster
%    which each point is most likely to be transferred to at each step.
%
%    Input/output, integer NC(K), the number of points in
%    each cluster.
%
%    Input/output, real AN1(K).
%
%    Input/output, real AN2(K).
%
%    Input/output, integer NCP(K).
%
%    Input/output, real D(M).
%
%    Input/output, integer ITRAN(K).
%
%    Input/output, integer INDX, counts the number of steps
%    since the last transfer.
%

%
%  In the optimal transfer stage, NCP(L) indicates the step at which
%  cluster L is last updated.   In the quick transfer stage, NCP(L)
%  is equal to the step at which cluster L is last updated plus M.
%
  icoun = 0;
  istep = 0;

  while ( true )

    for i = 1 : m

      icoun = icoun + 1;
      istep = istep + 1;
      l1 = ic1(i);
      l2 = ic2(i);
%
%  If point I is the only member of cluster L1, no transfer.
%
      if ( 1 < nc(l1) )
%
%  If NCP(L1) < ISTEP, no need to re-compute distance from point I to
%  cluster L1.   Note that if cluster L1 is last updated exactly M
%  steps ago, we still need to compute the distance from point I to
%  cluster L1.
%
        if ( istep <= ncp(l1) )

          da = 0.0;
          for j = 1 : n
            db = a(i,j) - c(l1,j);
            da = da + db * db;
          end

          d(i) = da * an1(l1);

        end
%
%  If NCP(L1) <= ISTEP and NCP(L2) <= ISTEP, there will be no transfer of
%  point I at this step.
%
        if ( istep < ncp(l1) || istep < ncp(l2) )

          r2 = d(i) / an2(l2);

          dd = 0.0;
          for j = 1 : n
            de = a(i,j) - c(l2,j);
            dd = dd + de * de;
          end
%
%  Update cluster centers, NCP, NC, ITRAN, AN1 and AN2 for clusters
%  L1 and L2.   Also update IC1(I) and IC2(I).   Note that if any
%  updating occurs in this stage, INDX is set back to 0.
%
          if ( dd < r2 )

            icoun = 0;
            indx = 0;
            itran(l1) = 1;
            itran(l2) = 1;
            ncp(l1) = istep + m;
            ncp(l2) = istep + m;
            al1 = nc(l1);
            alw = al1 - 1.0;
            al2 = nc(l2);
            alt = al2 + 1.0;
            for j = 1 : n
              c(l1,j) = ( c(l1,j) * al1 - a(i,j) ) / alw;
              c(l2,j) = ( c(l2,j) * al2 + a(i,j) ) / alt;
            end
            nc(l1) = nc(l1) - 1;
            nc(l2) = nc(l2) + 1;
            an2(l1) = alw / al1;
            if ( 1.0 < alw )
              an1(l1) = alw / ( alw - 1.0 );
            else
              an1(l1) = Inf;
            end
            an1(l2) = alt / al2;
            an2(l2) = alt / ( alt + 1.0 );
            ic1(i) = l2;
            ic2(i) = l1;

          end

        end

      end
%
%  If no re-allocation took place in the last M steps, return.
%
      if ( icoun == m )
        return
      end

    end

  end

  return
end
