11import msolve_jll: libmsolve
22
3- export real_solutions, rational_solutions, rational_parametrization
3+ export inter_solutions, real_solutions, rational_solutions, rational_parametrization
44
55@doc Markdown. doc"""
66 _get_rational_parametrization(nr::Int32, lens::Vector{Int32}, cfs::Ptr{BigInt})
@@ -134,6 +134,7 @@ function _core_msolve(
134134 C,x = polynomial_ring (QQ," x" )
135135 I. rat_param = RationalParametrization (Symbol[], ZZRingElem[], C (- 1 ), C (- 1 ), PolyRingElem[])
136136 I. real_sols = QQFieldElem[]
137+ I. inter_sols = Vector{QQFieldElem}[]
137138 return I. rat_param, I. real_sols
138139 end
139140 [nterms += jl_len[i] for i= 1 : jl_ld]
@@ -152,6 +153,7 @@ function _core_msolve(
152153 rat_param[3 ], rat_param[4 ])
153154 if jl_nb_sols == 0
154155 I. real_sols = QQFieldElem[]
156+ I. inter_sols = Vector{QQFieldElem}[]
155157 return rat_param, Vector{QQFieldElem}[]
156158 end
157159
@@ -164,25 +166,32 @@ function _core_msolve(
164166 # end
165167
166168 #= solutions are returned as intervals, i.e. a minimum and a maximum entry for
167- = the numerator and denominator; thus we sum up and divide by =#
169+ = the numerator and denominator; we also sum up and divide by 2 =#
170+
171+ inter_solutions = Vector {Vector{Vector{QQFieldElem}}} (undef, jl_nb_sols)
168172 solutions = Vector {Vector{QQFieldElem}} (undef, jl_nb_sols)
169173
170174 len = 2 * jl_nb_sols* nr_vars
171175 i = 1
172176 k = 1
173177 while i <= len
174178 j = 1
179+ inter_tmp = Vector {Vector{QQFieldElem}} (undef, nr_vars)
175180 tmp = Vector {QQFieldElem} (undef, nr_vars)
176181 while j <= nr_vars
177- tmp[perm[j]] = QQFieldElem (unsafe_load (jl_sols_num, i)) >> Int64 (unsafe_load (jl_sols_den, i))
178- tmp[perm[j]] += QQFieldElem (unsafe_load (jl_sols_num, i+ 1 )) >> Int64 (unsafe_load (jl_sols_den, i+ 1 ))
179- tmp[perm[j]] = tmp[perm[j]] >> 1
182+ inter_tmp_coeff = Vector {QQFieldElem} (undef, 2 )
183+ inter_tmp_coeff[1 ] = QQFieldElem (unsafe_load (jl_sols_num, i)) >> Int64 (unsafe_load (jl_sols_den, i))
184+ inter_tmp_coeff[2 ] = QQFieldElem (unsafe_load (jl_sols_num, i+ 1 )) >> Int64 (unsafe_load (jl_sols_den, i+ 1 ))
185+ inter_tmp[perm[j]] = inter_tmp_coeff
186+ tmp[perm[j]] = sum (inter_tmp_coeff) >> 1
180187 i += 2
181188 j += 1
182189 end
190+ inter_solutions[k] = inter_tmp
183191 solutions[k] = tmp
184192 k += 1
185193 end
194+ I. inter_sols = inter_solutions
186195 I. real_sols = solutions
187196
188197 ccall ((:free_msolve_julia_result_data , libmsolve), Nothing ,
@@ -401,3 +410,62 @@ function real_solutions(
401410
402411 return I. real_sols
403412end
413+
414+ @doc Markdown. doc"""
415+ inter_solutions(I::Ideal{T} where T <: MPolyRingElem, <keyword arguments>)
416+
417+ Given an ideal `I` with a finite solution set over the complex numbers, return
418+ the intervals with a given precision (default 32 bits), containing the roots of the ideal.
419+
420+ **Note**: At the moment only QQ is supported as ground field. If the dimension of the ideal
421+ is greater than zero an empty array is returned.
422+
423+ # Arguments
424+ - `I::Ideal{T} where T <: MPolyRingElem`: input generators.
425+ - `initial_hts::Int=17`: initial hash table size `log_2`.
426+ - `nr_thrds::Int=1`: number of threads for parallel linear algebra.
427+ - `max_nr_pairs::Int=0`: maximal number of pairs per matrix, only bounded by minimal degree if `0`.
428+ - `la_option::Int=2`: linear algebra option: exact sparse-dense (`1`), exact sparse (`2`, default), probabilistic sparse-dense (`42`), probabilistic sparse(`44`).
429+ - `info_level::Int=0`: info level printout: off (`0`, default), summary (`1`), detailed (`2`).
430+ - `precision::Int=32`: bit precision for the computed solutions.
431+
432+ # Examples
433+ ```jldoctest
434+ julia> using AlgebraicSolving
435+
436+ julia> R,(x1,x2,x3) = polynomial_ring(QQ, ["x1","x2","x3"])
437+ (Multivariate polynomial ring in 3 variables over QQ, QQMPolyRingElem[x1, x2, x3])
438+
439+ julia> I = Ideal([x1+2*x2+2*x3-1, x1^2+2*x2^2+2*x3^2-x1, 2*x1*x2+2*x2*x3-x2])
440+ QQMPolyRingElem[x1 + 2*x2 + 2*x3 - 1, x1^2 - x1 + 2*x2^2 + 2*x3^2, 2*x1*x2 + 2*x2*x3 - x2]
441+
442+ julia> inter_solutions(I)
443+ 4-element Vector{Vector{Vector{QQFieldElem}}}:
444+ [[1354207349//2147483648, 2708414699//4294967296], [1354207349//4294967296, 677103675//2147483648], [-355532291286331190123863132844989723573//2722258935367507707706996859454145691648, -1422129165145324760495452531379958894291//10889035741470030830827987437816582766592]]
445+ [[1, 1], [0, 0], [0, 0]]
446+ [[972985841//4294967296, 486492921//2147483648], [60811615//536870912, 486492921//4294967296], [93053303113782607831679264095876317083//340282366920938463463374607431768211456, 372213212455130431326717056383505268333//1361129467683753853853498429727072845824]]
447+ [[1431655765//4294967296, 715827883//2147483648], [-1//4294967296, 1//4294967296], [1814839290245005138471331239636097127765//5444517870735015415413993718908291383296, 907419645122502569235665619818048563883//2722258935367507707706996859454145691648]]
448+ ```
449+ """
450+ function inter_solutions (
451+ I:: Ideal{T} where T <: MPolyRingElem ; # input generators
452+ initial_hts:: Int = 17 , # hash table size, default 2^17
453+ nr_thrds:: Int = 1 , # number of threads
454+ max_nr_pairs:: Int = 0 , # number of pairs maximally chosen
455+ # in symbolic preprocessing
456+ la_option:: Int = 2 , # linear algebra option
457+ info_level:: Int = 0 , # info level for print outs
458+ precision:: Int = 32 # precision of the solution set
459+ )
460+
461+ isdefined (I, :inter_sols ) ||
462+ _core_msolve (I,
463+ initial_hts = initial_hts,
464+ nr_thrds = nr_thrds,
465+ max_nr_pairs = max_nr_pairs,
466+ la_option = la_option,
467+ info_level = info_level,
468+ precision = precision)
469+
470+ return I. inter_sols
471+ end
0 commit comments