For starters you can use binary search it is easy to implement let:
x
be your bigint
n
the n-th power you want to check
so you want to check if there is y
such that y^n=x
and for starters assume x>=0
The algorithm is like this:
first compute y
limit ymax
I would use 2^(log2(x)/n)
which is the number with (bits used for x)/n
so ymax^n
has the same amount of bits as x
. So first count the bits of x
and then divide it by n
for (ymax=1,i=1;i<=x;i<<=1) ymax++; ymax=(ymax/n);
now ymax
is the number of bits the y
need to be tested up to
bin search
for(m=1<<ymax,y=0;m;m>>=1)
{
y|=m;
if (integer_pow(y,n)>x) y^=m;
}
return (integer_pow(y,n)==x);
the integer_pow(y,n)
can be done by binary powering or with single for loop for small n
add handling the sign
if (x<0)
then n
must be odd obviously and y<0
so if not return false else negate x
and also the final y
result.
[edit1] Here some simple C++ example:
bool is_root(DWORD &y,DWORD x,DWORD n) // y=x^(1/n) return true if perfect nth root
{
DWORD i,p,m; y=x;
if (n==0) { y=0; return (x==0); }
if (n==1) { y=x; return (x!=0); }
for (i=1,m=1;m<x;i++,m<<=1); m=1<<(i/n); // compute the y limit
for (y=0;m;m>>=1) // bin search through y
{
y|=m;
for (p=y,i=1;i<n;i++) p*=y; // p=y^n
if (p>x) y^=m; // this is xor not power!!!
}
for (p=y,i=1;i<n;i++) p*=y; // p=y^n
return (p==x);
}
so just convert the DWORD
to your bigint datatype as you can see you need only basic arithmetic and bit operations like +,<,==,<<,>>,|,^
(the last is XOR not power)
There are also other possibilities to do this for some inspiration check this (and all sublinks in there):
So for example you can get even rid of the *
operations (like I did in the 16T sqrt sublink presented in one of the sublinks (title: ... one cycle only)) Which is a huge speed up on bigints.