From 0f1100bc1892867f54b61e2f249b4c98e78e2de2 Mon Sep 17 00:00:00 2001
From: Paul Zimmermann <Paul.Zimmermann@inria.fr>
Date: Wed, 26 Jun 2024 16:41:14 +0200
Subject: [PATCH] simplify the logic in get_curve_from_random_parameter()

If the random sigma value fails, then try the next one (sigma+1),
and so on, instead of drawing a new random value. For small n,
this will avoid failures (for n=5, the probability of failure
with param=1 goes down from 1/150 to 0).
---
 parametrizations.c | 35 ++++++++++++++++-------------------
 1 file changed, 16 insertions(+), 19 deletions(-)

diff --git a/parametrizations.c b/parametrizations.c
index 44249024..77aaff72 100644
--- a/parametrizations.c
+++ b/parametrizations.c
@@ -243,8 +243,8 @@ get_curve_from_param1 (mpres_t A, mpres_t x0, mpz_t sigma, mpmod_t n)
       
   /* A=4*d-2 with d = sigma^2/2^64 */
   /* Compute d = sigma^2/2^64 */
-  mpz_ui_pow_ui(tmp, 2, 64);
-  mpz_invert(tmp, tmp, n->orig_modulus);
+  mpz_ui_pow_ui (tmp, 2, 64);
+  mpz_invert (tmp, tmp, n->orig_modulus);
 
   /* tmp = sigma^2/2^64 */
   mpz_mul (tmp, tmp, sigma);
@@ -264,7 +264,7 @@ get_curve_from_param1 (mpres_t A, mpres_t x0, mpz_t sigma, mpmod_t n)
   mpres_set_z (A, tmp, n);
   mpres_set_ui (x0, 2, n);
 
-  mpz_clear(tmp);
+  mpz_clear (tmp);
   return ECM_NO_FACTOR_FOUND;
 }
 
@@ -433,30 +433,27 @@ get_curve_from_random_parameter (mpz_t f, mpres_t A, mpres_t x, mpz_t sigma,
      to avoid an infinite loop in corner cases (for example with -param 1,
      there is no valid sigma for n=3, see
      https://gitlab.inria.fr/zimmerma/ecm/-/issues/21876) */
+  unsigned long bitsize = (param == ECM_PARAM_BATCH_SQUARE ||
+                           param == ECM_PARAM_BATCH_32BITS_D) ? 32 : 64;
+  mpz_urandomb (sigma, rng, bitsize);
   for (int i = 0; ret == ECM_ERROR && i < 10; i++)
     {
       if (param == ECM_PARAM_SUYAMA)
-        {
-          mpz_urandomb (sigma, rng, 64);
-          ret = get_curve_from_param0 (f, A, x, sigma, modulus);
-        }
+        ret = get_curve_from_param0 (f, A, x, sigma, modulus);
       else if (param == ECM_PARAM_BATCH_SQUARE)
-        {
-          mpz_urandomb (sigma, rng, 32);
-          ret = get_curve_from_param1 (A, x, sigma, modulus);
-        }
+        ret = get_curve_from_param1 (A, x, sigma, modulus);
       else if (param == ECM_PARAM_BATCH_2)
-        {
-          mpz_urandomb (sigma, rng, 64);
-          ret = get_curve_from_param2 (f, A, x, sigma, modulus);
-        }
+        ret = get_curve_from_param2 (f, A, x, sigma, modulus);
       else if (param == ECM_PARAM_BATCH_32BITS_D)
-        {
-          mpz_urandomb (sigma, rng, 32);
-          ret = get_curve_from_param3 (A, x, sigma, modulus);
-        }
+        ret = get_curve_from_param3 (A, x, sigma, modulus);
       else
         return ECM_ERROR;
+      if (ret == ECM_ERROR) // try next sigma value
+      {
+        mpz_add_ui (sigma, sigma, 1);
+        if (mpz_sizeinbase (sigma, 2) > bitsize)
+          mpz_set_ui (sigma, 2);
+      }
     }
 
   return ret;
-- 
GitLab