Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce low-level analogs for Flint structs #1889

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
255 changes: 255 additions & 0 deletions src/flint/CTypes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
###############################################################################
#
# Flint C types
#
###############################################################################

module Flint

#
# C types (names provided to ease automatic conversion of struct definitions)
#
const int = Cint
const char = Cchar

#
# from flint.h
#
const ulong = Culong
const slong = Clong

const flint_bitcnt_t = ulong
const nn_ptr = Ptr{ulong}

const fmpz = Clong

const fmpz_t = Ptr{fmpz}

struct fmpq
num::fmpz
den::fmpz
end

const fmpq_t = Ptr{fmpq}

struct nmod_t
n::ulong
ninv::ulong
norm::flint_bitcnt_t
end

#
# from limb_types.h
#

const FLINT_MAX_FACTORS_IN_LIMB = 15

struct n_factor_t
num::int
exp::NTuple{FLINT_MAX_FACTORS_IN_LIMB, int}
p::NTuple{FLINT_MAX_FACTORS_IN_LIMB, ulong}
end

struct n_primes_struct
small_i::slong
small_num::slong
small_primes::Ptr{Cuint}

sieve_a::ulong
sieve_b::ulong
sieve_i::slong
sieve_num::slong
sieve::Ptr{char}
end

#
# from fmpz_types.h
#

struct zz_struct
alloc::int
size::int
ptr::nn_ptr
end

const zz_ptr = Ptr{zz_struct}

struct fmpz_factor_struct
sign::int
p::Ptr{fmpz}
exp::Ptr{ulong}
alloc::slong
num::slong
end

struct fmpz_preinvn_struct
dinv::nn_ptr
n::slong
norm::flint_bitcnt_t
end

struct fmpz_poly_struct
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things I have no thought through yet: which of these should we do (and why):

  1. fmpz_poly_struct a struct, and ZZPolyRingElem a mutable struct with finalizer (this is what we have now)
  2. fmpz_poly_struct a mutable struct, with finalizer, and ZZPolyRingElem a struct
  3. both mutable struct (and one of them has finalizer)

I did 1 because this needed the least number of changes and this PR is just an incomplete PoC

Pro for 2 would be that several high-level Julia structs wrap the same underlying FLINT structs (e.g. fmpz_poly_struct is wrapped by ZZPolyRingElem, ZZAbsPowerSeriesRingElem and ZZRelPowerSeriesRingElem) and so they could use the same finalizer (well technically they already could do that now).

Anyway, I did not try methods 2 and 3, they might not work at all for fundamental reasons, or maybe method 1 (what this PR has now) is fundamentally flawed -- gotta find some time to experiment more. But if someone else has insights, please share them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would find it most intuitive if the finalized is attached to the fmpz_poly_struct as that is the most fundamental data structure that occupies foreign memory. And as you pointed out, that removes some duplication between multiple Nemo types using the same flint primitives

coeffs::Ptr{fmpz}
alloc::slong
length::slong
end

struct fmpz_poly_factor_struct
c::fmpz
p::Ptr{fmpz_poly_struct}
exp::Ptr{slong}
num::slong
alloc::slong
end

struct fmpz_mat_struct
entries::Ptr{fmpz}
r::slong
c::slong
rows::Ptr{Ptr{fmpz}}
end

struct fmpz_poly_mat_struct
entries::Ptr{fmpz_poly_struct}
r::slong
c::slong
rows::Ptr{Ptr{fmpz_poly_struct}}
end

struct fmpz_mpoly_struct
coeffs::Ptr{fmpz}
exps::Ptr{ulong}
alloc::slong
length::slong
bits::flint_bitcnt_t
end

struct fmpz_mpoly_factor_struct
constant::fmpz_t
constant_den::fmpz_t
poly::Ptr{fmpz_mpoly_struct}
exp::Ptr{fmpz}
num::slong
alloc::slong
end

struct fmpz_poly_q_struct
num::Ptr{fmpz_poly_struct}
den::Ptr{fmpz_poly_struct}
end

struct fmpz_mpoly_q_struct
num::fmpz_mpoly_struct
den::fmpz_mpoly_struct
end

