diff --git a/lib/ffe.gd b/lib/ffe.gd
index b4a37d9835..fd4f65a011 100644
--- a/lib/ffe.gd
+++ b/lib/ffe.gd
@@ -659,18 +659,19 @@ DeclareAttribute( "AsInternalFFE", IsFFE);
##
## <#GAPDoc Label="RootFFE">
##
-##
+##
##
##
## returns a finite field element
-## r whose k-th power is z. If no such element exists
+## r from whose k-th power is z.
+## If no such element exists
## then
## fail is returned.
##
##
## <#/GAPDoc>
##
-DeclareOperation( "RootFFE", [ IsFFE, IsObject ] );
+DeclareOperation( "RootFFE", [ IsObject, IsFFE, IsObject ] );
#############################################################################
diff --git a/lib/ffe.gi b/lib/ffe.gi
index 6e3b6cc53f..6b007a173b 100644
--- a/lib/ffe.gi
+++ b/lib/ffe.gi
@@ -1149,17 +1149,33 @@ end);
##
#M RootFFE( , )
##
-InstallMethod( RootFFE, "use LogFFE",true,[IsFFE,IsPosInt],
-function(z,k)
-local q,e;
- q:=Characteristic(z)^DegreeFFE(z);
+InstallMethod(RootFFE,"use field order",IsCollsElmsX,
+ [IsField,IsFFE,IsPosInt],0,
+function(F,z,k)
+ return RootFFE(Size(F),z,k);
+end);
+
+InstallOtherMethod(RootFFE,"use LogFFE",true,[IsPosInt,IsFFE,IsPosInt],
+function(q,z,k)
+local e,m,p,a;
+ if IsZero(z) or IsOne(z) then return z;fi;
+ m:=q-1;
e:=LogFFE(z,Z(q));
- e:=e/k;
- if Gcd(DenominatorRat(e),q-1)=1 then
- return Z(q)^(e mod (q-1));
- else
- return fail;
+ p:=GcdInt(m,e); #power for subgroup it is in
+ k:=k mod m;
+ a:=GcdInt(m,k); # power for subgroup we want
+ if p mod a<>0 then
+ return fail; # element does not lie in subgroup of a-th powers
fi;
+ # k/a is coprime to order of elts in subgroup and elt is an a-th power
+ a:=(e*(a/k mod (m/p))/a mod m);
+ return Z(q)^a;
+end);
+
+InstallOtherMethod(RootFFE,"without field",true,
+ [IsFFE,IsPosInt],0,
+function(z,k)
+ return RootFFE(Characteristic(z)^DegreeFFE(z),z,k);
end);
diff --git a/lib/zmodnz.gi b/lib/zmodnz.gi
index e344e79f9c..51ea368229 100644
--- a/lib/zmodnz.gi
+++ b/lib/zmodnz.gi
@@ -660,16 +660,28 @@ InstallMethod( LogFFE,
##
#M RootFFE( , ) . . . . . . . . . . . . . . . . . . for `IsZmodpZObj'
##
-InstallMethod(RootFFE,"for modulus rep, using RootMod",true,
- [IsZmodpZObj and IsModulusRep,IsPosInt],
-function( z, k )
+InstallOtherMethod(RootFFE,"for modulus rep, using RootMod",true,
+ [IsPosInt,IsZmodpZObj and IsModulusRep,IsPosInt],
+function( A, z, k )
local r,fam;
fam:=FamilyObj(z);
- r:=RootMod(z![1],k,fam!.Characteristic);
+ if A<>fam!.Characteristic then
+ TryNextMethod();
+ fi;
+ if k=1 or z![1]=0 or z![1]=1 then return z;fi;
+ r:=RootMod(z![1],k,A);
if r=fail then return r;fi;
return ZmodnZObj(fam,r);
end );
+InstallOtherMethod(RootFFE,"for modulus rep",true,
+ [IsZmodpZObj and IsModulusRep,IsPosInt],
+function(z,k)
+ return RootFFE(FamilyObj(z)!.Characteristic,z,k);
+end);
+
+
+
#############################################################################
##
diff --git a/tst/testinstall/ffe.tst b/tst/testinstall/ffe.tst
index 3f73ab0ff1..e67c614c83 100644
--- a/tst/testinstall/ffe.tst
+++ b/tst/testinstall/ffe.tst
@@ -119,6 +119,23 @@ gap> Subfields( GF(81) );
[ GF(3), GF(3^2), GF(3^4) ]
gap> Subfields( GF(2^6) );
[ GF(2), GF(2^2), GF(2^3), GF(2^6) ]
+
+# RootFFE
+gap> Rochambeau:=function(F)
+> local e,i,p,a,r;
+> e:=Elements(F);
+> for i in [1..2*Size(F)] do
+> p:=Set(List(e,x->x^i));
+> for a in e do
+> r:=RootFFE(F,a,i);
+> if a in p and r=fail then Error("-1"); return -1;fi;
+> if r<>fail and a<>r^i then Error("1");return 1;fi;
+> od;
+> od;
+> return 0;
+> end;;
+gap> ForAll(Filtered([1..256],IsPrimePowerInt),x->Rochambeau(GF(x))=0);
+true
gap> STOP_TEST( "ffe.tst", 470000);
#############################################################################