#include <math.h>
#include "ulong_extras.h"
static const double inv_table[] = {
0.000000000000000, 1.000000000000000, 0.500000000000000,
0.333333333333333, 0.250000000000000, 0.200000000000000,
0.166666666666667, 0.142857142857143, 0.125000000000000,
0.111111111111111, 0.100000000000000, 0.090909090909091,
0.083333333333333, 0.076923076923077, 0.071428571428571,
0.066666666666667, 0.062500000000000, 0.058823529411765,
0.055555555555556, 0.052631578947368, 0.050000000000000,
0.047619047619048, 0.045454545454545, 0.043478260869565,
0.041666666666667, 0.040000000000000, 0.038461538461538,
0.037037037037037, 0.035714285714286, 0.034482758620690,
0.033333333333333, 0.032258064516129, 0.031250000000000,
0.030303030303030, 0.029411764705882, 0.028571428571429,
0.027777777777778, 0.027027027027027, 0.026315789473684,
0.025641025641026, 0.025000000000000, 0.024390243902439,
0.023809523809524, 0.023255813953488, 0.022727272727273,
0.022222222222222, 0.021739130434783, 0.021276595744681,
0.020833333333333, 0.020408163265306, 0.020000000000000,
0.019607843137255, 0.019230769230769, 0.018867924528302,
0.018518518518519, 0.018181818181818, 0.017857142857143,
0.017543859649123, 0.017241379310345, 0.016949152542373,
0.016666666666667, 0.016393442622951, 0.016129032258065,
0.015873015873016, 0.015625000000000 };
static const ulong max_base[] = {
#ifdef FLINT64
UWORD(0), UWORD_MAX, UWORD(4294967296), UWORD(2642245), UWORD(65536),
UWORD(7131), UWORD(1625), UWORD(565), UWORD(256), UWORD(138), UWORD(84),
UWORD(56), UWORD(40), UWORD(30), UWORD(23), UWORD(19), UWORD(16),
UWORD(13), UWORD(11), UWORD(10), UWORD(9), UWORD(8), UWORD(7),
UWORD(6), UWORD(6), UWORD(5), UWORD(5), UWORD(5), UWORD(4), UWORD(4),
UWORD(4), UWORD(4), UWORD(4), UWORD(3), UWORD(3), UWORD(3), UWORD(3),
UWORD(3), UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2),
UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2),
UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2),
UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2)
#else
UWORD(0), UWORD(4294967295), UWORD(65535), UWORD(1625), UWORD(255),
UWORD(84), UWORD(40), UWORD(23), UWORD(15), UWORD(11), UWORD(9),
UWORD(7), UWORD(6), UWORD(5), UWORD(4), UWORD(4), UWORD(3), UWORD(3),
UWORD(3), UWORD(3), UWORD(3), UWORD(2), UWORD(2), UWORD(2), UWORD(2),
UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2), UWORD(2)
#endif
};
ulong
n_root(ulong n, ulong root)
{
ulong x, currval, base, upper_limit;
double dx;
if (!n || !root)
return 0;
if (root == 1)
return n;
if (root == 2)
return n_sqrt(n);
if (root == 3)
return n_cbrt(n);
if (root >= FLINT_BITS || (UWORD(1) << root) > n)
return 1;
upper_limit = max_base[root];
x = n_root_estimate((double)n, root);
currval = n_pow(x, root-1);
dx = n / currval;
dx -= x;
dx *= inv_table[root];
dx = floor(dx);
x += dx;
base = x;
if (base >= upper_limit)
base = upper_limit - 1;
currval = n_pow(base, root);
if (currval == n)
goto final;
while (currval <= n)
{
(base) += 1;
currval = n_pow(base, root);
if (base == upper_limit)
break;
}
while (currval > n)
{
(base) -= 1;
currval = n_pow(base, root);
}
final:
return base;
}