2121/*
2222 TODO:
2323
24- * Handle aliasing
2524 * try to reuse information from previous failed attempt
2625 * improve bounds
2726 * add LM bound termination for nonsquare case
2827 * add linear and quadratic cases
2928 * Tune the number of primes used in trial factoring
3029 * Use ECM and larger recombination for very large square roots
31- * Prove isomorphism to Z/pZ in all cases or exclude primes
30+ * Prove homomorphism to Z/pZ in all cases or exclude primes
3231 * Deal with lousy starting bounds (they are too optimistic if f is not monic)
3332 * Deal with number fields of degree 1 and 2
3433 * Deal with primes dividing denominator of norm
@@ -121,7 +120,7 @@ slong _fmpz_poly_get_n_adic(fmpz * sqrt, slong len, fmpz_t z, fmpz_t n)
121120 return slen ;
122121}
123122
124- int nf_elem_sqrt (nf_elem_t a , const nf_elem_t b , const nf_t nf )
123+ int _nf_elem_sqrt (nf_elem_t a , const nf_elem_t b , const nf_t nf )
125124{
126125 if (nf -> flag & NF_LINEAR )
127126 {
@@ -154,12 +153,6 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
154153 fmpz * r , * mr , * bz ;
155154 int res = 0 , factored , iters ;
156155
157- if (!fmpz_is_one (fmpq_poly_denref (nf -> pol )))
158- {
159- flint_printf ("Non-monic defining polynomial not supported in sqrt yet.\n" );
160- flint_abort ();
161- }
162-
163156 if (lenb == 0 )
164157 {
165158 nf_elem_zero (a , nf );
@@ -215,7 +208,7 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
215208#endif
216209
217210 bbits = FLINT_ABS (_fmpz_vec_max_bits (bz , lenb ));
218- nbits = (bbits + 1 )/(2 * lenf ) + 2 ;
211+ nbits = (bbits + 1 )/(20 ) + 2 ;
219212
220213 /*
221214 Step 3: find a nbits bit prime such that z = f(n) is a product
@@ -225,29 +218,41 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
225218 field K defined by f. Then O_K/P_i is isomorphic to Z/pZ via
226219 the map s(x) mod P_i -> s(n) mod p.
227220 */
228- #if DEBUG
229- flint_printf ("Step 3\n" );
230- #endif
231221
232222 fmpz_factor_init (fac );
233223 fmpz_init (z );
234224 fmpz_init (n );
235225
226+ fmpz_init (disc );
227+ flint_randinit (state );
228+
229+ _fmpz_poly_discriminant (disc , fmpq_poly_numref (nf -> pol ), lenf );
230+
236231 do /* continue increasing nbits until square root found */
237232 {
238- fmpz_init (disc );
239- flint_randinit (state );
240-
241- _fmpz_poly_discriminant (disc , fmpq_poly_numref (nf -> pol ), lenf );
233+ fmpz_t fac1 ;
234+
235+ fmpz_init (fac1 );
242236
243237 factored = 0 ;
244238 iters = 0 ;
245239
246- while (!factored || fac -> num > 6 ) /* no bound known for finding such a factorisation */
240+ #if DEBUG
241+ flint_printf ("Step 3\n" );
242+ #endif
243+
244+ while (!factored || fac -> num > 14 ) /* no bound known for finding such a factorisation */
247245 {
248246 fmpz_factor_clear (fac );
249247 fmpz_factor_init (fac );
250248
249+ /* ensure we don't exhaust all primes of the given size */
250+ if (nbits < 20 && iters >= (1 <<(nbits - 1 )))
251+ {
252+ iters = 0 ;
253+ nbits ++ ;
254+ }
255+
251256 fmpz_randprime (n , state , nbits , 0 );
252257 if (fmpz_sgn (n ) < 0 )
253258 fmpz_neg (n , n );
@@ -257,19 +262,17 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
257262 factored = fmpz_factor_trial (fac , z , 3512 );
258263
259264 if (!factored )
260- factored = fmpz_is_probabprime (fac -> p + fac -> num - 1 );
261-
262- if (nbits < 20 && iters >= (1 <<(nbits - 1 )))
263265 {
264- iters = 0 ;
265- nbits ++ ;
266+ fmpz_set (fac1 , fac -> p + fac -> num - 1 );
267+ fac -> num -- ;
268+
269+ factored = fmpz_factor_smooth (fac , fac1 , FLINT_MIN (20 , nbits /5 + 1 ), 0 );
266270 }
267271
268272 iters ++ ;
269273 }
270274
271- flint_randclear (state );
272- fmpz_clear (disc );
275+ fmpz_clear (fac1 );
273276
274277 /*
275278 Step 4: compute the square roots r_i of z = b(n) mod p_i for each
@@ -379,6 +382,9 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
379382 } while (res != 1 );
380383
381384cleanup :
385+ flint_randclear (state );
386+ fmpz_clear (disc );
387+
382388 fmpz_clear (n );
383389 fmpz_clear (temp );
384390 fmpz_clear (z );
@@ -394,3 +400,23 @@ int nf_elem_sqrt(nf_elem_t a, const nf_elem_t b, const nf_t nf)
394400 }
395401}
396402
403+ int nf_elem_sqrt (nf_elem_t a , const nf_elem_t b , const nf_t nf )
404+ {
405+ nf_elem_t t ;
406+
407+ if (a == b )
408+ {
409+ int ret ;
410+
411+ nf_elem_init (t , nf );
412+
413+ ret = _nf_elem_sqrt (t , b , nf );
414+ nf_elem_swap (t , a , nf );
415+
416+ nf_elem_clear (t , nf );
417+
418+ return ret ;
419+ }
420+ else
421+ return _nf_elem_sqrt (a , b , nf );
422+ }
0 commit comments