No BSD License  

Highlights from
Modified GCD

from Modified GCD by Sundar Krishnan
Modification in MATLAB's gcd.m by suppressing calculation of u2, v2 and t2 at intermediate steps

gcd(a, b)
function [g, c, d] = gcd(a, b)
%
% [My notes on the working of 0, 1 and  1, 0 "trick",
% and Usage Examples have been added.
% Sundar Krishnan (sundark100@yahoo.com) Oct 2004]
%
% Pl also refer my modified code : gcd_SK_GHB.m which
% is based on the suppression of calculation of u2, v2 and t2
% at intermediate steps - as observed by Gordon H. Bradley - as given
% in 4.5.2, P343 of Vol 2, 3rd Ed of D E Knuth's book.
%
% Matlab's Original Initial Comments :
%
%GCD    Greatest common divisor.
%   G = GCD(A,B) is the greatest common divisor of corresponding
%   elements of A and B.  The arrays A and B must contain non-negative
%   integers and must be the same size (or either can be scalar).
%   GCD(0,0) is 0 by convention; all other GCDs are positive integers.
%
%   [G,C,D] = GCD(A,B) also returns C and D so that G = A.*C + B.*D.
%   These are useful for solving Diophantine equations and computing
%   Hermite transformations.
%   Refer also my code Diophantine_1.m and Diophantine_miniature9.pdf.
%
%   Algorithm: Originally of Aryabhatta (AD 499)
%   See Knuth Volume 2, Section 4.5.2, Algorithm X.
%   (P343 in 3rd Ed of D E Knuth's book)
%
%   See also LCM.
%   Author:    John Gilbert, Xerox PARC
%   Copyright 1984-2000 The MathWorks, Inc. 
%   $Revision: 5.12 $  $Date: 2000/06/01 15:13:59 $
%
%                                 &&&&&&&&&&&&
%
% Refer to my modified code gcd_SK_GHB.m incorporating Gordon H. Bradley's
% suggestion of suppression of calculation of u2, v2 and t2
% at intermediate steps.
%
% Refer also to my code CMPLX_GCD.m where too, I have followed
% Aryabhatta's 0, 1 and 1, 0 logic as followed in Matlab's standard gcd.m
% However, as of Sep 2004, I have not yet explored in CMPLX_GCD.m
% if similar u2, v2 and t2 calculations can be suppressed
% at intermediate steps.
%
% Refer also to my other GCD related codes like Poly_GCD.m, Ch_Rem_Thr_Int.m,
% Ch_Rem_Thr_Poly.m etc as published in Matlab's File Exchange.
%
%                               ****************
%
% Working Egs :
% The notation in this eg largely follows Richard Blahut's book :
% Algebraic Codes for Data Transmission / P71.
% Read this as a support for field_inv_test.m
%
% Let us work with this eg :
% [G, a, b] = gcd ( s, p ) = gcd ( 585, 3887 ) 
% Assumption : s < p    (I follow p instead of q.)
%
% Verify : G = a*s + b*p
%
% 585 ) 3887 ( 6
%       3510
%       ----
%        377 ) 585 ( 1
%              377
%              ---
%              208 ) 377 ( 1
%                    208
%                    ---
%                    169 ) 208 ( 1
%                          169
%                          ---
%                           39 ) 169 ( 4
%                                156
%                                ---
%                                 13 ) 39 ( 3
%                                      39
%                                      --
%                                      00
%
% IMP : Observe that all the Divisors : 13, 39, 169, 208, 377, 585
% are all multiples of the GCD = 13.
%
% So our qoutients have been : 6, 1, 1, 1, 4, 3
%
% The Procedure :
%
% Take : 0  1  higher no = 3887
% and  : 1  0  lower no  =  585
%
% Now, we need to operate on 0 1  and  1 0 the same way as with the main nos,
% but with the same quotients as we obtained for the main 2 nos.
%
%  1 ) 0 ( 6
%      6
%     --
%     -6 ) 1 ( 1
%         -6
%         --
%          7 ) -6 ( 1
%               7
%             ---
%             -13 )  7 ( 1
%                  -13
%                  ---
%                   20 ) -13 ( 4
%                         80
%                        ---
%              a =  -->  -93 )  20 ( 3    % a = -93, the multiple on s = 585, the lower no
%                             -279 
%                             ----
%                         -->  299        % abs (299) * (GCD = 13) = 3887 = p (higher no)
%                             
%
%  0 ) 1 ( 6
%      0
%      -
%      1 ) 0 ( 1
%          1
%         --
%         -1 ) 1 ( 1
%             -1
%             --
%              2 ) -1 ( 1
%                   2
%                  --
%                  -3 )  2 ( 4
%                      -12
%                      ---
%              b =  --> 14 ) -3 ( 3     
% b = 14, the multiple on p =3887, the higher no
%                            42
%                           ---
%                       --> -45         
% abs (-45) * (GCD = 13) = 585 = s (lower no)
%
%
%                                 &&&&&&&&&&&&
%
% [G, a, b] = gcd ( 21, 77 )
%
% 21 ) 77 ( 3
%      63
%      --
%      14 ) 21 ( 1
%           14
%           --
%            7 ) 14 ( 2
%                14
%                --
%                00
%
% IMP : Observe that all the Divisors : 7, 14, 21
% are all multiples of the GCD = 7.
%
% So our qoutients have been : 3, 1, 2
%
% The Procedure :
%
% Take : 0  1  higher no = 77
% and  : 1  0  lower no  = 21
%
% Now, we need to operate on 0 1  and  1 0 the same way as with the main nos,
% but with the same quotients as we obtained for the main 2 nos.
%
%  1 ) 0 ( 3
%      3
%     --
%     -3 ) 1 ( 1
%         -3
%         --
% a = -->  4 ) -3 ( 2       % a = 4, the multiple on s = 21, the lower no
%               8
%             ---
%        -->  -11           % abs (-11) * (GCD = 7) = 77 = p (higher no)
%
%
%  0 ) 1 ( 3
%      0
%     --
%      1 ) 0 ( 1
%          1
%         --
% b = --> -1 )  1 ( 2       % b = -1, the multiple on p = 77, the higher no
%              -2
%              --
%          -->  3           % abs (3) * (GCD = 7) = 21 = s (lower no)
%
%                                 &&&&&&&&&&&&
%
% % Case Mod 3a of gcd_SK_GHB.m :
% clc
% a = round ( randn ( 1, 10) * 10000 ) ;
% b = round ( randn ( 1, 10) * 10000 ) ;
% [G, c, d] = gcd ( a, b )
%
% % Observe that for random numbers, the GCD would be 1 for 60.793%
% % the cases. Refer Knuth, Vol 2, Theorem D in P342.
%
% % Above Reversed : Case Mod 3b of gcd_SK_GHB.m :
% clc
% [G, c, d] = gcd_SK_GHB ( b, a )
%
%                               ****************

% Do scalar expansion if necessary - to make both a and b of the same size
if length(a) == 1
   a = a(ones(size(b))) ;
elseif length(b) == 1
   b = b(ones(size(a))) ;
end

if ~isequal(size(a),size(b))
    error('Inputs must be the same size.')
else
    siz = size(a) ;
    a = a(:) ;      b = b(:) ;
end

if ~isequal(round(a),a) | ~isequal(round(b),b)
    error('Requires integer input arguments.')
end
 
for k = 1 : length(a)            % length(a) decides the no of sets.
    u = [ 1  0  abs(a(k)) ] ;
    v = [ 0  1  abs(b(k)) ] ;
    
    % The "abs" above is the culprit why Bradley's suggestion did not
    % work directly in gcd_SK_GHB.m !
    
    while v(3)    % ie, till the rem becomes 0 for EACH set
    % Note that (3) => the 3rd el => each set is handled independently.
    
        % Fulcrum : The foll 4 steps do the HCF operation on the 2 main nos,
        % and similarly, with the same quotients on 1 0  and  0 1.
        % See 2 Working Egs above.
        % u(3), v(3)
        q = floor ( u(3) / v(3) ) ;
        t = u - v * q ;
        u = v ;
        v = t ;
    end
    
    % u, v, t, q, pause
    
    c(k) = u(1) * sign(a(k)) ;
    d(k) = u(2) * sign(b(k)) ;
    g(k) = u(3) ;
    
%     % Only for comapring the results of gdc_SK_GHB.m ;
%     % Foll line to be commented later.
%     fprintf ( '\n**** gcd.m        : k = %d ;    u(2) = %d\n', k, u(2) ) ;
    
end

c = reshape(c,siz) ;
d = reshape(d,siz) ;
g = reshape(g,siz) ;

Contact us at files@mathworks.com