diff --git a/hpcgap/lib/ffeconway.gi b/hpcgap/lib/ffeconway.gi index 473f1ff073..d7c8cb9495 100644 --- a/hpcgap/lib/ffeconway.gi +++ b/hpcgap/lib/ffeconway.gi @@ -1198,91 +1198,21 @@ end); ## #M LogFFE( , ) ## -## 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 ); ############################################################################# ## diff --git a/lib/dlog.gd b/lib/dlog.gd new file mode 100644 index 0000000000..7c607ebce6 --- /dev/null +++ b/lib/dlog.gd @@ -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( , [, ] ) +## +## +## +## +## +## logarithm +## returns a discrete logarithm of x w.r.t. the basis base, +## i. e., an integer l such that base^l = x +## holds, if such a number exists. +## Otherwise fail is returned. +##

+## The order of base or its factorization can be given as m. +## +## +## +DeclareGlobalFunction( "_DLog" ); + +DeclareGlobalFunction( "_DLogShanks" ); diff --git a/lib/dlog.gi b/lib/dlog.gi new file mode 100644 index 0000000000..c43357eb55 --- /dev/null +++ b/lib/dlog.gi @@ -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( , , ) +## +## Let be a multiplicative element of order . +## Return an integer l such that = ^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( , [, ] ) +## +## recursive method, can be the order m of or its factorization +## Let r be the largest prime factor of m, then we use +## ^e = 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 ); diff --git a/lib/ffeconway.gi b/lib/ffeconway.gi index 99fa49ac2c..70729ad1d1 100644 --- a/lib/ffeconway.gi +++ b/lib/ffeconway.gi @@ -1166,93 +1166,23 @@ end); ############################################################################# ## -#M LogFFE( , ) -## -## 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 ); ############################################################################# ## diff --git a/lib/read3.g b/lib/read3.g index 76b4e05c0b..2aa5319200 100644 --- a/lib/read3.g +++ b/lib/read3.g @@ -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" ); diff --git a/lib/read5.g b/lib/read5.g index 07963b6d65..a71bde1a09 100644 --- a/lib/read5.g +++ b/lib/read5.g @@ -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" ); diff --git a/tst/testinstall/dlog.tst b/tst/testinstall/dlog.tst new file mode 100644 index 0000000000..0a09fa31a2 --- /dev/null +++ b/tst/testinstall/dlog.tst @@ -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, 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" );