Skip to content

Commit

Permalink
Conform Nemo to new FLINT random struct (#1750)
Browse files Browse the repository at this point in the history
* The GMP-state in a FLINT random context structure will no longer be
  expanded inside the struct, but rather a pointer to it. Hence, make
  Nemo compatible with this.

* Do not use `flint_rand_alloc` and `flint_rand_free` for allocating the
  FLINT random context structure. This is in order to be able to use
  the same code for the new version of FLINT as well as the old version.

* Use the new symbol names for the FLINT random functions if they are
  available. This is checked during the initialization of Nemo, where we
  check for the new symbol `flint_rand_init`.
  • Loading branch information
albinahlback committed May 14, 2024
1 parent 85d161c commit 1c99647
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 50 deletions.
35 changes: 28 additions & 7 deletions src/Nemo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,14 @@ function flint_abort()
error("Problem in the Flint-Subsystem")
end

_ptr = Libdl.dlopen(libflint)
if Libdl.dlsym(_ptr, :flint_rand_init; throw_error = false) !== nothing
const NEW_FLINT = true
else
const NEW_FLINT = false
end
Libdl.dlclose(_ptr)

################################################################################
#
# Debugging tools for allocation tracking
Expand Down Expand Up @@ -525,14 +533,27 @@ end

Random.seed!(a::rand_ctx, s::Nothing=nothing) = Random.seed!(a, rand(UInt128))

flint_randseed!(a::rand_ctx, seed1::UInt, seed2::UInt) =
ccall((:flint_randseed, libflint), Cvoid, (Ptr{Cvoid}, UInt, UInt), a.ptr, seed1, seed2)
if NEW_FLINT
flint_randseed!(a::rand_ctx, seed1::UInt, seed2::UInt) =
ccall((:flint_rand_set_seed, libflint), Cvoid, (Ref{rand_ctx}, UInt, UInt), a, seed1, seed2)

function flint_gmp_randseed!(a::rand_ctx, seed::BigInt)
ccall((:_flint_rand_init_gmp, libflint), Cvoid, (Ptr{Cvoid},), a.ptr)
ccall((:__gmp_randseed, :libgmp), Cvoid, (Ptr{Cvoid}, Ref{BigInt}),
a.ptr, # gmp_state is the first field of a.ptr (cf. flint.h)
seed)
function flint_gmp_randseed!(a::rand_ctx, seed::BigInt)
if a.gmp_state == C_NULL
# gmp_state needs to be initialised
ccall((:_flint_rand_init_gmp_state, libflint), Cvoid, (Ref{rand_ctx},), a)
end
ccall((:__gmp_randseed, :libgmp), Cvoid, (Ptr{Cvoid}, Ref{BigInt}), a.gmp_state, seed)
end
else
flint_randseed!(a::rand_ctx, seed1::UInt, seed2::UInt) =
ccall((:flint_randseed, libflint), Cvoid, (Ref{rand_ctx}, UInt, UInt), a, seed1, seed2)

function flint_gmp_randseed!(a::rand_ctx, seed::BigInt)
ccall((:_flint_rand_init_gmp, libflint), Cvoid, (Ref{rand_ctx},), a)
ccall((:__gmp_randseed, :libgmp), Cvoid, (Ref{rand_ctx}, Ref{BigInt}),
a, # gmp_state is the first field of flint_rand_s
seed)
end
end

################################################################################
Expand Down
12 changes: 6 additions & 6 deletions src/arb/Real.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2108,22 +2108,22 @@ function rand(r::RealField, prec::Int = precision(Balls); randtype::Symbol=:uran

if randtype == :urandom
ccall((:arb_urandom, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int), x, state.ptr, prec)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int), x, state, prec)
elseif randtype == :randtest
ccall((:arb_randtest, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, prec, 30)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int, Int), x, state, prec, 30)
elseif randtype == :randtest_exact
ccall((:arb_randtest_exact, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, prec, 30)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int, Int), x, state, prec, 30)
elseif randtype == :randtest_precise
ccall((:arb_randtest_precise, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, prec, 30)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int, Int), x, state, prec, 30)
elseif randtype == :randtest_wide
ccall((:arb_randtest_wide, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, prec, 30)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int, Int), x, state, prec, 30)
elseif randtype == :randtest_special
ccall((:arb_randtest_special, libflint), Nothing,
(Ref{RealFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, prec, 30)
(Ref{RealFieldElem}, Ref{rand_ctx}, Int, Int), x, state, prec, 30)
else
error("Arb random generation `" * String(randtype) * "` is not defined")
end
Expand Down
12 changes: 6 additions & 6 deletions src/arb/arb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2123,22 +2123,22 @@ function rand(r::ArbField; randtype::Symbol=:urandom)

if randtype == :urandom
ccall((:arb_urandom, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int), x, state.ptr, r.prec)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int), x, state, r.prec)
elseif randtype == :randtest
ccall((:arb_randtest, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, r.prec, 30)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int, Int), x, state, r.prec, 30)
elseif randtype == :randtest_exact
ccall((:arb_randtest_exact, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, r.prec, 30)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int, Int), x, state, r.prec, 30)
elseif randtype == :randtest_precise
ccall((:arb_randtest_precise, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, r.prec, 30)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int, Int), x, state, r.prec, 30)
elseif randtype == :randtest_wide
ccall((:arb_randtest_wide, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, r.prec, 30)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int, Int), x, state, r.prec, 30)
elseif randtype == :randtest_special
ccall((:arb_randtest_special, libflint), Nothing,
(Ref{ArbFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, r.prec, 30)
(Ref{ArbFieldElem}, Ref{rand_ctx}, Int, Int), x, state, r.prec, 30)
else
error("Arb random generation `" * String(randtype) * "` is not defined")
end
Expand Down
12 changes: 6 additions & 6 deletions src/calcium/ca.jl
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,16 @@ function rand(C::CalciumField; depth::Int, bits::Int,

if randtype == :null
ccall((:ca_randtest, libflint), Nothing,
(Ref{CalciumFieldElem}, Ptr{Cvoid}, Int, Int, Ref{CalciumField}),
x, state.ptr, depth, bits, C)
(Ref{CalciumFieldElem}, Ref{rand_ctx}, Int, Int, Ref{CalciumField}),
x, state, depth, bits, C)
elseif randtype == :rational
ccall((:ca_randtest_rational, libflint), Nothing,
(Ref{CalciumFieldElem}, Ptr{Cvoid}, Int, Ref{CalciumField}),
x, state.ptr, bits, C)
(Ref{CalciumFieldElem}, Ref{rand_ctx}, Int, Ref{CalciumField}),
x, state, bits, C)
elseif randtype == :special
ccall((:ca_randtest_special, libflint), Nothing,
(Ref{CalciumFieldElem}, Ptr{Cvoid}, Int, Int, Ref{CalciumField}),
x, state.ptr, depth, bits, C)
(Ref{CalciumFieldElem}, Ref{rand_ctx}, Int, Int, Ref{CalciumField}),
x, state, depth, bits, C)
else
error("randtype not defined")
end
Expand Down
6 changes: 3 additions & 3 deletions src/calcium/qqbar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,14 @@ function rand(R::QQBarField; degree::Int, bits::Int,

if randtype == :null
ccall((:qqbar_randtest, libflint), Nothing,
(Ref{QQBarFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, degree, bits)
(Ref{QQBarFieldElem}, Ref{rand_ctx}, Int, Int), x, state, degree, bits)
elseif randtype == :real
ccall((:qqbar_randtest_real, libflint), Nothing,
(Ref{QQBarFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, degree, bits)
(Ref{QQBarFieldElem}, Ref{rand_ctx}, Int, Int), x, state, degree, bits)
elseif randtype == :nonreal
degree < 2 && error("nonreal requires degree >= 2")
ccall((:qqbar_randtest_nonreal, libflint), Nothing,
(Ref{QQBarFieldElem}, Ptr{Cvoid}, Int, Int), x, state.ptr, degree, bits)
(Ref{QQBarFieldElem}, Ref{rand_ctx}, Int, Int), x, state, degree, bits)
else
error("randtype not defined")
end
Expand Down
46 changes: 32 additions & 14 deletions src/flint/FlintTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6657,22 +6657,40 @@ end
#
################################################################################

mutable struct rand_ctx
ptr::Ptr{Cvoid}
if NEW_FLINT
mutable struct rand_ctx
gmp_state::Ptr{Cvoid}
randval::UInt
randval2::UInt

function rand_ctx()
a = new()
ccall((:flint_rand_init, libflint), Cvoid, (Ref{rand_ctx},), a)
finalizer(_rand_ctx_clear_fn, a)
return a
end
end

function rand_ctx()
z = new()
z.ptr = ccall((:flint_rand_alloc, libflint), Ptr{Cvoid}, ( ))
ccall((:flint_randinit, libflint), Cvoid, (Ptr{Cvoid}, ), z.ptr)
finalizer(_rand_ctx_clear_fn, z)
return z
end
end
function _rand_ctx_clear_fn(a::rand_ctx)
ccall((:flint_rand_clear, libflint), Cvoid, (Ref{rand_ctx},), a)
nothing
end
else
mutable struct rand_ctx
data::NTuple{56, Int8}

function rand_ctx()
a = new()
ccall((:flint_randinit, libflint), Cvoid, (Ref{rand_ctx},), a)
finalizer(_rand_ctx_clear_fn, a)
return a
end
end

function _rand_ctx_clear_fn(a::rand_ctx)
ccall((:flint_randclear, libflint), Cvoid, (Ptr{Cvoid}, ), a.ptr)
ccall((:flint_rand_free, libflint), Cvoid, (Ptr{Cvoid}, ), a.ptr)
nothing
function _rand_ctx_clear_fn(a::rand_ctx)
ccall((:flint_randclear, libflint), Cvoid, (Ref{rand_ctx},), a)
nothing
end
end

################################################################################
Expand Down
4 changes: 2 additions & 2 deletions src/flint/fmpq.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1155,8 +1155,8 @@ denominator can be smaller than $b$ bits.
function rand_bits(::QQField, b::Int)
b > 0 || throw(DomainError(b, "Bit count must be positive"))
z = QQFieldElem()
ccall((:fmpq_randbits, libflint), Nothing, (Ref{QQFieldElem}, Ptr{Cvoid}, Int),
z, _flint_rand_states[Threads.threadid()].ptr, b)
ccall((:fmpq_randbits, libflint), Nothing, (Ref{QQFieldElem}, Ref{rand_ctx}, Int),
z, _flint_rand_states[Threads.threadid()], b)
return z
end

Expand Down
12 changes: 6 additions & 6 deletions src/flint/fmpz.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1499,8 +1499,8 @@ function _ecm(a::ZZRingElem, B1::UInt, B2::UInt, ncrv::UInt,
rnd = _flint_rand_states[Threads.threadid()])
f = ZZRingElem()
r = ccall((:fmpz_factor_ecm, libflint), Int32,
(Ref{ZZRingElem}, UInt, UInt, UInt, Ptr{Cvoid}, Ref{ZZRingElem}),
f, ncrv, B1, B2, rnd.ptr, a)
(Ref{ZZRingElem}, UInt, UInt, UInt, Ref{rand_ctx}, Ref{ZZRingElem}),
f, ncrv, B1, B2, rnd, a)
return r, f
end

Expand Down Expand Up @@ -2741,8 +2741,8 @@ Return a random signed integer whose absolute value has $b$ bits.
function rand_bits(::ZZRing, b::Int)
b >= 0 || throw(DomainError(b, "Bit count must be non-negative"))
z = ZZRingElem()
ccall((:fmpz_randbits, libflint), Nothing,(Ref{ZZRingElem}, Ptr{Cvoid}, Int),
z, _flint_rand_states[Threads.threadid()].ptr, b)
ccall((:fmpz_randbits, libflint), Nothing,(Ref{ZZRingElem}, Ref{rand_ctx}, Int),
z, _flint_rand_states[Threads.threadid()], b)
return z
end

Expand All @@ -2756,8 +2756,8 @@ function rand_bits_prime(::ZZRing, n::Int, proved::Bool = true)
n < 2 && throw(DomainError(n, "No primes with that many bits"))
z = ZZRingElem()
ccall((:fmpz_randprime, libflint), Nothing,
(Ref{ZZRingElem}, Ptr{Cvoid}, Int, Cint),
z, _flint_rand_states[Threads.threadid()].ptr, n, Cint(proved))
(Ref{ZZRingElem}, Ref{rand_ctx}, Int, Cint),
z, _flint_rand_states[Threads.threadid()], n, Cint(proved))
return z
end

Expand Down

0 comments on commit 1c99647

Please sign in to comment.