diff --git a/docs/src/integer.md b/docs/src/integer.md index a2410f2a33..be0afcea07 100644 --- a/docs/src/integer.md +++ b/docs/src/integer.md @@ -285,14 +285,20 @@ isqrtrem(::fmpz) root(::fmpz, ::Int) ``` +```@docs +iroot(::fmpz, ::Int) +``` + **Examples** ```julia a = ZZ(13) +b = ZZ(27) -b = isqrt(a) +c = isqrt(a) s, r = isqrtrem(a) -c = root(a, 3) +d = iroot(a, 3) +k = root(b, 3; check=true) ``` ### Number theoretic functionality diff --git a/src/flint/fmpz.jl b/src/flint/fmpz.jl index 86da30b5f0..8500cf1c9b 100644 --- a/src/flint/fmpz.jl +++ b/src/flint/fmpz.jl @@ -43,7 +43,7 @@ export fmpz, FlintZZ, FlintIntegerRing, parent, show, convert, hash, euler_phi, fibonacci, moebius_mu, primorial, rising_factorial, number_of_partitions, canonical_unit, isunit, isequal, addeq!, mul!, issquare, square_root, issquare_with_square_root, next_prime, - iszero, rand, rand_bits, binomial, factorial, rand_bits_prime + iszero, rand, rand_bits, binomial, factorial, rand_bits_prime, iroot ############################################################################### # @@ -1132,16 +1132,36 @@ function Base.sqrt(x::fmpz) end @doc Markdown.doc""" - root(x::fmpz, n::Int) + root(x::fmpz, n::Int; check::Bool=true) -Return the floor of the $n$-the root of $x$. We require $n > 0$ and that -$x \geq 0$ if $n$ is even. +Return the $n$-the root of $x$. We require $n > 0$ and that +$x \geq 0$ if $n$ is even. By default the function tests whether the input was +a perfect $n$-th power and if not raises an exception. If `check=false` this +check is omitted. """ -function root(x::fmpz, n::Int) +function root(x::fmpz, n::Int; check::Bool=true) x < 0 && iseven(n) && throw(DomainError((x, n), "Argument `x` must be positive if exponent `n` is even")) n <= 0 && throw(DomainError(n, "Exponent must be positive")) z = fmpz() - ccall((:fmpz_root, libflint), Nothing, + res = ccall((:fmpz_root, libflint), Bool, + (Ref{fmpz}, Ref{fmpz}, Int), z, x, n) +#= Check disabled until flint-2.9 comes out + check && !res && error("Not a perfect n-th power (n = $n)") +=# + return z +end + +@doc Markdown.doc""" + iroot(x::fmpz, n::Int) + +Return the integer truncation of the $n$-the root of $x$ (round towards zero). +We require $n > 0$ and that $x \geq 0$ if $n$ is even. +""" +function iroot(x::fmpz, n::Int) + x < 0 && iseven(n) && throw(DomainError((x, n), "Argument `x` must be positive if exponent `n` is even")) + n <= 0 && throw(DomainError(n, "Exponent must be positive")) + z = fmpz() + ccall((:fmpz_root, libflint), Bool, (Ref{fmpz}, Ref{fmpz}, Int), z, x, n) return z end diff --git a/test/flint/fmpz-test.jl b/test/flint/fmpz-test.jl index 3024f519cd..6311192eb9 100644 --- a/test/flint/fmpz-test.jl +++ b/test/flint/fmpz-test.jl @@ -510,10 +510,23 @@ end @test_throws DomainError isqrtrem(-fmpz(12)) @test root(fmpz(1000), 3) == 10 + @test root(-fmpz(27), 3) == -3 + @test root(fmpz(27), 3; check=true) == 3 @test_throws DomainError root(-fmpz(1000), 4) - @test_throws DomainError root(fmpz(1000), -3) + +#= Disabled until Flint-2.9 comes out + @test_throws ErrorException root(fmpz(1100), 3; check=true) + @test_throws ErrorException root(-fmpz(40), 3; check=true) +=# + + @test iroot(fmpz(1000), 3) == 10 + @test iroot(fmpz(1100), 3) == 10 + @test iroot(-fmpz(40), 3) == -3 + + @test_throws DomainError iroot(-fmpz(1000), 4) + @test_throws DomainError iroot(fmpz(1000), -3) end @testset "fmpz.extended_gcd" begin