Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
- move the code from StandardFF to new files `lib/dlog.gd`, `lib/dlog.gi`,
  independent of the record `FFECONWAY`
- call the functions `_DLog` and `_DLogShanks`,
  since StandardFF currently wants to bind global variables `_DLog` and
  `_DLogShanks`
- add a few tests
  • Loading branch information
ThomasBreuer committed Sep 18, 2023
1 parent 52269fd commit a0136f4
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 148 deletions.
76 changes: 3 additions & 73 deletions hpcgap/lib/ffeconway.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1198,91 +1198,21 @@ end);
##
#M LogFFE( <x>, <base> )
##
## The code related to `LogFFE` was copied from the StandardFF package.
##
FFECONWAY.DLogShanks:= function(base, x, r)
local rr, baby, ord, giant, t, pos, i, j;
rr := RootInt(r, 2);
baby := [One(base)];
if x = baby[1] then
return 0;
fi;
for i in [1..rr-1] do
baby[i+1] := baby[i]*base;
if x = baby[i+1] then
return i;
fi;
od;
giant := baby[rr]*base;
ord := [0..rr-1];
SortParallel(baby, ord);
t := x;
for j in [1..QuoInt(r, rr)+1] do
t := t*giant;
pos := PositionSet(baby, t);
if IsInt(pos) then
return (ord[pos] - j * rr) mod r;
fi;
od;
return fail;
end;

# recursive method, m can be order of base or its factorization
# Let r be the largest prime factor of m, then we use
# base^e = x with e = a + b*r where 0 <= a < r and
# 0 <= b < m/r, and compute a with DLogShanks and b by
# recursion.
FFECONWAY.DLog:= function(base, x, m...)
local r, mm, mp, a, b;
if Length(m) = 0 then
m := Order(base);
else
m := m[1];
fi;
if not IsList(m) then
m := Factors(m);
fi;
if Length(m) = 1 then
return FFECONWAY.DLogShanks(base, x, m[1]);
fi;
r := m[Length(m)];
mm := m{[1..Length(m)-1]};
mp := Product(mm);
a := FFECONWAY.DLogShanks(base^mp, x^mp, r);
b := FFECONWAY.DLog(base^r, x/(base^a), mm);
return a + b*r;
end;

FFECONWAY.DoLogFFE:= function(x, base)
local ob, o, e;
ob := Order(base);
o := Order(x);
if ob mod o <> 0 then
return fail;
fi;
if ob <> o then
e := ob/o;
base := base^e;
else
e := 1;
fi;
return FFECONWAY.DLog(base, x, o) * e;
end;

InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsCoeffsModConwayPolRep],
FFECONWAY.DoLogFFE );
DoDLog );

InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsInternalRep, IsFFE and IsCoeffsModConwayPolRep],
FFECONWAY.DoLogFFE );
DoDLog );

InstallMethod( LogFFE,
IsIdenticalObj,
[ IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsInternalRep],
FFECONWAY.DoLogFFE );
DoDLog );

#############################################################################
##
Expand Down
35 changes: 35 additions & 0 deletions lib/dlog.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#############################################################################
##
## This file is part of GAP, a system for computational discrete algebra.
## This file's authors include Frank Lübeck.
##
## Copyright of GAP belongs to its developers, whose names are too numerous
## to list here. Please refer to the COPYRIGHT file for details.
##
## SPDX-License-Identifier: GPL-2.0-or-later
##
## This file declares operations related to discrete logarithms.
##


#############################################################################
##
#F _DLog( <base>, <x>[, <m>] )
##
## <ManSection>
## <Func Name="_DLog" Arg='base, x[, m]'/>
##
## <Description>
## <Index Subkey="discrete">logarithm</Index>
## returns a discrete logarithm of <A>x</A> w.r.t. the basis <A>base</A>,
## i. e., an integer <M>l</M> such that <M><A>base</A>^l = <A>x</A></M>
## holds, if such a number exists.
## Otherwise <K>fail</K> is returned.
## <P/>
## The order of <A>base</A> or its factorization can be given as <A>m</A>.
## </Description>
## </ManSection>
##
DeclareGlobalFunction( "_DLog" );

DeclareGlobalFunction( "_DLogShanks" );
108 changes: 108 additions & 0 deletions lib/dlog.gi
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#############################################################################
##
## This file is part of GAP, a system for computational discrete algebra.
## This file's authors include Frank Lübeck.
##
## Copyright of GAP belongs to its developers, whose names are too numerous
## to list here. Please refer to the COPYRIGHT file for details.
##
## SPDX-License-Identifier: GPL-2.0-or-later
##
## This file contains methods related to discrete logarithms.
## The code was copied from the StandardFF package.
##


#############################################################################
##
#F _DLogShanks( <base>, <x>, <r> )
##
## Let <base> be a multiplicative element of order <r>.
## Return an integer l such that <x> = <base>^l holds,
## or 'fail' if no such l exists.
##
InstallGlobalFunction( _DLogShanks, function(base, x, r)
local rr, baby, ord, giant, t, pos, i, j;
rr := RootInt(r, 2);
baby := [One(base)];
if x = baby[1] then
return 0;
fi;
for i in [1..rr-1] do
baby[i+1] := baby[i]*base;
if x = baby[i+1] then
return i;
fi;
od;
giant := baby[rr]*base;
ord := [0..rr-1];
SortParallel(baby, ord);
t := x;
for j in [1..QuoInt(r, rr)+1] do
t := t*giant;
pos := PositionSet(baby, t);
if IsInt(pos) then
return (ord[pos] - j * rr) mod r;
fi;
od;
return fail;
end );


