Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  Smith.gi   Sprache: unbekannt

 
###############################################################################
##
#F Smith.gi            The SymbCompCC package          Dörte Feichtenschlager
##

###############################################################################
##
## InfoLevel: InfoSmithPPowerPoly: 1 level until which SNF is computed
##                                 2 show pivot element
##                                 3 show always P, Q and S
##
## Global Varialble: CHECK_SMITHNF_PPOWERPOLY
##

###############################################################################
##
## IdentityPPowerPolyMat( p, n )
##
## Input: a prime p and a positive integer n.
##
## Output: the nxn-identity matrix with p-power-poly entries.
##
InstallMethod( IdentityPPowerPolyMat, [ IsPosInt, IsPosInt ],
   function( p, n )
      local I, One1, Zero0, i, j;
      
      I := [];
      One1 := Int2PPowerPoly( p, 1 );
      Zero0 := Int2PPowerPoly( p, 0 );

      for i in [1..n] do
         I[i] := [];
         I[i][i] := One1;
         for j in [1..i-1] do
            I[i][j] := Zero0;
         od;
         for j in [i+1..n] do
            I[i][j] := Zero0;
         od;
      od;

      return I;
   end);

###############################################################################
##
## IdentityPPowerPolyLocMat( p, n )
##
## Input: a prime p and a positive integer n.
##
## Output: a nxn-identity-matrix with p-power-poly-loc entries.
##
InstallMethod( IdentityPPowerPolyLocMat, [ IsPosInt, IsPosInt ],
   function( p, n )
      local I, One1, Zero0, i, j, One1Loc, Zero0Loc;
      
      I := [];
      One1 := Int2PPowerPoly( p, 1 );
      Zero0 := Int2PPowerPoly( p, 0 );
      One1Loc := [ One1, One1 ];
      Zero0Loc := [ Zero0, One1 ];

      for i in [1..n] do
         I[i] := [];
         I[i][i] := One1Loc;
         for j in [1..i-1] do
            I[i][j] := Zero0Loc;
         od;
         for j in [i+1..n] do
            I[i][j] := Zero0Loc;
         od;
      od;

      return I;
   end);

###############################################################################
##
## NullPPowerPolyMat( p, n )
##
## Input: a prime p and a positive integer n.
##
## Output: a nxn-zero-matrix with p-power-poly entries.
##
InstallMethod( NullPPowerPolyMat, [ IsPosInt, IsPosInt ],
   function( p, n )
      local N, Zero0, i, j;
      
      N := [];
      Zero0 := Int2PPowerPoly( p, 0 );

      for i in [1..n] do
         N[i] := [];
         for j in [1..n] do
            N[i][j] := Zero0;
         od;
      od;

      return N;
   end);

###############################################################################
##
## NullPPowerPolyLocMat( p, n )
##
## Input: a prime p and a positive integer n.
##
## Output: a nxn-zero-matrix with p-power-poly-loc entries.
##
InstallMethod( NullPPowerPolyLocMat, [ IsPosInt, IsPosInt ],
   function( p, n )
      local N, Zero0, One1, Zero0Loc, i, j;
      
      N := [];
      Zero0 := Int2PPowerPoly( p, 0 );
      One1 := Int2PPowerPoly( p, 1 );
      Zero0Loc := [ Zero0, One1 ];

      for i in [1..n] do
         N[i] := [];
         for j in [1..n] do
            N[i][j] := Zero0Loc;
         od;
      od;

      return N;
   end);

###############################################################################
##
## NullPPowerPolyMat( p, n, m )
##
## Input: a prime p and positive integers n and m.
##
## Output: a nxm-zero-matrix with p-power-poly entries.
##
InstallMethod( NullPPowerPolyMat, [ IsPosInt, IsPosInt, IsPosInt ], 
   function( p, n, m )
      local N, Zero0, i, j;
      
      N := [];
      Zero0 := Int2PPowerPoly( p, 0 );

      for i in [1..n] do
         N[i] := [];
         for j in [1..m] do
            N[i][j] := Zero0;
         od;
      od;

      return N;
   end);

###############################################################################
##
## NullPPowerPolyLocMat( p, n, m )
##
## Input: a prime p and positive integers n and m.
##
## Output: a nxm-zero-matrix with p-power-poly-loc entries.
##
InstallMethod( NullPPowerPolyLocMat, [ IsPosInt, IsPosInt, IsPosInt ], 
   function( p, n, m )
      local N, Zero0, One1, Zero0Loc, i, j;
      
      N := [];
      Zero0 := Int2PPowerPoly( p, 0 );
      One1 := Int2PPowerPoly( p, 1 );
      Zero0Loc := [ Zero0, One1 ];

      for i in [1..n] do
         N[i] := [];
         for j in [1..m] do
            N[i][j] := Zero0Loc;
         od;
      od;

      return N;
   end);

###############################################################################
##
## ExchangeRowsPPP( i, j, S )
##
## Input: a matrix S with p-power-poly entries and positive integers i and j,
##        where i and j are smaller than or equal to the number of rows of S.
##
## Output: a matrix with p-power-poly entries, which is the matrix S, but the
##         rows i and j interchanged.
##
InstallMethod( ExchangeRowsPPP, [ IsPosInt, IsPosInt, IsList ], 
   function( i, j, S )
      local help, k, l_s;

      l_s := Length( S );

      ## check if the input is alright
      if i > l_s or j > l_s then
         Error("Wrong input, the first two input parameters (integers) have to be smaller than the number of rows of the matrix (the third input).");
      fi;

      ## exchange the rows
      for k in [1..Length(S[1])] do
         if not PPP_Equal( S[i][k], S[j][k] ) then
            help := StructuralCopy( S[i][k] );
            S[i][k] := StructuralCopy( S[j][k] );
            S[j][k] := help;
         fi;
      od;

      return S;
   end);

###############################################################################
##
## ExchangeRowsPPPL( i, j, S )
##
## Input: a matrix S with p-power-poly-loc entries and positive integers i and
##        j, where i and j are smaller than or equal to the number of rows of S.
##
## Output: a matrix with p-power-poly-loc entries, which is the matrix S, but 
##         the rows i and j interchanged.
##
InstallMethod( ExchangeRowsPPPL, [ IsPosInt, IsPosInt, IsList ], 
   function( i, j, S )
      local help, k, l_s;

      l_s := Length( S );

      ## check if the input is alright
      if i > l_s or j > l_s then
         Error("Wrong input, the first two input parameters (integers) have to be smaller than the number of rows of the matrix (the third input).");
      fi;

      ## exchange the rows
      for k in [1..Length(S[1])] do
         if not PPPL_Equal( S[i][k], S[j][k] ) then
            help := StructuralCopy( S[i][k] );
            S[i][k] := StructuralCopy( S[j][k] );
            S[j][k] := help;
         fi;
      od;

      return S;
   end);

