diff mftoolbox/rootpm_schur_newton.m @ 0:8f23314345f4 draft

Create local repository for matrix toolboxes. Step #0 done.
author Antonio Pino Robles <data.script93@gmail.com>
date Wed, 06 May 2015 14:56:53 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mftoolbox/rootpm_schur_newton.m	Wed May 06 14:56:53 2015 +0200
@@ -0,0 +1,66 @@
+function [X,Y] = rootpm_schur_newton(A,p)
+%ROOTPM_SCHUR_NEWTON  Matrix pth root by Schur-Newton method.
+%   [X,Y] = ROOTPM_SCHUR_NEWTON(A,p) computes the principal pth root
+%   X of the real matrix A using the Schur-Newton algorithm.
+%   It also returns Y = INV(X).
+
+if norm(imag(A),1), error('A must be real.'), end
+A = real(A);   % Discard any zero imaginary part.
+[Q,R] = schur(A,'real'); % Quasitriangular R.
+
+e = eig(R);
+if any (e(find(e == real(e))) < 0 )
+   error('A has a negative real eigenvalue: principal pth root not defined')
+end
+
+f = factor(p);
+k0 = length(find(f == 2)); % Number of factors 2.
+q = p/2^(k0);
+k1 = k0;
+if q > 1
+
+   emax = max(abs(e)); emin = min(abs(e));
+   if emax > emin % Avoid log(0).
+      k1 = max(k1, ceil( log2( log2(emax/emin) ) ));
+   end
+
+   max_arg = norm(angle(e),inf);
+   if max_arg > pi/8
+      k3 = 1;
+      if max_arg > pi/2
+         k3 = 3;
+      elseif max_arg > pi/4
+         k3 = 2;
+      end
+      k1 = max(k1,k3);
+   end
+
+end
+
+for i = 1:k1, R = sqrtm_real(R); end
+
+
+if q ~= 1
+   pw = 2^(-k1); emax = emax^pw; emin = emin^pw;
+   if ~any(imag(e))
+     % Real eigenvalues.
+     if emax > emin
+        alpha = emax/emin;
+        c = ( (alpha^(1/q)*emax-emin)/( (alpha^(1/q)-1)*(q+1) ) )^(1/q);
+     else
+        c = emin^(1/q);
+     end
+   else
+     % Complex eigenvalues.
+     c = (( emax+emin)/2 )^(1/q);
+   end
+
+   X = rootpm_newton(R,q,c);
+   for i = 1:k1-k0
+       X = X*X;
+   end
+else
+   X = R;
+end
+Y = Q*(X\Q');  % Return inverse pth root, too.
+X = Q*X*Q';