#############################################################################
##
#F _DLog( <base>, <x>[, <m>] )
##
## recursive method, <m> can be the order m of <base> or its factorization
## Let r be the largest prime factor of m, then we use
## <base>^e = <x> with e = a + b*r where 0 <= a < r and
## 0 <= b < m/r,
## and compute a with _DLogShanks and b by recursion.
##
InstallGlobalFunction( _DLog, function(base, x, m...)
local r, mm, mp, a, b;
if Length(m) = 0 then
m := Order(base);
else
m := m[1];
fi;
if not IsList(m) then
m := Factors(m);
fi;
if Length(m) = 1 then
return _DLogShanks(base, x, m[1]);
fi;
r := m[Length(m)];
mm := m{[1..Length(m)-1]};
mp := Product(mm);
a := _DLogShanks(base^mp, x^mp, r);
if a = fail then
return fail;
fi;
b := _DLog(base^r, x/(base^a), mm);
if b = fail then
return fail;
fi;
return a + b*r;
end );


#############################################################################
##
## used as method for LogFFE
##
BindGlobal( "DoDLog", function(x, base)
local ob, o, e;
ob := Order(base);
o := Order(x);
if ob mod o <> 0 then
return fail;
fi;
if ob <> o then
e := ob/o;
base := base^e;
else
e := 1;
fi;
return _DLog(base, x, o) * e;
end );
80 changes: 5 additions & 75 deletions lib/ffeconway.gi
Original file line number Diff line number Diff line change
Expand Up @@ -1166,93 +1166,23 @@ end);

#############################################################################
##
#M LogFFE( <x>, <base> )
##
## The code related to `LogFFE` was copied from the StandardFF package.
##
FFECONWAY.DLogShanks:= function(base, x, r)
local rr, baby, ord, giant, t, pos, i, j;
rr := RootInt(r, 2);
baby := [One(base)];
if x = baby[1] then
return 0;
fi;
for i in [1..rr-1] do
baby[i+1] := baby[i]*base;
if x = baby[i+1] then
return i;
fi;
od;
giant := baby[rr]*base;
ord := [0..rr-1];
SortParallel(baby, ord);
t := x;
for j in [1..QuoInt(r, rr)+1] do
t := t*giant;
pos := PositionSet(baby, t);
if IsInt(pos) then
return (ord[pos] - j * rr) mod r;
fi;
od;
return fail;
end;

# recursive method, m can be order of base or its factorization
# Let r be the largest prime factor of m, then we use
# base^e = x with e = a + b*r where 0 <= a < r and
# 0 <= b < m/r, and compute a with DLogShanks and b by
# recursion.
FFECONWAY.DLog:= function(base, x, m...)
local r, mm, mp, a, b;
if Length(m) = 0 then
m := Order(base);
else
m := m[1];
fi;
if not IsList(m) then
m := Factors(m);
fi;
if Length(m) = 1 then
return FFECONWAY.DLogShanks(base, x, m[1]);
fi;
r := m[Length(m)];
mm := m{[1..Length(m)-1]};
mp := Product(mm);
a := FFECONWAY.DLogShanks(base^mp, x^mp, r);
b := FFECONWAY.DLog(base^r, x/(base^a), mm);
return a + b*r;
end;

FFECONWAY.DoLogFFE:= function(x, base)
local ob, o, e;
ob := Order(base);
o := Order(x);
if ob mod o <> 0 then
return fail;
fi;
if ob <> o then
e := ob/o;
base := base^e;
else
e := 1;
fi;
return FFECONWAY.DLog(base, x, o) * e;
end;
#M LogFFE
##

InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsCoeffsModConwayPolRep],
FFECONWAY.DoLogFFE );
DoDLog );

InstallMethod( LogFFE,
IsIdenticalObj,
[IsFFE and IsInternalRep, IsFFE and IsCoeffsModConwayPolRep],
FFECONWAY.DoLogFFE );
DoDLog );

InstallMethod( LogFFE,
IsIdenticalObj,
[ IsFFE and IsCoeffsModConwayPolRep, IsFFE and IsInternalRep],
FFECONWAY.DoLogFFE );
DoDLog );

#############################################################################
##
Expand Down
1 change: 1 addition & 0 deletions lib/read3.g
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ ReadLib( "lierep.gd" );
ReadLib( "integer.gd" );
ReadLib( "gaussian.gd" );
ReadLib( "numtheor.gd" );
ReadLib( "dlog.gd" );
ReadLib( "primality.gd");
ReadLib( "contfrac.gd" );
ReadLib( "ringsc.gd" );
Expand Down
1 change: 1 addition & 0 deletions lib/read5.g
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ReadLib( "algrep.gi" );
ReadLib( "lierep.gi" );

ReadLib( "numtheor.gi" );
ReadLib( "dlog.gi" );
ReadLib( "primality.gi");
ReadLib( "contfrac.gi" );
ReadLib( "ringsc.gi" );
Expand Down
22 changes: 22 additions & 0 deletions tst/testinstall/dlog.tst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#@local R, o
gap> START_TEST( "dlog.tst" );

# _DLog
gap> R:= Integers mod 71;; o:= One( R );;
gap> _DLog( 2*o, 4*o );
2
gap> R:= Integers mod 17;; o:= One( R );;
gap> _DLog( 2*o, 3*o );
fail
gap> R:= Integers mod 9;; o:= One( R );;
gap> _DLog( 2*o, 4*o );
2
gap> _DLog( 3*o, 4*o );
Error, <obj> is not invertible
gap> ForAll( Primes, p -> p = 2 or _DLog( Z(p^2), Z(p^2)^2 ) = 2 );
true
gap> ForAll( Primes, p -> p = 2 or _DLog( Z(p^2)^2, Z(p^2) ) = fail );
true

#
gap> STOP_TEST( "dlog.tst" );

0 comments on commit a0136f4

Please sign in to comment.