###############################################################################
##
##  ExchangeColumnsPPP( o, j, S )
##
## Input: a matrix S with p-power-poly entries and positive integers i and j,
##        where i and j are smaller than or equal to the number of columns of S.
##
## Output: a matrix with p-power-poly entries, which is the matrix S, but the
##         columns i and j interchanged.
##
InstallMethod( ExchangeColumnsPPP, [ IsPosInt, IsPosInt, IsList ], 
   function( i, j, S )
      local l_s, k, help;

      l_s := Length( S[1] );

      ## check if the input is alright
      if i > l_s or j > l_s then
         Error("Wrong input, the first two input parameters (integers) have to be smaller than the number of columns of the matrix (the third input).");
      fi;

      ## exchange the columns
      for k in [1..Length(S)] do
         if not PPP_Equal( S[k][i], S[k][j] ) then
            help := StructuralCopy( S[k][i] );
            S[k][i] := StructuralCopy( S[k][j] );
            S[k][j] := help;
         fi;
      od;

      return S;
   end);

###############################################################################
##
##  ExchangeColumnsPPPL( i, j, S )
##
## Input: a matrix S with p-power-poly-loc entries and positive integers i and
##        j, where i and j are smaller than or equal to the number of columns 
##        of S.
##
## Output: a matrix with p-power-poly-loc entries, which is the matrix S, but 
##         the columns i and j interchanged.
##
InstallMethod( ExchangeColumnsPPPL, [ IsPosInt, IsPosInt, IsList ], 
   function( i, j, S )
      local l_s, k, help;

      l_s := Length( S[1] );

      ## check if the input is alright
      if i > l_s or j > l_s then
         Error("Wrong input, the first two input parameters (integers) have to be smaller than the number of columns of the matrix (the third input).");
      fi;

      ## exchange the columns
      for k in [1..Length(S)] do
         if not PPPL_Equal( S[k][i], S[k][j] ) then
            help := StructuralCopy( S[k][i] );
            S[k][i] := StructuralCopy( S[k][j] );
            S[k][j] := help;
         fi;
      od;

      return S;
   end);

