FLINT3.7.0-dev

Square roots, n-th roots and perfect powers

Synopsis#include <flint/fmpz.h>
void fmpz_sqrt(fmpz_t f, const fmpz_t g)source
void fmpz_sqrtrem(fmpz_t f, fmpz_t r, const fmpz_t g)source

Set ff to ⌊g⌋\lfloor \sqrt g \rfloor and rr to g−f2g - f^2, for g≥0g \ge 0. Throw an exception if g<0g < 0. In fmpz_sqrtrem, ff and rr must be distinct objects.

int fmpz_perfect_sqrt(fmpz_t s, const fmpz_t a)source

If aa is a perfect square, sets ss to a≥0\sqrt a \ge 0 and returns 1; otherwise returns 0 and leaves ss undefined. Faster than fmpz_is_square followed by fmpz_sqrt.

int fmpz_is_square(const fmpz_t f)source

Returns whether ff is a perfect square (f≥0f \ge 0).

int fmpz_root(fmpz_t r, const fmpz_t f, slong n)source

Sets rr to the nn-th root of ff rounded towards zero and returns 1 if it is exact and 0 otherwise. Requires n≥1n \ge 1, and f≥0f \ge 0 if nn is even; otherwise an exception is raised.

int fmpz_is_perfect_power(fmpz_t root, const fmpz_t f)source

If f=rkf = r^k for some k≥2k \ge 2, sets root to rr and returns kk; otherwise returns 0. Negative ff are allowed (then kk is odd). The exponent is not necessarily the largest one: 21202^{120} currently gives k=2k = 2, and −2120-2^{120} gives k=3k = 3. By convention 0 and 1 give k=2k = 2 and −1-1 gives k=1k = 1.

fmpz_sqrt and fmpz_sqrtrem compute the integer square root s=⌊g⌋s = \lfloor \sqrt g \rfloor and the remainder g−s2∈[0,2s]g - s^2 \in [0, 2s]. When only squares are of interest, fmpz_perfect_sqrt is the function to use: it decides whether aa is a square and returns the root if it is, rejecting almost all non-squares without computing a root. fmpz_is_square only answers the question. fmpz_root computes nn-th roots rounded towards zero, and fmpz_is_perfect_power decides whether an integer is a nontrivial power.

Square roots#

Inline values use n_sqrt (a floating-point square root with a correction). Large values use FLINT's own square root code (_flint_mpn_sqrtrem) on 64-bit machines:

  • one to four limbs: the hardware square root of a double, a Newton correction and one step of Zimmermann's divide-and-conquer square root, specialised to a two-limb root;
  • up to FLINT_MPN_SQRTREM_NEWTON_CUTOFF limbs (7423 on recent x86-64): the divide-and-conquer ("Karatsuba") square root of Zimmermann [Zim1999], as in GMP, which computes the root of the top half recursively and the remaining limbs by one division, at a cost of a small multiple of a multiplication;
  • above: Newton iteration for 1/α1/\sqrt{\alpha} in fixed-point arithmetic with the Karp–Markstein trick [KM1997], followed by a check of the last limb that certifies the integer part.

The algorithms are described in Square roots. fmpz_sqrt does not form the remainder, which saves a squaring.

Recognising squares#

fmpz_is_square and fmpz_perfect_sqrt first reject a large input unless it is a square modulo 256 (low limb), then modulo the factors of 248−12^{48} - 1 (4095=9⋅5⋅7⋅134095 = 9 \cdot 5 \cdot 7 \cdot 13, 1717, 257257, 9797 and 241241, from a single reduction modulo 248−12^{48} - 1), which lets about one random non-square in 900 through. A surviving candidate is decided by computing the root: for inputs below 21002^{100}, rounding the floating-point root is exact for squares; otherwise the divide-and-conquer root is computed with an early exit as soon as its low bits show that the input cannot be a square. fmpz_perfect_sqrt returns this root, so for a square it costs one root computation, about half the cost of fmpz_is_square followed by fmpz_sqrt.

n-th roots and perfect powers#

fmpz_root uses n_sqrtrem, n_cbrtrem and n_rootrem for inline values and GMP's mpz_root (Newton iteration) otherwise. The root of a negative number is negative for odd nn and an error for even nn.

fmpz_is_perfect_power returns an exponent k≥2k \ge 2 with f=rkf = r^k if there is one. For one-limb values it uses n_is_perfect_power repeatedly, which finds the largest exponent. For larger values it follows the algorithm of GMP's mpz_perfect_power_p: the multiplicities of 2 and of small primes in ff restrict the possible exponents to the divisors of their GCD, and the remaining candidates are tested with mpz_root. The exponent found is then not necessarily the largest: 21202^{120} is reported as the square of 2602^{60}. Apply the function again to the root to obtain a larger exponent.

Example#

Fifty digits of 2\sqrt 2, checked square roots, a cube root of a negative number and a perfect power:

Examplefmpz_roots.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/fmpz.h>

int main(void)
{
    fmpz_t a, s, r;
    int k;

    fmpz_init(a); fmpz_init(s); fmpz_init(r);

    /* 50 digits of sqrt(2): floor(sqrt(2 * 10^98)) */
    fmpz_ui_pow_ui(a, 10, 98);
    fmpz_mul_ui(a, a, 2);
    fmpz_sqrtrem(s, r, a);
    flint_printf("isqrt(2*10^98) = "); fmpz_print(s); flint_printf("\n");
    flint_printf("remainder has %wu bits\n", fmpz_bits(r));

    /* checked square roots */
    fmpz_mul(a, s, s);
    flint_printf("perfect_sqrt(s^2) = %d, ", fmpz_perfect_sqrt(r, a));
    flint_printf("equal to s: %d\n", fmpz_equal(r, s));
    fmpz_add_ui(a, a, 1);
    flint_printf("is_square(s^2 + 1) = %d\n", fmpz_is_square(a));

    /* n-th roots round towards zero */
    fmpz_set_si(a, -1000001);
    k = fmpz_root(r, a, 3);
    flint_printf("root(-1000001, 3) = "); fmpz_print(r);
    flint_printf(", exact: %d\n", k);

    /* perfect powers */
    fmpz_ui_pow_ui(a, 7, 45);
    k = fmpz_is_perfect_power(r, a);
    flint_printf("7^45 = r^%d with r = ", k); fmpz_print(r); flint_printf("\n");

    fmpz_clear(a); fmpz_clear(s); fmpz_clear(r);
    return 0;
}
Output
isqrt(2*10^98) = 14142135623730950488016887242096980785696718753769
remainder has 164 bits
perfect_sqrt(s^2) = 1, equal to s: 1
is_square(s^2 + 1) = 0
root(-1000001, 3) = -100, exact: 0
7^45 = r^45 with r = 7

The remainder 2⋅1098−s22 \cdot 10^{98} - s^2 is at most 2s2s; here both ss and the remainder have 164 bits.

Guides#

References#

  • [Zim1999] P. Zimmermann. Karatsuba square root. INRIA Research Report RR-3805, 1999.
  • [KM1997] A. H. Karp and P. Markstein, "High-precision division and square root", ACM Transactions on Mathematical Software 23:4 (1997), 561–589
Cite this page

The FLINT team, “Square roots, n-th roots and perfect powers (fmpz.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/fmpz/roots.html (generated 2026-11-02).