No BSD License  

Highlights from
More Flexible Sorting and Multiplicity of Roots of a Polynomial

from More Flexible Sorting and Multiplicity of Roots of a Polynomial by Sundar Krishnan
More Flexible Sorting and Multiplicity of Roots of a Polynomial

...
function [Poly_Rts, no_Real_Rts, no_Cmplx_Rts] = ...
    cmplx_roots_sort ( Poly_Rts, str_Rev )
%
% Sundar Krishnan (sundark100@yahoo.com)
% Release  : R14, R13, R12
% Date     : June-July 2005
%
% Functional Description :
% ------------------------
% Imagine a function that can pair the Complex Conjugate Roots
% of a Polynomial, and also tell us how many Roots are Real,
% and how many are Complex.
% The immediate answer will be that oh, we already have
% Matlab's standard cplxpair. But, I have observed that
% as the degree of a Polynomial increases, the results obtained by
% Matlab's roots has so much variation that the standard cplxpair
% will result in an error !
% The standard Matlab roots () function does not return
% n exactly identical roots if the input Polynomial has
% n Repeated Roots, specially when n is above 10.
% So, firstly, we need to modify the tolerances of cplxpair.
% cplxpair_Mod is a modified version of the Standard R14 Matlab's cplxpair.
%
% There are three additional requirements :
% 2) After reading TrigonometryAnglesPi7.html in MathWorld,
% I realised that :
% If the coeffs of a Poly are reversed, and then if the resulting roots
% of this modified Poly are reversed in order, we get an exact
% Identity = 1 relationship between the 2 sets of roots.
%
% For eg, if one of the roots of a Poly_N = [ 8, -4, -4, 1 ]
% is -cos(2*pi/7), then the corresponding Reciprocal Root
% will be -sec(2*pi/7), which can be obtained as the corresponding root
% of Poly_R = [ 1, -4, -4, 8 ] which is Poly_N with coeffs
% reversed in order.
% So, we need a function which can also reverse the pairing order.
%
% 3) The third reason is that we would like to have the Pure Real Roots
% listed in the beginning, and then the Complex (Conjugate-Paired) Roots
% for both the NORmal and the REVerse sorting cases.
%
% 4) The fourth reason is to obtain the number of Real and Complex Roots.
%
% In the Default "Forward" Dir, the Real Roots are first sorted,
% and then, the Complex Roots are sorted by their absolute magnitude.
% If the 'REV' option is chosen, the Real Roots are again first sorted,
% but now in Reverse order, and then, the Complex Roots are sorted
% in the Reverse order of their absolute magnitude.
% Thus, in both cases, we will have the Real Roots listed first.
%
% Because of the usage of cplxpair_Mod (a modified version of cplxpair),
% this Programme will work correctly only if the Complex Roots are
% in Conjugate Pairs.
%
% 5) There is in fact, a fifth reason :
% that is when we need to know the multiplicity of the roots
% as is required when we need to raise a Polynomial to Fractional Powers.
% This roots' multiplicity need is fulfilled by a more Detailed Programme :
% cmplx_roots_sort_Det.m, which in addition to the number
% of Real and Complex Roots, also gives the multiplicity of each root.
% cmplx_roots_sort_Det.m calls this Programme cmplx_roots_sort.m
% which in turn calls cplxpair_Mod.m.
% Also, when cplxpair_Mod fails for Non-Conjugate Complex Roots,
% cmplx_roots_sort_Det.m deals with such cases by considering
% them as individual roots, the code being in the catch section
% of thetry-catch block.
% cmplx_roots_sort_Det.m was developed as a sequel to this Programme.
%
% If this suite of Programmes (in this zip file) don't work for you
% directly when downloaded into an independent directory, you could
% try loading these files in the Matlab dir : ...\toolbox\matlab\specfun
%
%                               &&&&&&&&&&&&&&&&&
%
% Author's Legal Disclaimer :
% ---------------------------
% I share my code, developed with lots of efforts, and often based
% on lots of studies, in good faith.
% Everyone is free to use this code at their own risk provided
% they include my name for this part in their works.
% However, I am still learning many facets of this subject ;
% there may be still some open unanswered technical questions for me
% on this subject and possibly in this programme.
% I am NOT responsible for any technical or legal complications
% directly or indirectly, arising out of any direct or indirect use
% of my codes or my interpretations.
% Any apparent TECHNICAL fault in interpreting any external references, 
% or others' replies in any Public User Group Forums, is my own, 
% not theirs. However, I am NOT LEGALLY responsible for any of my
% technical or other interpretation of others' comments in ANY Forum.
%
%                               &&&&&&&&&&&&&&&&&
%
% % Usage Egs :
% % Case 1 for :
% Poly_N = [ 43    82    90    64    73    82    58 ] 
% Num_Roots = roots ( Poly_N ) 
% Recipr_Roots = roots ( fliplr( Poly_N ) ) 
% 
% [Rts_N, no_Real_Rts, no_Cmplx_Rts] = cmplx_roots_sort ( Num_Roots ) 
% [Rts_R, no_Real_Rts, no_Cmplx_Rts] = ...
%     cmplx_roots_sort ( Recipr_Roots, 'REV' ) 
% Rts_N .* Rts_R    % SHOULD BE all 1  ie, Recipr_Roots = 1./Num_Roots
%
%       OR with Num_Roots and Recipr_Roots given directly :
%
% [Rts_N, no_Real_Rts, no_Cmplx_Rts] = ...
%     cmplx_roots_sort ( [ 0.5582 + 0.8057i,  0.5582 - 0.8057i, ...
% -0.5631 + 0.9537i,  -0.5631 - 0.9537i, ...
% -0.9487 + 0.4946i,  -0.9487 - 0.4946i ], 'NOR' )
%
% [Rts_R, no_Real_Rts, no_Cmplx_Rts] = ...
%     cmplx_roots_sort ( [ 0.5810 + 0.8386i,  0.5810 - 0.8386i, ...
% -0.8289 + 0.4321i,  -0.8289 - 0.4321i, ...
% -0.4590 + 0.7775i,  -0.4590 - 0.7775i ], 'REV' )
%
% Rts_N .* Rts_R    % SHOULD BE all 1  ie, Recipr_Roots = 1./Num_Roots
%
%
% % Construct Poly_R and verify :
% Poly_R = 1 ;
% for i = 1 : length (Rts_R)
%     Poly_R = conv ( Poly_R, [1, -Rts_R(i)] ) ;
% end
% Poly_R    % This is a monic Polynomial.
% Poly_R = Poly_R * Poly_N(end)
% % This should tally with reversed coeffs of Poly_N
% Poly_R - fliplr( Poly_N )    % order of 1e-12
%
%                                   ^^^^^^^^^^
%
% % Case 2 for :
% Poly_N = [ -3    82    -90    64    -73    -82    58   -99 ] ;
% Num_Roots = roots ( Poly_N ) 
% Recipr_Roots = roots ( fliplr( Poly_N ) ) 
%
% [Rts_N, no_Real_Rts, no_Cmplx_Rts] = cmplx_roots_sort ( Num_Roots ) 
% [Rts_R, no_Real_Rts, no_Cmplx_Rts] = ...
%     cmplx_roots_sort ( Recipr_Roots, 'REV' ) 
% Rts_N .* Rts_R    % SHOULD BE all 1  ie, Recipr_Roots = 1./Num_Roots
%
% % Construct Poly_R and verify :
% Poly_R = 1 ;
% for i = 1 : length (Rts_R)
%     Poly_R = conv ( Poly_R, [1, -Rts_R(i)] ) ;
% end
% Poly_R    % This is a monic Polynomial.
% Poly_R = Poly_R * Poly_N(end)
% % This should tally with reversed coeffs of Poly_N
% Poly_R - fliplr( Poly_N )    % order of 1e-12
%
%                                   ^^^^^^^^^^
%
% % Case 3 for :
% Poly_N = [ 0.1897    0.6145    0.1934    0.5077   0.6822    1.6924 ]
% Num_Roots = roots ( Poly_N ) 
% Recipr_Roots = roots ( fliplr( Poly_N ) ) 
%
% [Rts_N, no_Real_Rts, no_Cmplx_Rts] = cmplx_roots_sort ( Num_Roots ) 
% [Rts_R, no_Real_Rts, no_Cmplx_Rts] = ...
%     cmplx_roots_sort ( Recipr_Roots, 'REV' ) 
% Rts_N .* Rts_R    % SHOULD BE all 1  ie, Recipr_Roots = 1./Num_Roots
%
% % Construct Poly_R and verify :
% Poly_R = 1 ;
% for i = 1 : length (Rts_R)
%     Poly_R = conv ( Poly_R, [1, -Rts_R(i)] ) ;
% end
% Poly_R    % This is a monic Polynomial.
% Poly_R = Poly_R * Poly_N(end)
% % This should tally with reversed coeffs of Poly_N
% Poly_R - fliplr( Poly_N )    % order of 1e-14
%
%                                   ^^^^^^^^^^
%
% Many more Usage Examples can be seen in Constants_AlgNo_Cycl.m
%
%                              *******************

% 1) Inits :
if nargin < 2
    str_Rev = 'NOR' ;    % Default is 'NORMAL' ordering of roots.
end

%                               &&&&&&&&&&&&&&&&&

% 2) Convert the roots to a Col Vector :
Poly_Rts = Poly_Rts (:) ;

%                               &&&&&&&&&&&&&&&&&

% 3) Separate the Real and Complex Roots :
Poly_Rts_Real = [ ] ;
Poly_Rts_Cmplx = [ ] ;

for index = 1 : length (Poly_Rts)
    if isreal (Poly_Rts(index))
        Poly_Rts_Real  = [ Poly_Rts_Real,  Poly_Rts(index) ] ;
    else
        Poly_Rts_Cmplx = [ Poly_Rts_Cmplx, Poly_Rts(index) ] ;
    end
end

%                               &&&&&&&&&&&&&&&&&

% 4) Pair the Complex Roots into Complex Conjugate Pairs.
% Note that if the Complex Roots are not "suitably paired"
% for cplxpair_Mod, it may result in an error.
Poly_Rts_Cmplx = cplxpair_Mod ( Poly_Rts_Cmplx ) ;

Poly_Rts_Cmplx_Abs = abs ( Poly_Rts_Cmplx ) ;
[Poly_Rts_Cmplx_Abs, ind_Cmplx] = sort ( Poly_Rts_Cmplx_Abs ) ;

[Poly_Rts_Real_Abs, ind_Real] = sort( abs( Poly_Rts_Real ) ) ;

%                               &&&&&&&&&&&&&&&&&

% 5) Choice of sorting :
% For 'NOR(MAL)'_Roots : Normal Sorted Order with Real first,
% then Complex Roots :
Poly_Rts_Real  = Poly_Rts_Real(ind_Real) ;
Poly_Rts_Cmplx = Poly_Rts_Cmplx(ind_Cmplx) ;

% For Reciprocal ie, 'REV(ERSE)' Roots :
% Here is where we reverse the sorted order
% within Real and within Complex, respectively :
if ~any ( str_Rev ~= 'REV' )
    Poly_Rts_Real  = fliplr( Poly_Rts_Real ) ;
    Poly_Rts_Cmplx = fliplr( Poly_Rts_Cmplx ) ;
end

Poly_Rts = [ Poly_Rts_Real, Poly_Rts_Cmplx ] ;

%                               &&&&&&&&&&&&&&&&&

% 5) Count the no of Real and Complex Roots.
no_Real_Rts  = length (Poly_Rts_Real)  ;
no_Cmplx_Rts = length (Poly_Rts_Cmplx) ;

% cmplx_roots_sort_Det.m gives the multiplicity of each root also,
% in addition to the number of Real and Complex Roots.

%                              *******************

Contact us at files@mathworks.com