summaryrefslogtreecommitdiff
path: root/macros/gflineq.sci
diff options
context:
space:
mode:
Diffstat (limited to 'macros/gflineq.sci')
-rw-r--r--macros/gflineq.sci170
1 files changed, 170 insertions, 0 deletions
diff --git a/macros/gflineq.sci b/macros/gflineq.sci
new file mode 100644
index 0000000..3b34529
--- /dev/null
+++ b/macros/gflineq.sci
@@ -0,0 +1,170 @@
+function [x, sflag] = gflineq(a, b, p)
+// This function finds a solution for linear equation Ax = b over a prime Galois field.
+//
+// Calling Sequence
+// [X, SFLAG] = GFLINEQ(A, B)
+// [X, SFLAG]= GFLINEQ(A, B, P)
+//
+// Description
+// [X, SFLAG] = GFLINEQ(A, B) returns a particular solution (X) of AX=B in GF(2).
+// If the equation has no solution, then X is empty and SFLAG = 0 else SFLAG = 1.
+//
+// [X, SFLAG]= GFLINEQ(A, B, P) returns a particular solution of the linear
+// equation A X = B in GF(P) and SFLAG=1.
+// If the equation has no solution, then X is empty and SFLAG = 0.
+//
+
+// Examples
+// A=[1 0 1; 1 1 0; 1 1 1]
+// p=3
+// [x,vld] = gflineq(A,[1;0;1],p)
+// disp(A,'A=')
+// disp(x,'x=');
+// if(vld)
+// disp('Linear equation has solution x')
+// else
+// disp('Linear equation has no solution and x is empty')
+// end
+// disp( pmodulo(A*x,p),'B =')
+
+// See also
+// gfadd, gfconv, gfdiv, gfrank, gfroots
+
+// Authors
+// Pola Lakshmi Priyanka, IIT Bombay//
+
+
+//*************************************************************************************************************************************//
+
+// Check number of input arguments
+[out_a,inp_a]=argn(0)
+
+if inp_a >3 | out_a> 2 | inp_a <2 then
+ error('comm:gflineq: Invalid number of arguments')
+end
+
+// Error checking .
+if inp_a < 3
+ p = 2;
+elseif ( isempty(p) | length(p)~=1 | abs(p)~=p | ceil(p)~=p | length(factor(p))~=1 )
+ error('comm:gflineq:Input argument 3 must be a positive prime integer.');
+end;
+
+[row_a, col_a] = size(a);
+[row_b, col_b] = size(b);
+
+// Error checking - A & B.
+if ( isempty(a) | ndims(a) > 2 )
+ error('comm:gflineq:Input argument 1 must be a two-dimensional matrix.');
+end
+if ( isempty(b) | ndims(b) > 2 | col_b > 1 )
+ error('comm:gflineq:Invalid dimensions of input argument 2 .');
+end
+if ( row_a ~= row_b )
+ error('comm:gflineq:Dimensions of A and B are not compatible');
+end
+if (( or( abs(a)~=a | floor(a)~=a | a>=p )) | ( or( abs(b)~=b | floor(b)~=b | b>=p )) )
+ error('comm:gflineq:Elements of input matrices should be integers between 0 and P-1.');
+end
+
+// Solution is found by using row reduction (Reducing it to echelon form)
+ab = [a b]; // Composite matrix
+[row_ab, col_ab] = size(ab);
+
+row_i = 1;
+col_i = 1;
+row = [];
+col = [];
+
+while (row_i <= row_ab) & (col_i < col_ab)
+
+ // Search for a non zero element in current column
+ while (ab(row_i,col_i) == 0) & (col_i < col_ab)
+
+ idx = find( ab(row_i:row_ab, col_i) ~= 0 );
+
+ if isempty(idx)
+ col_i = col_i + 1; // No non zero element
+ else
+ // Swap the current row with a row containing a non zero element
+ // (preferably with the row with value 1).
+ idx = [ find(ab(row_i:row_ab, col_i) == 1) idx ];
+ idx = idx(1);
+ temp_row = ab(row_i,:)
+ ab(row_i,:) = ab(row_i+idx-1,:)
+ ab(row_i+idx-1,:) = temp_row
+
+ end
+ end
+
+ if ( ( ab(row_i,col_i) ~= 0 ) & ( col_i < col_ab ) )
+
+ // Set major element to 1.
+ if (ab(row_i,col_i) ~= 1)
+ ab(row_i,:) = pmodulo( field_inv( ab(row_i,col_i),p ) * ab(row_i,:), p );
+ end
+
+ // The current element is a major element.
+ row = [row row_i];
+ col = [col col_i];
+
+ // Find the other elements in the column that must be cleared,
+ idx = find(ab(:,col_i)~=0);
+
+ for i = idx
+ if i ~= row_i
+ ab(i,:) = pmodulo( ab(i,:) + ab(row_i,:) * (p - ab(i,col_i)), p );
+ end
+ end
+
+ col_i = col_i + 1;
+
+ end
+
+
+ row_i = row_i + 1;
+
+
+end
+
+if ( rank(ab) > rank( ab(:,1:col_a) ) )
+ disp('comm:gflineq:Solution does not exist');
+ x = [];
+ sflag = 0;
+else
+ x = zeros(col_a, 1);
+ x(col,1) = ab(row,col_ab);
+ sflag = 1;
+end
+
+endfunction
+
+
+function [x] = field_inv(a,n)
+ t = 0;
+ newt = 1;
+ r = n;
+ newr = a;
+
+ while newr ~= 0
+ quotient = floor(r / newr);
+
+ temp = t;
+ t = newt;
+ newt = temp -quotient*newt;
+
+ temp = r;
+ r = newr;
+ newr = temp - quotient*newr;
+ end
+
+ if r>1
+ [x c] = find( pmodulo( (1:(p-1)).' * (1:(p-1)) , p ) == 1 );
+ end
+
+ if t<0
+ t = t + n;
+ end
+ x = t;
+
+endfunction