function [ x, qraux, ipvt ] = zqrdc ( x, ldx, n, p, ipvt, job )

%*****************************************************************************80
%
%% ZQRDC computes the QR factorization of an N by P complex matrix.
%
%  Discussion:
%
%    ZQRDC uses Householder transformations to compute the QR factorization
%    of an N by P matrix X.  Column pivoting based on the 2-norms of the
%    reduced columns may be performed at the user's option.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 May 2007
%
%  Author:
%
%    MATLAB version by John Burkardt
%
%  Reference:
%
%    Jack Dongarra, Jim Bunch, Cleve Moler, Pete Stewart,
%    LINPACK User's Guide,
%    SIAM, 1979,
%    ISBN13: 978-0-898711-72-1,
%    LC: QA214.L56.
%
%  Parameters:
%
%    Input, complex X(LDX,P), the matrix whose decomposition
%    is to be computed.
%
%    Input, integer LDX, the leading dimension of X.  N <= LDX.
%
%    Input, integer N, the number of rows of the matrix.
%
%    Input, integer P, the number of columns in the matrix X.
%
%    Input, integer IPVT(P), integers that control the
%    selection of the pivot columns.  The K-th column X(K) of X is placed
%    in one of three classes according to the value of IPVT(K):
%      IPVT(K) > 0, then X(K) is an initial column.
%      IPVT(K) == 0, then X(K) is a free column.
%      IPVT(K) < 0, then X(K) is a final column.
%    Before the decomposition is computed, initial columns are moved to the
%    beginning of the array X and final columns to the end.  Both initial
%    and final columns are frozen in place during the computation and only
%    free columns are moved.  At the K-th stage of the reduction, if X(K)
%    is occupied by a free column it is interchanged with the free column
%    of largest reduced norm.
%
%    Input, integer JOB, initiates column pivoting.
%    0, no pivoting is done.
%    nonzero, pivoting is done.
%
%    Output, complex X(LDX,P); the upper triangle contains the upper
%    triangular matrix R of the QR factorization.  Below its diagonal, X
%    contains information from which the unitary part of the decomposition
%    can be recovered.  If pivoting has been requested, the decomposition is
%    not that of the original matrix X, but that of X with its columns
%    permuted as described by IPVT.
%
%    Output, complex QRAUX(P), further information required to recover
%    the unitary part of the decomposition.
%
%    Output, integer IPVT(P); the index of the column of the
%    original matrix that has been interchanged into
%    the K-th column, if pivoting was requested.
%    IPVT is not referenced if JOB == 0.
%
  pl = 1;
  pu = 0;

  if ( job ~= 0 )
%
%  Pivoting has been requested.  Rearrange the columns according to IPVT.
%
    for j = 1 : p

      swapj = ( 0 < ipvt(j) );
      negj = ( ipvt(j) < 0 );

      if ( negj )
        ipvt(j) = -j;
      else
        ipvt(j) = j;
      end

      if ( swapj )

        if ( j ~= pl )
          temp      = x(1:n,pl);
          x(1:n,pl) = x(1:n,j);
          x(1:n,j)  = temp;
        end

        ipvt(j) = ipvt(pl);
        ipvt(pl) = j;
        pl = pl + 1;

      end

    end

    pu = p;

    for jj = 1 : p

      j = p - jj + 1;

      if ( ipvt(j) < 0 )

        ipvt(j) = -ipvt(j);

        if ( j ~= pu )

          temp      = x(1:n,pu);
          x(1:n,pu) = x(1:n,j);
          x(1:n,j)  = temp;

          i        = ipvt(pu);
          ipvt(pu) = ipvt(j);
          ipvt(j)  = i;

        end

        pu = pu - 1;

      end

    end

  end
%
%  Compute the norms of the free columns.
%
  for j = pl : pu
    qraux(j) = dznrm2 ( n, x(1:n,j), 1 );
    work(j) = qraux(j);
  end
%
%  Perform the Householder reduction of X.
%
  lup = min ( n, p );

  for l = 1 : lup
%
%  Locate the column of largest norm and bring it
%  into the pivot position.
%
    if ( pl <= l && l < pu )

      maxnrm = 0.0;
      maxj = l;

      for j = l : pu
        if ( maxnrm < real ( qraux(j) ) )
          maxnrm = real ( qraux(j) );
          maxj = j;
        end
      end

      if ( maxj ~= l )

        temp        = x(1:n,l);
        x(1:n,l)    = x(1:n,maxj);
        x(1:n,maxj) = temp;

        qraux(maxj) = qraux(l);
        work(maxj)  = work(l);

        i          = ipvt(maxj);
        ipvt(maxj) = ipvt(l);
        ipvt(l)    = i;

      end

    end

    qraux(l) = 0.0;

    if ( l ~= n )
%
%  Compute the Householder transformation for column L.
%
      nrmxl = dznrm2 ( n-l+1, x(l:n,l), 1 );

      if ( zabs1 ( nrmxl ) ~= 0.0 )

        if ( zabs1 ( x(l,l) ) ~= 0.0 )
          nrmxl = zsign2 ( nrmxl, x(l,l) );
        end

        x(l:n,l) = x(l:n,l) / nrmxl;
        x(l,l) = 1.0 + x(l,l);
%
%  Apply the transformation to the remaining columns,
%  updating the norms.
%
        for j = l+1 : p

          t = - ( conj ( transpose ( x(l:n,l) ) ) * x(l:n,j) ) / x(l,l);
          x(l:n,j) = x(l:n,j) + t * x(l:n,l);

          if ( j < pl || pu < j )
            continue
          end

          if ( zabs1 ( qraux(j) ) == 0.0 )
            continue
          end

          tt = 1.0 - ( abs ( x(l,j) ) / real ( qraux(j) ) )^2;
          tt = max ( tt, 0.0 );
          t = tt;
          tt = 1.0 + 0.05 * tt * ( real ( qraux(j) ) / real ( work(j) ) )^2;

          if ( tt ~= 1.0 )
            qraux(j) = qraux(j) * sqrt ( t );
          else
            qraux(j) = dznrm2 ( n-l, x(l+1:n,j), 1 );
            work(j) = qraux(j);
          end

        end
%
%  Save the transformation.
%
        qraux(l) = x(l,l);
        x(l,l) = -nrmxl;

      end

    end

  end

  return
end