struct fmpzi_struct
a::fmpz
b::fmpz
end


#
# from nmod_types.h
#
struct nmod_mat_struct
entries::Ptr{ulong}
r::slong
c::slong
rows::Ptr{Ptr{ulong}}
mod::nmod_t
end

struct nmod_poly_struct
coeffs::nn_ptr
alloc::slong
length::slong
mod::nmod_t
end

const nmod_poly_t = Ptr{nmod_poly_struct}

struct nmod_poly_factor_struct
p::Ptr{nmod_poly_struct}
exp::Ptr{slong}
num::slong
alloc::slong
end

struct nmod_poly_mat_struct
entries::Ptr{nmod_poly_struct}
r::slong
c::slong
rows::Ptr{Ptr{nmod_poly_struct}}
modulus::ulong
end

struct nmod_mpoly_struct
coeffs::Ptr{ulong}
exps::Ptr{ulong}
length::slong
bits::flint_bitcnt_t
coeffs_alloc::slong
exps_alloc::slong
end

struct nmod_mpoly_factor_struct
constant::ulong
poly::Ptr{nmod_mpoly_struct}
exp::Ptr{fmpz}
num::slong
alloc::slong
end

#
# from fq_nmod_types.h
#

const fq_nmod_struct = nmod_poly_struct

struct fq_nmod_ctx_struct
mod::nmod_t

sparse_modulus::int
is_conway::int

a::Ptr{ulong}
j::Ptr{slong}
len::slong

modulus::nmod_poly_t
inv::nmod_poly_t

var::Ptr{char}
end

struct fq_nmod_mat_struct
entries::Ptr{fq_nmod_struct}
r::slong
c::slong
rows::Ptr{Ptr{fq_nmod_struct}}
end

struct fq_nmod_poly_struct
coeffs::Ptr{fq_nmod_struct}
alloc::slong
length::slong
end

struct fq_nmod_poly_factor_struct
poly::Ptr{fq_nmod_poly_struct}
exp::Ptr{slong}
num::slong
alloc::slong
end

struct fq_nmod_mpoly_struct
coeffs::Ptr{ulong}
exps::Ptr{ulong}
length::slong
bits::flint_bitcnt_t
coeffs_alloc::slong
exps_alloc::slong
end

end
33 changes: 13 additions & 20 deletions src/flint/FlintTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

const _err_dim_negative = ErrorException("Dimensions must be non-negative")

include("CTypes.jl")

###############################################################################
#
# ZZRing / ZZRingElem
Expand Down Expand Up @@ -42,7 +44,7 @@ integer_ring() = ZZRing()

@doc zz_ring_doc
mutable struct ZZRingElem <: RingElem
d::Int
d::Flint.fmpz
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
d::Flint.fmpz
data::Flint.fmpz

consistency with the other structs


function ZZRingElem()
z = new()
Expand Down Expand Up @@ -92,11 +94,7 @@ function _fmpz_clear_fn(a::ZZRingElem)
end

mutable struct fmpz_factor
sign::Cint
p::Ptr{Nothing} # Array of fmpz_struct's
exp::Ptr{UInt}
alloc::Int
num::Int
data::Flint.fmpz_factor_struct

function fmpz_factor()
z = new()
Expand Down Expand Up @@ -241,9 +239,7 @@ end
const FmpzPolyID = CacheDictType{Symbol, ZZPolyRing}()

mutable struct ZZPolyRingElem <: PolyRingElem{ZZRingElem}
coeffs::Ptr{Nothing}
alloc::Int
length::Int
data::Flint.fmpz_poly_struct
parent::ZZPolyRing

function ZZPolyRingElem()
Expand Down Expand Up @@ -291,11 +287,7 @@ function _fmpz_poly_clear_fn(a::ZZPolyRingElem)
end

mutable struct fmpz_poly_factor
d::Int # ZZRingElem
p::Ptr{ZZPolyRingElem} # array of flint fmpz_poly_struct's
exp::Ptr{Int}
num::Int
alloc::Int
data::Flint.fmpz_poly_factor_struct