###############################################################################
##
## EmptyColumn( i, S, P )
##
## Input: a positive integer i and p-power-poly matrices S and P, where P
##        stores row-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyColTrans := P ), where S is the
##         modified matrix where the entries in column i are zero, except 
##         (i,i), subject to the condition that (i,i) divides every entry in 
##         the i-th column of S; P stores row-transformation performed on 
##         S so far.
##
InstallMethod( EmptyColumn, [ IsPosInt, IsList, IsList ], 
   function( i, S, P )
      local Zero0, One1, l_s, l_s1, l_p1, j, list, q, k;

      Zero0 := PPP_ZeroNC( S[1][1] );
      One1 := PPP_OneNC( S[1][1] );

      l_s := Length( S );
      l_s1 := Length( S[1] );
      l_p1 := Length( P[1] );

      if i > l_s then
         Error("Wrong input, the first entry cannot be larger then the row-length of the second entry.");
      fi;

      ## empty column in S and P, first columns above i
      for j in [1..i-1] do
         if not PPP_Equal( S[j][i], Zero0 ) then
            if not PPP_Equal( S[i][i], One1 ) then
               q := DivPPartPoly( S[j][i], S[i][i] );
            else q := S[j][i];
            fi;
            for k in [1..l_s1] do
               S[j][k] := PPP_Subtract( S[j][k], PPP_Mult( q, S[i][k] ) );
               P[j][k] := PPP_Subtract( P[j][k], PPP_Mult( q, P[i][k] ) );
            od;
         fi;
      od;

      ## empty column in S and P, first columns below i
      for j in [i+1..l_s] do
         if not PPP_Equal( S[j][i], Zero0 ) then
            if not PPP_Equal( S[i][i], One1 ) then
               q := DivPPartPoly( S[j][i], S[i][i] );
            else q := S[j][i];
            fi;

            ## row j of S - q row i of S
            for k in [1..l_s1] do
               if not PPP_Equal( S[i][k], Zero0 ) then
                  S[j][k] := PPP_Subtract( S[j][k], PPP_Mult( q, S[i][k] ) );
               fi;
            od;

            ## row j of P - q row i of P
            for k in [1..l_p1] do
               if not PPP_Equal( P[i][k], Zero0 ) then
                  P[j][k] := PPP_Subtract( P[j][k], PPP_Mult( q, P[i][k] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyCol := S, emptyColTrans := P );
   end);

###############################################################################
##
## EmptyColumnLoc( i, S, P )
##
## Input: a positive integer i and p-power-poly-loc matrices S and P, where P
##        stores row-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyColTrans := P ), where S is the
##         modified matrix where the entries in column i are zero, except 
##         (i,i), subject to the condition that (i,i) divides every entry in 
##         the i-th column of S; P stores row-transformation performed on 
##         S so far.
##
InstallMethod( EmptyColumnLoc, [ IsPosInt, IsList, IsList ], 
   function( i, S, P )
      local Zero0Loc, num, denom, Zero0, j, num_j, denom_j, list, q,
            q_Loc, k, l_s, l_s1, l_p1, One1;

      Zero0Loc := PPPL_ZeroNC( S[1][1] );

      l_s := Length( S );
      l_s1 := Length( S[1] );
      l_p1 := Length( P[1] );

      if i > l_s then
         Error("Wrong input.");
      fi;

      num := S[i][i][1];
      denom := S[i][i][2];

      Zero0 := PPP_ZeroNC( num );
      One1 := PPP_OneNC( num );
 
      ## empty column in S and P, first columns above i
      for j in [1..i-1] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            num_j := S[j][i][1];
            denom_j := S[j][i][1];
            q := PPP_Mult( num_j, denom );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( PPP_Mult( num_j, denom ), num );
            fi;
            if PPP_Equal( denom_j, One1 ) then
               q_Loc := [ q, denom_j ];
            else q_Loc := PPPL_Check( [ q, denom_j ] );
            fi;
            for k in [1..l_s1] do
               S[j][k] := PPPL_Subtract( S[j][k], PPPL_Mult( q_Loc, S[i][k] ) );
               P[j][k] := PPPL_Subtract( P[j][k], PPPL_Mult( q_Loc, P[i][k] ) );
            od;
         fi;
      od;

      ## empty column in S and P, first columns below i
      for j in [i+1..l_s] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            num_j := S[j][i][1];
            denom_j := S[j][i][2];
            q := PPP_Mult( num_j, denom );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( PPP_Mult( num_j, denom ), num );
            fi;
            if PPP_Equal( denom_j, One1 ) then
               q_Loc := [ q, denom_j ];
            else q_Loc := PPPL_Check( [ q, denom_j ] );
            fi;

            ## row j of S - q_Loc row i of S
            for k in [1..l_s1] do
               if not PPPL_Equal( S[i][k], Zero0Loc ) then
                  S[j][k] := PPPL_Subtract( S[j][k], PPPL_Mult( q_Loc, S[i][k] ) );
               fi;
            od;

            ## row j of P - q_Loc row i of P
            for k in [1..l_p1] do
               if not PPPL_Equal( P[i][k], Zero0Loc ) then
                  P[j][k] := PPPL_Subtract( P[j][k], PPPL_Mult( q_Loc, P[i][k] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyCol := S, emptyColTrans := P );
   end);

###############################################################################
##
## EmptyColumnGreater( i, S, P )
##
## Input: a positive integer i and p-power-poly matrices S and P, where P
##        stores row-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyColTrans := P ), where S is the
##         modified matrix where the entries in column i and row j with j > i
##         are zero, subject to the condition that (i,i) divides every entry 
##         in the i-th column of S; P stores row-transformation performed 
##         on S so far.
##
InstallMethod( EmptyColumnGreater, [ IsPosInt, IsList, IsList ], 
   function( i, S, P )
      local Zero0, One1, j, list, q, k, l_s, l_s1, l_p1;

      Zero0 := PPP_ZeroNC( S[1][1] );
      One1 := PPP_OneNC( S[1][1] );

      l_s := Length( S );
      l_s1 := Length( S[1] );
      l_p1 := Length( P[1] );

      if i > l_s then
         Error("Wrong input, the first entry cannot be larger then the number of rows of the second entry.");
      fi;

      for j in [i+1..l_s] do
         if not PPP_Equal( S[j][i], Zero0 ) then
            if not PPP_Equal( S[i][i], One1 ) then
               q := DivPPartPoly( S[j][i], S[i][i] ); 
            else q := S[j][i];
            fi;

            ## row j of S - q row i of S
            for k in [1..l_s1] do
               if not PPP_Equal( S[i][k], Zero0 ) then
                  S[j][k] := PPP_Subtract( S[j][k], PPP_Mult( q, S[i][k] ) );
               fi;
            od;

            ## row j of P - q row i of P
            for k in [1..l_p1] do
               if not PPP_Equal( P[i][k], Zero0 ) then
                  P[j][k] := PPP_Subtract( P[j][k], PPP_Mult( q, P[i][k] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyCol:=S, emptyColTrans:=P );
   end);

###############################################################################
##
## EmptyColumnGreaterLoc( i, S, P )
##
## Input: a positive integer i and p-power-poly-loc matrices S and P, where P
##        stores row-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyColTrans := P ), where S is the
##         modified matrix where the entries in column i and row j with j > i
##         are zero, subject to the condition that (i,i) divides every entry 
##         in the i-th column of S; P stores row-transformation performed 
##         on S so far.
##
InstallMethod( EmptyColumnGreaterLoc, [ IsPosInt, IsList, IsList ], 
   function( i, S, P )
      local Zero0Loc, num, denom, Zero0, j, num_j, denom_j, 
            list, q, q_Loc, k, l_s, l_s1, l_p1, One1;

      Zero0Loc := PPPL_ZeroNC( S[1][1] );

      l_s := Length( S );
      l_s1 := Length( S[1] );
      l_p1 := Length( P[1] );

      if i > l_s then
         Error("Wrong input, the first entry cannot be larger than the number of rows of the second entry.");
      fi;

      num := S[i][i][1];
      denom := S[i][i][2];

      Zero0 := PPP_ZeroNC( num );
      One1 := PPP_OneNC( num );

      for j in [i+1..l_s] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            num_j := S[j][i][1];
            denom_j := S[j][i][2];
            q := PPP_Mult( num_j, denom );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( q, num ); 
            fi;
            if PPP_Equal( denom_j, One1 ) then
               q_Loc := [ q, denom_j ];
            else q_Loc := PPPL_Check( [ q, denom_j ] );
            fi;

            ## row j of S - q_Loc row i of S
            for k in [1..l_s1] do
               if not PPPL_Equal( S[i][k], Zero0Loc ) then
                  S[j][k] := PPPL_Subtract( S[j][k], PPPL_Mult( q_Loc, S[i][k] ) );
               fi;
            od;

            ## row j of P - q_Loc row i of P
            for k in [1..l_p1] do
               if not PPPL_Equal( P[i][k], Zero0Loc ) then
                  P[j][k] := PPPL_Subtract( P[j][k], PPPL_Mult( q_Loc, P[i][k] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyCol := S, emptyColTrans := P );
   end);

###############################################################################
##
## EmptyColumnGreaterLoc_NonP( i, S )
##
## Input: a positive integer i and a p-power-poly matrix S.
##
## Output: a matrix S: S is the modified matrix where the entries in column 
##         i and row j with j > i are zero, subject to the condition that 
##         (i,i) divides every entry in the i-th column of S. 
##
InstallMethod( EmptyColumnGreaterLoc_NonP, [ IsPosInt, IsList ], 
   function( i, S )
      local Zero0Loc, num, denom, Zero0, j, num_j, denom_j, 
            list, q, q_Loc, k, l_s, l_s1, l_p1, One1;

      Zero0Loc := PPPL_ZeroNC( S[1][1] );

      l_s := Length( S );
      l_s1 := Length( S[1] );

      if i > l_s then
         Error("Wrong input, the first entry cannot be larger than the number of colums of the second entry.");
      fi;

      num := S[i][i][1];
      denom := S[i][i][2];

      Zero0 := PPP_ZeroNC( num );
      One1 := PPP_OneNC( num );

      for j in [i+1..l_s] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            num_j := S[j][i][1];
            denom_j := S[j][i][2];
            q := PPP_Mult( num_j, denom );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( q, num ); 
            fi;
            if PPP_Equal( denom_j, One1 ) then
               q_Loc := [ q, denom_j ];
            else q_Loc := PPPL_Check( [ q, denom_j ] );
            fi;

            ## row j of S - q_Loc row i of S
            for k in [1..l_s1] do
               if not PPPL_Equal( S[i][k], Zero0Loc ) then
                  S[j][k] := PPPL_Subtract( S[j][k], PPPL_Mult( q_Loc, S[i][k] ) );
               fi;
            od;

         fi;
      od;

      return S;
   end);

###############################################################################
##
## EmptyRowGreater( i, S, Q )
##
## Input: a positive integer i and p-power-poly matrices S and Q, where Q
##        stores column-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyRowTrans := Q ), where S is the
##         modified matrix where the entries in row i and column j with j > i
##         are zero, subject to the condition that (i,i) divides every entry 
##         in the i-th row of S; Q stores column-transformation performed 
##         on S so far.
##
InstallMethod( EmptyRowGreater, [ IsPosInt, IsList, IsList ], 
   function( i, S, Q )
      local n, Zero0, One1, j, k, q, list, l_s, l_q;

      n := Length( S[1] );
      Zero0 := PPP_ZeroNC( S[1][1] );
      One1 := PPP_OneNC( S[1][1] );

      l_s := Length( S );
      l_q := Length( Q );

      if i > n then
         Error("Wrong input, the first entry cannot be larger than the number of rows of the second entry.");
      fi;

      for j in [i+1..n] do
         if not PPP_Equal( S[i][j], Zero0 ) then
            if not PPP_Equal( S[i][i], One1 ) then
               q := DivPPartPoly( S[i][j], S[i][i] );
            else q := S[i][j];
            fi;

            ## column j of S - q column i of S
            for k in [1..l_s] do
               if not PPP_Equal( S[k][i], Zero0 ) then
                  S[k][j] := PPP_Subtract( S[k][j], PPP_Mult( q, S[k][i] ) );
               fi;
            od;

            ## column j of Q - q column i of Q
            for k in [1..l_q] do
               if not PPP_Equal( Q[k][i], Zero0 ) then
                  Q[k][j] := PPP_Subtract( Q[k][j], PPP_Mult( q, Q[k][i] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyRow := S, emptyRowTrans := Q );
   end);

###############################################################################
##
## EmptyRowGreaterLoc( i, S, Q )
##
## Input: a positive integer i and p-power-poly-loc matrices S and Q, where Q
##        stores column-transformation performed on S so far.
##
## Output: a record rec( emptyCol := S, emptyRowTrans := Q ), where S is the
##         modified matrix where the entries in row i and column j with j > i
##         are zero, subject to the condition that (i,i) divides every entry 
##         in the i-th row of S; Q stores column-transformation performed 
##         on S so far.
##
InstallMethod( EmptyRowGreaterLoc, [ IsPosInt, IsList, IsList ], 
   function( i, S, Q )
      local n, Zero0Loc, Zero0, num, denom, j, k, q, list, q_Loc, l_s, 
            l_q, One1;

      n := Length( S[1] );
      Zero0Loc := PPPL_ZeroNC( S[1][1] );
      Zero0 := PPP_ZeroNC( S[1][1][1] );
      One1 := PPP_OneNC( S[1][1][1] );

      l_s := Length( S );
      l_q := Length( Q );

      if i > n then
         Error("Wrong input, the first entry cannot be larger than the numver of rows of the second entry.");
      fi;

      num := S[i][i][1];
      denom := S[i][i][2];

      for j in [i+1..n] do
         if not PPP_Equal( S[i][j][1], Zero0 ) then
            q := PPP_Mult( denom, S[i][j][1] );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( q, num );
            fi;
            if PPP_Equal( S[i][j][2], One1 ) then
               q_Loc := [ q, S[i][j][2] ];
            else q_Loc := PPPL_Check( [ q, S[i][j][2] ] );
            fi;

            ## column j of S - q_Loc column i of S
            for k in [1..l_s] do
               if not PPPL_Equal( S[k][i], Zero0Loc ) then
                  S[k][j] := PPPL_Subtract( S[k][j], PPPL_Mult( q_Loc, S[k][i] ) );
               fi;
            od;

            ## column j of Q - q_Loc column i of Q
            for k in [1..l_q] do
               if not PPPL_Equal( Q[k][i], Zero0Loc ) then
                  Q[k][j] := PPPL_Subtract( Q[k][j], PPPL_Mult( q_Loc, Q[k][i] ) );
               fi;
            od;
         fi;
      od;

      return rec( emptyRow := S, emptyRowTrans := Q );
   end);

###############################################################################
##
## EmptyRowGreaterLoc_NonQ( i, S )
##
## Input: a positive integer i and p-power-poly-loc matrix S.
##
## Output: a matrix S: S is the modified matrix where the entries in row i 
##         and column j with j > i are zero, subject to the condition that 
##         (i,i) divides every entry in the i-th row of S.
##
InstallMethod( EmptyRowGreaterLoc_NonQ, [ IsPosInt, IsList ], 
   function( i, S )
      local n, Zero0Loc, Zero0, num, denom, j, k, q, list, q_Loc, l_s, 
            One1;

      n := Length( S[1] );
      Zero0Loc := PPPL_ZeroNC( S[1][1] );
      Zero0 := PPP_ZeroNC( S[1][1][1] );
      One1 := PPP_OneNC( S[1][1][1] );

      l_s := Length( S );

      if i > n then
         Error("Wrong input, the first entry cannot be larger than the number of rows of the second entry.");
      fi;

      num := S[i][i][1];
      denom := S[i][i][2];

      for j in [i+1..n] do
         if not PPP_Equal( S[i][j][1], Zero0 ) then
            q := PPP_Mult( denom, S[i][j][1] );
            if not PPP_Equal( num, One1 ) then
               q := DivPPartPoly( q, num );
            fi;
            if PPP_Equal( S[i][j][2], One1 ) then
               q_Loc := [ q, S[i][j][2] ];
            else q_Loc := PPPL_Check( [ q, S[i][j][2] ] );
            fi;

            ## column j of S - q_Loc column i of S
            for k in [1..l_s] do
               if not PPPL_Equal( S[k][i], Zero0Loc ) then
                  S[k][j] := PPPL_Subtract( S[k][j], PPPL_Mult( q_Loc, S[k][i] ) );
               fi;
            od;
         fi;
      od;

      return S;
   end);

###############################################################################
##
## DivRowLoc( i, S, P, el )
##
## Input: a positive integer i, p-power-poly-loc matrices S and P and a
##        p-power-poly-loc element el, where P stores row-transformation 
##        performed on S so far. 
##
## Output: a list [S, P]: S is the modified matrix where the entries in row i
##         are divided by the p-power-poly-loc element el; P stores 
##         row-transformation performed on S so far.
##
InstallGlobalFunction( DivRowLoc, 
   function( i, S, P, el )
      local Zero0Loc, num, Zero0, denom, j, div;

      Zero0Loc := PPPL_ZeroNC( el );

      num := el[1];
      Zero0 := PPP_ZeroNC( num );
      ## check
      if PPP_Equal( num, Zero0 ) then
         Error( "Wrong input, division by zero." );
      fi;

      denom := el[2];
      div := PPPL_CheckNC( [ denom, num ] );

      ## divide entries in row i of S
      for j in [1..Length(S[1])] do
         if not PPPL_Equal( S[i][j], Zero0Loc ) then
            S[i][j] := PPPL_Mult( S[i][j], div );
         fi;
      od;

      ## divide entries in row i of P
      for j in [1..Length(P[1])] do
         if not PPPL_Equal( P[i][j], Zero0Loc ) then
            P[i][j] := PPPL_Mult( P[i][j], div );
         fi;
      od;

      return [ S, P ];
   end);

###############################################################################
##
## DivRowLoc_NonP( i, S, el )
##
## Input: a positive integer i, a p-power-poly-loc matrix S and a
##        p-power-poly-loc element el. 
##
## Output: a matrix S which is the modified matrix where the entries in row i
##         are divided by the p-power-poly-loc element el.
##
InstallGlobalFunction( DivRowLoc_NonP, 
   function( i, S, el )
      local Zero0Loc, num, Zero0, denom, j, div;

      Zero0Loc := PPPL_ZeroNC( el );

      num := el[1];
      Zero0 := PPP_ZeroNC( num );
      ## check
      if PPP_Equal( num, Zero0 ) then
         Error( "Wrong input, division by zero." );
      fi;

      denom := el[2];
      div := PPPL_CheckNC( [ denom, num ] );

      ## divide entries in row i of S
      for j in [1..Length(S[1])] do
         if not PPPL_Equal( S[i][j], Zero0Loc ) then
            S[i][j] := PPPL_Mult( S[i][j], div );
         fi;
      od;

      return S;
   end);

###############################################################################
##
## DivColLoc( i, S, Q, el )
##
## Input: a positive integer i, p-power-poly-loc matrices S and Q and a
##        p-power-poly-loc element el, where Q stores column-transformation 
##        performed on S so far. 
##
## Output: a list [S, Q]: S is the modified matrix where the entries in 
##         column i are divided by the p-power-poly-loc element el; Q stores 
##         column-transformation performed on S so far.
##
InstallGlobalFunction( DivColLoc, 
   function( i, S, Q, el )
      local Zero0Loc, Zero0, num, denom, div, j;

      Zero0Loc := PPPL_ZeroNC( el );

      num := el[1];
      Zero0 := PPP_ZeroNC( num );
      ## check
      if PPP_Equal( num, Zero0 ) then
         Error( "Wrong input, division by zero." );
      fi;

      denom := el[2];
      div := PPPL_CheckNC( [ denom, num ] );

      ## divide entries in column i of S
      for j in [1..Length(S)] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            S[j][i] := PPPL_Mult( S[j][i], div );
         fi;
      od;

      ## divide entries in column i of Q
      for j in [1..Length(Q)] do
         if not PPPL_Equal( Q[j][i], Zero0Loc ) then
            Q[j][i] := PPPL_Mult( Q[j][i], div );
         fi;
      od;

      return [ S, Q ];
   end);

###############################################################################
##
## DivColLoc_NonQ( i, S, el )
##
## Input: a positive integer i, a p-power-poly-loc matrix S and a
##        p-power-poly-loc element el. 
##
## Output: a matrix S which is the modified matrix where the entries in 
##         column i are divided by the p-power-poly-loc element el.
##
InstallGlobalFunction( DivColLoc_NonQ, 
   function( i, S, el )
      local Zero0Loc, num, Zero0, denom, div, j;

      Zero0Loc := PPPL_ZeroNC( el );

      num := el[1];
      Zero0 := PPP_ZeroNC( num );
      ## check
      if PPP_Equal( num, Zero0 ) then
         Error( "Wrong input, division by zero." );
      fi;

      denom := el[2];
      div := PPPL_CheckNC( [ denom, num ] );

      ## divide entries in column i of S
      for j in [1..Length(S)] do
         if not PPPL_Equal( S[j][i], Zero0Loc ) then
            S[j][i] := PPPL_Mult( S[j][i], div );
         fi;
      od;

      return [ S ];
   end);

###############################################################################
##
## SmithNormalFormPPowerPoly( M_in )
##
## Input: a matrix M_in with p-power-poly-loc entries.
##
## Output: a matrix which is the Smith normal form of M_in.
##
InstallMethod( SmithNormalFormPPowerPoly, [ IsList ], 
   function( M_in )

      local p, n, m, i, j, k, l, S, Zero0Loc, One1Loc, eval_pv, eval_test, 
            pprimediv, pv_set, pv_1, pv_2, q, Rec, test, check;

      check := CHECK_SMITHNF_PPOWERPOLY;

      if check then
         Print( "Note: no check can be done during the computation of the Smith normal form." );
      fi;

      CHECK_SMITHNF_PPOWERPOLY := false;

      n := Length( M_in[1] );
      m := Length( M_in );

      p := M_in[1][1][2][1];

      Zero0Loc := PPPL_ZeroNC( M_in[1][1] );
      One1Loc := PPPL_OneNC( M_in[1][1] );

      ## if zero-mat, then return
      if ForAll( M_in, x -> ForAll( x, y -> PPPL_Equal( y, PPPL_Mult( Zero0Loc, y ) ) ) ) then
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "Smith normal form is computed. \n" );
         fi;

         CHECK_SMITHNF_PPOWERPOLY := check;

         return M_in;
      fi;
      S := StructuralCopy( M_in );

      ## change the matrix to a diagonal matrix
      i := 1;
      while i <= n do
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "SNF: i = ", i, " of ", n , "\n" );
         fi;
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         # get set of record with pivot-element and position
         pv_set := [ rec( el := S[i][i], p_1 := i, p_2 := i ) ];
         if not PPPL_Equal( S[i][i], One1Loc ) then
            k := i;
            ## find list of elements with smallest p-adic value
            while k <= m do
               l := i;
               while l <= n do
                  if PPPL_Equal( S[k][l], One1Loc ) then
                     pv_set := [ rec( el := S[k][l], p_1 := k, p_2 := l ) ];
                     l := n + 1;
                     k := m + 1;
                  elif PPPL_PadicValue( S[k][l] ) < PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set := [];
                     pv_set[1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  elif PPPL_PadicValue( S[k][l] ) = PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set[Length([pv_set])+1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  else
                     l := l + 1;
                  fi;
               od;
               k := k + 1;
            od;
            ## find element in that set with smallest p-prime-part
            if not PPPL_Equal( pv_set[1]!.el, One1Loc ) and not PPPL_Equal( pv_set[1]!.el, Zero0Loc ) then
               test := pv_set[1];
               for j in [1..Length( pv_set )] do
                  if PPPL_Smaller( PPPL_AbsValue( PPrimePartPolyLoc( pv_set[j]!.el ) ), PPPL_AbsValue( PPrimePartPolyLoc( test!.el ) ) ) then
                     test := pv_set[j];
                  fi;
               od;
               pv_set := [ test ];
            else pv_set := [pv_set[1]];
            fi;
         fi;

         ## get position of pivot element
         pv_1 := pv_set[1]!.p_1;
         pv_2 := pv_set[1]!.p_2;

         ## if there is no pivot then return
         if PPPL_Equal( S[pv_1][pv_2], Zero0Loc ) then
            if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
               Print( "Smith normal form is computed. \n" );
            fi;

            CHECK_SMITHNF_PPOWERPOLY := check;

            return S;
         fi;
         
         ## check that pivot (k,l) is positive
         if PPPL_Smaller( S[pv_1][pv_2], Zero0Loc ) then
            S := DivRowLoc_NonP( pv_1, S, PPPL_AdditiveInverse( One1Loc ) );
         fi;

         ## move pivot to position (i,i)
         if pv_1 <> i or pv_2 <> i then
            S := ExchangeRowsPPPL( i, pv_1, S );
            S := ExchangeColumnsPPPL( i, pv_2, S );
            if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
            elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
            fi;
            pv_1 := i;
            pv_2 := i;
            if InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "pivot = [", pv_1, ",", pv_2, "] \n\n" );
            fi;
         fi;
         
         ## make pivot a p-part element
         if not PPPL_Equal( S[i][i], Zero0Loc ) and not PPPL_Equal( S[i][i], One1Loc ) then
            ## divide row by p-prime-part of pivot
            pprimediv := PPrimePartPolyLoc( S[i][i] );
            S := DivRowLoc_NonP( i, S, pprimediv );
         fi;

         ## emtpy column greater than i
         S := EmptyColumnGreaterLoc_NonP( i, S );

         ## empty row greater than i
         S := EmptyRowGreaterLoc_NonQ( i, S );
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         
         ## initialize next step
         i := i + 1;
      od;

      if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
         Print( "Smith normal form is computed. \n" );
      fi;

      CHECK_SMITHNF_PPOWERPOLY := check;

      return S;
   end);

###############################################################################
##
## SmithNormalFormPPowerPolyTransforms( M_in )
##
## Input: a matrix M_in with p-power-poly-loc entries.
##
## Output: a record rec( norm:=S, rowtrans:=P, coltrans:=Q ) where S is the
##         Smith normal form of M_in, P records the row transformations 
##         performed and Q the column transformations, such that PMQ = S
##
InstallMethod( SmithNormalFormPPowerPolyTransforms,
   "compute Smith normal form with p-power-poly-loc entries", 
   [ IsList ], 
   function( M_in )
      local p, n, m, i, j, k, l, S, M, P, Q, Zero0Loc, One1Loc, eval_pv, 
            eval_test, pprimediv, pv_set, pv_1, pv_2, list, q, Rec, test, T;

      n := Length( M_in[1] );
      m := Length( M_in );

      p := M_in[1][1][2][1];

      Zero0Loc := PPPL_ZeroNC( M_in[1][1] );
      One1Loc := PPPL_OneNC( M_in[1][1] );

      P := IdentityPPowerPolyLocMat( p, m );
      Q := IdentityPPowerPolyLocMat( p, n );

      ## if zero-mat, then return
      if ForAll( M_in, x -> ForAll( x, y -> PPPL_Equal( y, PPPL_Mult( Zero0Loc, y ) ) ) ) then
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "Smith normal form is computed. \n" );
         fi;

         return rec( norm:=M_in, rowtrans:=P, coltrans:=Q );
      fi;

      S := StructuralCopy( M_in );

      if CHECK_SMITHNF_PPOWERPOLY then
         M := StructuralCopy( S );
      fi;

      ## change the matrix to a diagonal matrix
      i := 1;
      while i <= n do
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "SNF: i = ", i, " of ", n , "\n" );
         fi;
         ## check?
         if CHECK_SMITHNF_PPOWERPOLY then
            T := PPPL_MatrixMult( P, PPPL_MatrixMult( M, Q ) );
            if not ForAll( [1..m], x -> ForAll( [1..n], y -> PPPL_Equal( T[x][y], S[x][y] ) ) ) then 
               Print( "P = " );
               PPPL_PrintMat( P );
               Print( "\n " );
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
               Print( "Q = " );
               PPPL_PrintMat( Q );
               Print( "\n " );
               Error("1");
            fi;
         fi;
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "P = " );
            PPPL_PrintMat( P );
            Print( "\n " );
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
            Print( "Q = " );
            PPPL_PrintMat( Q );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         # get set of record with pivot-element and position
         pv_set := [ rec( el := S[i][i], p_1 := i, p_2 := i ) ];
         if not PPPL_Equal( S[i][i], One1Loc ) then
            k := i;
            ## find list of elements with smallest p-adic value
            while k <= m do
               l := i;
               while l <= n do
                  if PPPL_Equal( S[k][l], One1Loc ) then
                     pv_set := [ rec( el := S[k][l], p_1 := k, p_2 := l ) ];
                     l := n + 1;
                     k := m + 1;
                  elif PPPL_PadicValue( S[k][l] ) < PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set := [];
                     pv_set[1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  elif PPPL_PadicValue( S[k][l] ) = PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set[Length([pv_set])+1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  else
                     l := l + 1;
                  fi;
               od;
               k := k + 1;
            od;
            ## find element in that set with smallest p-prime-part
            if not PPPL_Equal( pv_set[1]!.el, One1Loc ) and not PPPL_Equal( pv_set[1]!.el, Zero0Loc ) then
               test := pv_set[1];
               for j in [1..Length( pv_set )] do
                  if PPPL_Smaller( PPPL_AbsValue( PPrimePartPolyLoc( pv_set[j]!.el ) ), PPPL_AbsValue( PPrimePartPolyLoc( test!.el ) ) ) then
                     test := pv_set[j];
                  fi;
               od;
               pv_set := [ test ];
            else pv_set := [pv_set[1]];
            fi;
         fi;

         ## get position of pivot element
         pv_1 := pv_set[1]!.p_1;
         pv_2 := pv_set[1]!.p_2;

         ## if there is no pivot then return
         if PPPL_Equal( S[pv_1][pv_2], Zero0Loc ) then
            if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
               Print( "Smith normal form is computed. \n" );
            fi;

            return rec( norm:=S, rowtrans:=P, coltrans:=Q );
         fi;
         
         ## check that pivot (k,l) is positive
         if PPPL_Smaller( S[pv_1][pv_2], Zero0Loc ) then
            list := DivRowLoc( pv_1, S, P, PPPL_AdditiveInverse( One1Loc ) );
            S := list[1];
            P := list[2];
         fi;

         ## move pivot to position (i,i)
         if pv_1 <> i or pv_2 <> i then
            S := ExchangeRowsPPPL( i, pv_1, S );
            P := ExchangeRowsPPPL( i, pv_1, P );
            S := ExchangeColumnsPPPL( i, pv_2, S );
            Q := ExchangeColumnsPPPL( i, pv_2, Q );
            ## check?
            if CHECK_SMITHNF_PPOWERPOLY then
               T := PPPL_MatrixMult( P, PPPL_MatrixMult( M, Q ) );
               if not ForAll( [1..m], x -> ForAll( [1..n], y -> PPPL_Equal( T[x][y], S[x][y] ) ) ) then 
                  Print( "P = " );
                  PPPL_PrintMat( P );
                  Print( "\n " );
                  Print( "S = " );
                  PPPL_PrintMat( S );
                  Print( "\n " );
                  Print( "Q = " );
                  PPPL_PrintMat( Q );
                  Print( "\n " );
                  Error("3");
               fi;
            fi;
            if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
               Print( "P = " );
               PPPL_PrintMat( P );
               Print( "\n " );
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
               Print( "Q = " );
               PPPL_PrintMat( Q );
               Print( "\n " );
            elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
            fi;
            pv_1 := i;
            pv_2 := i;
            if InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "pivot = [", pv_1, ",", pv_2, "] \n\n" );
            fi;
         fi;
         
         ## make pivot a p-part element
         if not PPPL_Equal( S[i][i], Zero0Loc ) and not PPPL_Equal( S[i][i], One1Loc ) then
            ## divide row by p-prime-part of pivot
            pprimediv := PPrimePartPolyLoc( S[i][i] );
            list := DivRowLoc( i, S, P, pprimediv );
            S := list[1];
            P := list[2];
            ## check?
            if CHECK_SMITHNF_PPOWERPOLY then
               T := PPPL_MatrixMult( P, PPPL_MatrixMult( M, Q ) );
               if not ForAll( [1..m], x -> ForAll( [1..n], y -> PPPL_Equal( T[x][y], S[x][y] ) ) ) then 
                  Print( "P = " );
                  PPPL_PrintMat( P );
                  Print( "\n " );
                  Print( "S = " );
                  PPPL_PrintMat( S );
                  Print( "\n " );
                  Print( "Q = " );
                  PPPL_PrintMat( Q );
                  Print( "\n " );
                  Error("4a");
               fi;
            fi;
         fi;
         ## emtpy column greater than i
         Rec := EmptyColumnGreaterLoc( i, S, P );
         S := Rec.emptyCol;
         P := Rec.emptyColTrans; ## row operations needed
         ## check?
         if CHECK_SMITHNF_PPOWERPOLY then
            T := PPPL_MatrixMult( P, PPPL_MatrixMult( M, Q ) );
            if not ForAll( [1..m], x -> ForAll( [1..n], y -> PPPL_Equal( T[x][y], S[x][y] ) ) ) then 
               Print( "P = " );
               PPPL_PrintMat( P );
               Print( "\n " );
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
               Print( "Q = " );
               PPPL_PrintMat( Q );
               Print( "\n " );
               Error("4b");
            fi;
         fi;

         ## empty row greater than i
         Rec := EmptyRowGreaterLoc( i, S, Q );
         S := Rec.emptyRow;
         Q := Rec.emptyRowTrans; ## column operations needed
         ## check?
         if CHECK_SMITHNF_PPOWERPOLY then
            T := PPPL_MatrixMult( P, PPPL_MatrixMult( M, Q ) );
            if not ForAll( [1..m], x -> ForAll( [1..n], y -> PPPL_Equal( T[x][y], S[x][y] ) ) ) then 
               Print( "P = " );
               PPPL_PrintMat( P );
               Print( "\n " );
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
               Print( "Q = " );
               PPPL_PrintMat( Q );
               Print( "\n " );
               Error("4c");
            fi;
         fi;
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "P = " );
            PPPL_PrintMat( P );
            Print( "\n " );
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
            Print( "Q = " );
            PPPL_PrintMat( Q );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         
         ## initialize next step
         i := i + 1;
      od;

      if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
         Print( "Smith normal form is computed. \n" );
      fi;

      return rec( norm:=S, rowtrans:=P, coltrans:=Q );
   end);

###############################################################################
##
## SmithNormalFormPPowerPolyColTransform( M )
##
## Input: a matrix M_in with p-power-poly-loc entries.
##
## Output: a record rec( norm:=S, coltrans:=Q ) where S is the Smith normal 
##         form of M_in and Q records the column transformations performed, 
##         such that PMQ = S for some invertible matrix P which is NOT 
##         computed in this function.
##
InstallMethod( SmithNormalFormPPowerPolyColTransform, [ IsList ], 
   function( M_in )
      local p, n, m, i, j, k, l, S, Q, Zero0Loc, One1Loc, eval_pv, eval_test, 
            pprimediv, pv_set, pv_1, pv_2, q, Rec, test, check;

      check := CHECK_SMITHNF_PPOWERPOLY;

      if check then
         Print( "Note: no check can be done during the computation of the Smith normal form." );
      fi;

      CHECK_SMITHNF_PPOWERPOLY := false;

      n := Length( M_in[1] );
      m := Length( M_in );

      p := M_in[1][1][2][1];

      Zero0Loc := PPPL_ZeroNC( M_in[1][1] );
      One1Loc := PPPL_OneNC( M_in[1][1] );

      Q := IdentityPPowerPolyLocMat( p, n );

      ## if zero-mat, then return
      if ForAll( M_in, x -> ForAll( x, y -> PPPL_Equal( y, PPPL_Mult( Zero0Loc, y ) ) ) ) then
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "Smith normal form is computed. \n" );
         fi;

         CHECK_SMITHNF_PPOWERPOLY := check;

         return rec( norm:=M_in, coltrans:=Q );
      fi;

      S := StructuralCopy( M_in );

      ## change the matrix to a diagonal matrix
      i := 1;
      while i <= n do
         if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
            Print( "SNF: i = ", i, " of ", n , "\n" );
         fi;
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
            Print( "Q = " );
            PPPL_PrintMat( Q );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         # get set of record with pivot-element and position
         pv_set := [ rec( el := S[i][i], p_1 := i, p_2 := i ) ];
         if not PPPL_Equal( S[i][i], One1Loc ) then
            k := i;
            ## find list of elements with smallest p-adic value
            while k <= m do
               l := i;
               while l <= n do
                  if PPPL_Equal( S[k][l], One1Loc ) then
                     pv_set := [ rec( el := S[k][l], p_1 := k, p_2 := l ) ];
                     l := n + 1;
                     k := m + 1;
                  elif PPPL_PadicValue( S[k][l] ) < PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set := [];
                     pv_set[1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  elif PPPL_PadicValue( S[k][l] ) = PPPL_PadicValue( pv_set[1]!.el ) then
                     pv_set[Length([pv_set])+1] := rec( el := S[k][l], p_1 := k, p_2 := l );
                     l := l + 1;
                  else
                     l := l + 1;
                  fi;
               od;
               k := k + 1;
            od;
            ## find element in that set with smallest p-prime-part
            if not PPPL_Equal( pv_set[1]!.el, One1Loc ) and not PPPL_Equal( pv_set[1]!.el, Zero0Loc ) then
               test := pv_set[1];
               for j in [1..Length( pv_set )] do
                  if PPPL_Smaller( PPPL_AbsValue( PPrimePartPolyLoc( pv_set[j]!.el ) ), PPPL_AbsValue( PPrimePartPolyLoc( test!.el ) ) ) then
                     test := pv_set[j];
                  fi;
               od;
               pv_set := [ test ];
            else pv_set := [pv_set[1]];
            fi;
         fi;

         ## get position of pivot element
         pv_1 := pv_set[1]!.p_1;
         pv_2 := pv_set[1]!.p_2;

         ## if there is no pivot then return
         if PPPL_Equal( S[pv_1][pv_2], Zero0Loc ) then
            if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
               Print( "Smith normal form is computed. \n" );
            fi;

            CHECK_SMITHNF_PPOWERPOLY := check;

            return rec( norm:=S, coltrans:=Q );
         fi;
         
         ## check that pivot (k,l) is positive
         if PPPL_Smaller( S[pv_1][pv_2], Zero0Loc ) then
            S := DivRowLoc_NonP( pv_1, S, PPPL_AdditiveInverse( One1Loc ) );
         fi;

         ## move pivot to position (i,i)
         if pv_1 <> i or pv_2 <> i then
            S := ExchangeRowsPPPL( i, pv_1, S );
            S := ExchangeColumnsPPPL( i, pv_2, S );
            Q := ExchangeColumnsPPPL( i, pv_2, Q );
            if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
               Print( "Q = " );
               PPPL_PrintMat( Q );
               Print( "\n " );
            elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "S = " );
               PPPL_PrintMat( S );
               Print( "\n " );
            fi;
            pv_1 := i;
            pv_2 := i;
            if InfoLevel( InfoSmithPPowerPoly ) >= 2 then
               Print( "pivot = [", pv_1, ",", pv_2, "] \n\n" );
            fi;
         fi;
         
         ## make pivot a p-part element
         if not PPPL_Equal( S[i][i], Zero0Loc ) and not PPPL_Equal( S[i][i], One1Loc ) then
            ## divide row by p-prime-part of pivot
            pprimediv := PPrimePartPolyLoc( S[i][i] );
            S := DivRowLoc_NonP( i, S, pprimediv );
         fi;

         ## emtpy column greater than i
         S := EmptyColumnGreaterLoc_NonP( i, S );

         ## empty row greater than i
         Rec := EmptyRowGreaterLoc( i, S, Q );
         S := Rec.emptyRow;
         Q := Rec.emptyRowTrans; ## column operations needed
         if InfoLevel( InfoSmithPPowerPoly ) >= 3 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
            Print( "Q = " );
            PPPL_PrintMat( Q );
            Print( "\n " );
         elif InfoLevel( InfoSmithPPowerPoly ) >= 2 then
            Print( "S = " );
            PPPL_PrintMat( S );
            Print( "\n " );
         fi;
         
         ## initialize next step
         i := i + 1;
      od;

      if InfoLevel( InfoSmithPPowerPoly ) >= 1 then
         Print( "Smith normal form is computed. \n" );
      fi;

      CHECK_SMITHNF_PPOWERPOLY := check;

      return rec( norm:=S, coltrans:=Q );
   end);

#E Smith.gi . . . . . . . . . . . . . . . . . . . . . . . . . . . .  ends here

[ zur Elbe Produktseite wechseln0.70Quellennavigators  Analyse erneut starten  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge