function [Q,R] = qrdelete(Q,R,j,orient)
%QRDELETE Delete a column or row from QR factorization.
%   [Q1,R1] = QRDELETE(Q,R,J) returns the QR factorization of the matrix A1,
%   where A1 is A with the column A(:,J) removed and [Q,R] = QR(A) is the QR
%   factorization of A. Matrices Q and R can also be generated by
%   the "economy size" QR factorization [Q,R] = QR(A,0).
%
%   QRDELETE(Q,R,J,'col') is the same as QRDELETE(Q,R,J).
%
%   [Q1,R1] = QRDELETE(Q,R,J,'row') returns the QR factorization of the matrix
%   A1, where A1 is A with the row A(J,:) removed and [Q,R] = QR(A) is the QR
%   factorization of A.
%
%   Example:
%      A = magic(5);  [Q,R] = qr(A);
%      j = 3;
%      [Q1,R1] = qrdelete(Q,R,j,'row');
%   returns a valid QR factorization, although possibly different from
%      A2 = A;  A2(j,:) = [];
%      [Q2,R2] = qr(A2);
%
%   Class support for inputs Q,R:
%      float: double, single
%
%   See also QR, QRINSERT, PLANEROT.

%   Copyright 1984-2020 The MathWorks, Inc.

    if nargin < 4
        if nargin < 3
            error(message('MATLAB:qrdelete:NotEnoughInputs'))
        end
        orient = 'col';
    end

    if ~isnumeric(j)||~isscalar(j)||~isfinite(j)||~isreal(j) || floor(j)~=j
        error(message('MATLAB:qrdelete:InvalidJ'));
    end

    % This comparison handles strings and partial matching
    if isstring(orient) || iscellstr(orient)
        if matlab.internal.math.checkInputName(orient,'col',1)
            orient = 'col';
        elseif matlab.internal.math.checkInputName(orient,'row',1)
            orient = 'row';
        end
    end

    R = triu(R);
    [mq,nq] = size(Q);
    [m,n] = size(R);
    if strcmp(orient,'row') && (mq ~= nq)
        error(message('MATLAB:qrdelete:QNotSquare'))
    elseif nq ~= m
        error(message('MATLAB:qrdelete:InnerDimQRfactors'))
    elseif j <= 0
        error(message('MATLAB:qrdelete:NegDeletionIndex'))
    end

    % Check if Q and R are non-sparse float arrays before invoking the
    % built-in function
    isFloatArray = (~isobject(Q) && isfloat(Q) && ~issparse(Q)) && ...
        (~isobject(R) && isfloat(R) && ~issparse(R))&&~isobject(j);

    switch orient
      case 'col'
        if (j > n)
            error(message('MATLAB:qrdelete:InvalidDelIndex'))
        end
        % Remove the j-th column.  n = number of columns in modified R.
        R(:,j) = [];
        [m,n] = size(R);

        % R now has nonzeros below the diagonal in columns j through n.
        %    R = [x | x x x         [x x x x
        %         0 | x x x          0 * * x
        %         0 | + x x    G     0 0 * *
        %         0 | 0 + x   --->   0 0 0 *
        %         0 | 0 0 +          0 0 0 0
        %         0 | 0 0 0]         0 0 0 0]
        % Use Givens rotations to zero the +'s, one at a time, from left to right.
        if isFloatArray
            [Q,R]=matlab.internal.math.deleteCol(Q,R,j);
        else
            for k = j:min(n,m-1)
                p = k:k+1;
                [G,R(p,k)] = planerot(R(p,k));
                if k < n
                    R(p,k+1:n) = G*R(p,k+1:n);
                end
                Q(:,p) = Q(:,p)*G';
            end
        end

        % If Q is not square, Q is from economy size QR(A,0).
        % Both Q and R need further adjustments.
        if (mq ~= nq)
            R(m,:)=[];
            Q(:,nq)=[];
        end

      case 'row'
        if (j > m)
            error(message('MATLAB:qrdelete:InvalidDelIndex'))
        end

        % Lets say q is the transpose of the jth row of Q.
        %    q = [x         [1
        %         -          -
        %         +    G     0
        %         +   --->   0
        %         +          0
        %         +          0
        %         +]         0]
        %
        % Use Givens rotations to zero the +'s, one at a time, from bottom to top.
        % The result will have a "1" in the (j,1) entry of Q.
        %
        % Apply the same rotations to R, which becomes upper Hessenberg.
        %    R = [x x x x          [* * * *
        %         -------           -------
        %           x x x     G     * * * *
        %             x x    --->     * * *
        %               x               * *
        %         0 0 0 0                 *
        %         0 0 0 0]          0 0 0 0]
        %
        % Under (the transpose of) the same rotations, Q becomes
        %    Q = [x | x x x x x         [0 | * * * * *
        %         x | x x x x x    G'    0 | * * * * *
        %         x | x x x x x   --->   0 | * * * * *
        %         --|----------          --|----------
        %         x | x x x x x          1 | 0 0 0 0 0
        %         --|----------          --|----------
        %         x | x x x x x          0 | * * * * *
        %         x | x x x x x]         0 | * * * * *]
        if isFloatArray
            [Q,R]=matlab.internal.math.deleteRow(Q,R,j);
        else
            q = Q(j,:)';
            for i = m : -1 : 2
                p = i-1 : i;
                [G,q(p)] = planerot(q(p));
                Q(:,p) = Q(:,p) * G';
                R(p,i-1:n) = G * R(p,i-1:n);
            end
        end

        % The boxed off (---) parts of Q and R are the desired factors.
        Q = Q([1:j-1,j+1:end],2:end);
        R(1,:) = [];

      otherwise
        error(message('MATLAB:qrdelete:InvalidInput4'));
    end