function fmpz_poly_factor()
z = new()
Expand Down Expand Up @@ -591,12 +583,7 @@ end
const NmodPolyRingID = CacheDictType{Tuple{zzModRing, Symbol}, zzModPolyRing}()

mutable struct zzModPolyRingElem <: PolyRingElem{zzModRingElem}
coeffs::Ptr{Nothing}
alloc::Int
length::Int
mod_n::UInt
mod_ninv::UInt
mod_norm::UInt
data::Flint.nmod_poly_struct
parent::zzModPolyRing

function zzModPolyRingElem(n::UInt)
Expand Down Expand Up @@ -736,6 +723,8 @@ mutable struct fpPolyRingElem <: PolyRingElem{fpFieldElem}
mod_n::UInt
mod_ninv::UInt
mod_norm::UInt
# end of flint struct

parent::fpPolyRing

function fpPolyRingElem(n::UInt)
Expand Down Expand Up @@ -3453,6 +3442,8 @@ mutable struct fpRelPowerSeriesRingElem <: RelPowerSeriesRingElem{fpFieldElem}
mod_n::UInt
mod_ninv::UInt
mod_norm::UInt
# end of flint struct

prec::Int
val::Int
parent::fpRelPowerSeriesRing
Expand Down Expand Up @@ -3554,6 +3545,8 @@ mutable struct zzModRelPowerSeriesRingElem <: RelPowerSeriesRingElem{zzModRingEl
mod_n::UInt
mod_ninv::UInt
mod_norm::UInt
# end of flint struct

prec::Int
val::Int
parent::zzModRelPowerSeriesRing
Expand Down
4 changes: 2 additions & 2 deletions src/flint/fmpq_poly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -706,10 +706,10 @@ for (factor_fn, factor_fn_inner, flint_fn) in
ccall((:fmpz_poly_factor_get_fmpz, libflint), Nothing,
(Ref{ZZRingElem}, Ref{fmpz_poly_factor}), z, fac)
f = ZZPolyRingElem()
for i in 1:fac.num
for i in 1:fac.data.num
ccall((:fmpz_poly_factor_get_fmpz_poly, libflint), Nothing,
(Ref{ZZPolyRingElem}, Ref{fmpz_poly_factor}, Int), f, fac, i - 1)
e = unsafe_load(fac.exp, i)
e = unsafe_load(fac.data.exp, i)
res[parent(x)(f)] = e
end
return res, QQFieldElem(z, denominator(x))
Expand Down
6 changes: 3 additions & 3 deletions src/flint/nmod_poly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ end

function _factor(x::zzModPolyRingElem)
!is_prime(modulus(x)) && error("Modulus not prime in factor")
fac = nmod_poly_factor(x.mod_n)
fac = nmod_poly_factor(x.data.mod.n)
z = ccall((:nmod_poly_factor, libflint), UInt,
(Ref{nmod_poly_factor}, Ref{zzModPolyRingElem}), fac, x)
res = Dict{zzModPolyRingElem,Int}()
Expand All @@ -729,7 +729,7 @@ function factor_squarefree(x::zzModPolyRingElem)
end

function _factor_squarefree(x::zzModPolyRingElem)
fac = nmod_poly_factor(x.mod_n)
fac = nmod_poly_factor(x.data.mod.n)
ccall((:nmod_poly_factor_squarefree, libflint), UInt,
(Ref{nmod_poly_factor}, Ref{zzModPolyRingElem}), fac, x)
res = Dict{zzModPolyRingElem,Int}()
Expand All @@ -753,7 +753,7 @@ function factor_distinct_deg(x::zzModPolyRingElem)
!is_prime(modulus(x)) && error("Modulus not prime in factor_distinct_deg")
degs = Vector{Int}(undef, degree(x))
degss = [ pointer(degs) ]
fac = nmod_poly_factor(x.mod_n)
fac = nmod_poly_factor(x.data.mod.n)
ccall((:nmod_poly_factor_distinct_deg, libflint), UInt,
(Ref{nmod_poly_factor}, Ref{zzModPolyRingElem}, Ptr{Ptr{Int}}),
fac, x, degss)
Expand Down
Loading