  function P3Grade()
% Checks out RightHalfPertub(A,s)

m = 10; n = 5; A = gallery('randsvd',[m,n],10^6);
clc
fprintf('%m = 1d, n = %1d, sigma_min(A) = %10.6e\n\n',m,n,min(svd(A)))
disp('    s   sigma_min([A1 A1+E_YOU])   norm(E_YOU)   norm(E_CVL)  ')   
disp('-----------------------------------------------------------------')
for s=1:n-1
    [normE,E] = RightHalfPerturb(A,s);
    Atilde = A + [zeros(m,n-s) E];
    sigma_min = min(svd(Atilde));
    [normE_CVL,E] = RightHalfPerturbCVL(A,s);
    fprintf('   %2d        %10.3e            %10.3e    %10.3e\n',s,sigma_min,normE,normE_CVL)
end


 
  function [normE,E] = RightHalfPerturbCVL(A,s)
% A is mxn with full column rank and 1<=s<n
% E is an m-by-s matrix with the property that [ A(:,1:n-s) A(:,n-s+1:n+e)] is
% rank deficient and no other matrix with this property has small 2-norm.
% normE is the 2-norm of E.

[m,n] = size(A);
% A1 = A(:,1:n-s), A2 = A(:,n-s+1:n)
[Q,R] = qr(A,0);
% Q = [Q1 Q2], R  = [R11 R12; 0 R22 ; 0 0 ]  where R11 and R22 (sxs) are square
R22 = R(n-s+1:n,n-s+1:n);
% If [A1 A2+E2] is rank deficient, then so is 
%
%          Q'[A1 A2+E2] = [R11 R12+E12_tilde ; 0 R22+E22_tilde; 0 0] 

% Note that if [R11 R12+E12_tilde ; 0 R22+E22_tilde] is singular then
% then norm([E12_tilde;E22_tilde]) >= norm(E22_tilde). (Why?)
% The block R22+E22_tilde must be singular and the "best" choice for E22_tilde
% is  -S(s,s)U(:,s)V(:,s)' where
[U,S,V] = svd(R22);
% Thus E = E2_opt = Q2*E22_tilde = (-S(s,s)*(Q2*U(:,s)))*V(:,s)'
E = (-S(s,s)*(Q(:,n-s+1:n)*U(:,s)))*V(:,s)';
normE = S(s,s);

% -1 if you do no tuse the thin qr factorizatio,

