function w = wcond(A,toler,kind) %function w = wcond(A,toler,kind) %wcond: calculate the w-condition number of A = X'X pos def, % sqrt(trace(X'X)/n/(det(X'X))^{1/n}) %INPUT: % A,X n x n pos. def.; X is m x n full column rank % toler tolerance to find w if det(A) jumps from 0 to Inf % kind =1 if A pos. def. is the input, % =2 if X rectangular is input %default is assuming pos. def. A is input if nargin==3, if kind==1, disp(['starting wcond assuming given input is A pos. def.']) elseif kind==2, disp(['starting wcond assuming given input is X rect.']) [m,n] = size(A); if (m>=n) A = A'*A; else A = A*A'; end else disp('ERROR: input kind is not 1 or 2') w = nan; return end elseif nargin==2 disp(['starting wcond assuming given input is A pos. def.']) else disp(['starting wcond assuming given input is A pos. def.']) toler=log(n)*1e-10; % default tolerance disp(['default tolerance for omega is ',num2str(toler)]); end %check the input [m,n]=size(A); if m ~= n, disp('ERROR: A is not square. Please check input.'); w = nan; return end if normest(A-A')>1e-10, disp('ERROR: A is not symmetric. Please check input.'); w = nan; return end %limit number of iterations to check w = Inf maxlim = ceil((log2(realmax)-log2(realmin))); w = trace(A)/n; %lu decomposition of A [~,u] = lu(full(A)); %use the formulation det(A)=abs(prod(diag(u))) A = diag(u); dA = prod(A); %if det(A) is finite, calculate w directly if (isfinite(dA) & isfinite(log(dA))) w = w/abs(dA)^(1/n); w = sqrt(w); return; end %calculate det(A)^{1/n} using binary search %find upper and lower bound for scalar a if isinf(dA) aL = 0; aH = 1; else %if det(A) = 0, calculate aL: det(aL*A) = 0 while det(2*aL*A) ~= 0 aL = 1; aH = 2; dA = prod(aH*A); index = 1; while (isfinite(dA) & isinf(log(dA)) & index <= maxlim) aL = aH; aH = 2*aH; dA = prod(aH*A); index = index + 1; end %if det(aH*A) = 0 if (isfinite(dA) & isinf(log(dA))) disp('ERROR: A is not pos. def. Please check input.'); w = Inf; return; end end %binary search to find the scalar a such that det(aA) is finite a = aH; %if det(aH*A) is not finite while ((isinf(dA) | isinf(log(dA))) & (aH-aL)/2>toler) a = (aL + aH)/2; dA = prod(a*A); if (isfinite(dA) & isfinite(log(dA))) w = a*w/abs(dA)^(1/n); w = sqrt(w); return; end %update aL and aH if (isinf(dA)) aH = a; else aL = a; end end %if det(a*A) and log(det(a*A)) are finite if ((aH-aL)/2 > toler) w = a*w/abs(dA)^(1/n); w = sqrt(w); else %1/det(A)^{1/n} is between aL and aH w = w*((aH+aL)/2); w = sqrt(w); end