Example #1
0
int verify_bernoulli_mod_p(unsigned long *res, unsigned long p)
{
   unsigned long N, i, product, sum, value, element;
   double p_inv;
   N = (p-1)/2;
   product = 1;
   sum = 0;
   
   p_inv = z_precompute_inverse(p);
   
   for(i = 0; i < N; i++)
   {
      element = res[i];
      value = z_mulmod_precomp(z_mulmod_precomp(product, 2*i+1, p, p_inv), element, p, p_inv);
      sum = z_mod_precomp(sum + value, p, p_inv);
      product = z_mulmod_precomp(product, 4, p, p_inv);
   }
   
   if(z_mod_precomp(sum + 2,  p, p_inv))
   {   
      return FALSE;
   }
   
   return TRUE;
}
Example #2
0
unsigned long compute_factor_base(QS_t * qs_inf)
{
   unsigned long fb_prime = 2;
   unsigned long multiplier = qs_inf->k;
   prime_t * factor_base = qs_inf->factor_base;
   uint32_t * sqrts = qs_inf->sqrts;
   unsigned long num_primes = num_FB_primes(qs_inf->bits);
   unsigned long prime, nmod;
   double pinv;
   fmpz_t n = qs_inf->n;
   long kron;
    
   factor_base[0].p = multiplier;
   factor_base[0].pinv = z_precompute_inverse(multiplier);
   factor_base[1].p = 2;
   prime = 2;
   
   while (fb_prime < num_primes)
   {
      prime = z_nextprime(prime, 0);
      pinv = z_precompute_inverse(prime);
      nmod = mpn_mod_1(n + 1, n[0], prime);
      if (nmod == 0) 
      {
         if (z_mod_precomp(multiplier, prime, pinv) != 0) return prime;
      }
      kron = z_jacobi(nmod, prime); 
      if (kron == 1)
      {
         factor_base[fb_prime].p = prime;
         factor_base[fb_prime].pinv = pinv;
         sqrts[fb_prime] = z_sqrtmod(nmod, prime);
         fb_prime++;
      }   
   }
   printf("Largest prime = %ld\n", prime);
   
   qs_inf->num_primes = fb_prime;
   return 0;
}
Example #3
0
void compute_B_terms(QS_t * qs_inf, poly_t * poly_inf)
{
   unsigned long s = poly_inf->s;
   unsigned long * A_ind = poly_inf->A_ind;
   unsigned long * A_modp = poly_inf->A_modp;
   unsigned long * B_terms = poly_inf->B_terms;
   prime_t * factor_base = qs_inf->factor_base;
   unsigned long limbs = qs_inf->prec+1;
   unsigned long limbs2;
   unsigned long * A = poly_inf->A;
   unsigned long * B = poly_inf->B;
   unsigned long p, i; 
   unsigned long * temp1 = (unsigned long *) flint_stack_alloc(limbs);
   unsigned long temp;
   mp_limb_t msl;
   double pinv;
   
   for (i = 0; i < s; i++)
   {
      p = factor_base[A_ind[i]].p;
      pinv = z_precompute_inverse(p);
      mpn_divmod_1(temp1 + 1, A + 1, A[0], p);
      temp1[0] = A[0] - (temp1[A[0]] == 0); 
      A_modp[i] = (temp = mpn_mod_1(temp1 + 1, temp1[0], p));
      temp = z_invert(temp, p);
      temp = z_mulmod_precomp(temp, qs_inf->sqrts[A_ind[i]], p, pinv);
      if (temp > p/2) temp = p - temp;
      msl = mpn_mul_1(B_terms + i*limbs + 1, temp1 + 1, temp1[0], temp);
      if (msl) 
      {
         B_terms[i*limbs + temp1[0] + 1] = msl;
         B_terms[i*limbs] = temp1[0] + 1;
      }
      else B_terms[i*limbs] = temp1[0];
#if B_TERMS
      mpz_t temp;
      mpz_init(temp);
      fmpz_to_mpz(temp, B_terms + i*limbs);
      gmp_printf("B_%ld = %Zd\n", i, temp);
      mpz_clear(temp);
#endif
   }
   
   F_mpn_copy(B, B_terms, B_terms[0]+1);  // Set B to the sum of the B terms
   if (limbs > B_terms[0] + 1) F_mpn_clear(B + B_terms[0] + 1, limbs - B_terms[0] - 1);
   for (i = 1; i < s; i++)
   {
      limbs2 = B_terms[i*limbs];
      msl = mpn_add_n(B+1, B+1, B_terms + i*limbs + 1, limbs2);
      if (msl) mpn_add_1(B + limbs2 + 1, B + limbs2 + 1, limbs - limbs2 - 1, msl);
   }
   B[0] = limbs - 1;
   while (!B[B[0]] && B[0]) B[0]--;
#if B_TERMS
   mpz_t temp2;
   mpz_init(temp2);
   fmpz_to_mpz(temp2, B);
   gmp_printf("B = %Zd\n", temp2);
   mpz_clear(temp2);
#endif
   
   flint_stack_release(); // release temp1
}
Example #4
0
int bernoulli_mod_p_mpz(unsigned long *res, unsigned long p)
{
   FLINT_ASSERT(p > 2);
   FLINT_ASSERT(z_isprime(p) == 1);
   
   unsigned long g, g_inv, g_sqr, g_sqr_inv;
   double p_inv = z_precompute_inverse(p);
   g = z_primitive_root(p);
   
   if(!g)
   {
      return FALSE;
   }
   
   g_inv = z_invert(g, p);
   g_sqr = z_mulmod_precomp(g, g, p, p_inv);
   g_sqr_inv = z_mulmod_precomp(g_inv, g_inv, p, p_inv);
   
   unsigned long poly_size = (p-1)/2;
   
   int is_odd = poly_size % 2;
   
   unsigned long g_power, g_power_inv;
   g_power = g_inv;
   g_power_inv = 1;
   
   // constant is (g-1)/2 mod p
   unsigned long constant;
   if(g % 2)
   {
      constant = (g-1)/2;
   }
   else
   {
      constant = (g+p-1)/2;
   }
   
   // fudge holds g^{i^2}, fudge_inv holds g^{-i^2}
   unsigned long fudge, fudge_inv;
   fudge = fudge_inv = 1;
   
   // compute the polynomials F(X) and G(X)
   mpz_poly_t F, G;
   
   mpz_poly_init2(F, poly_size);
   mpz_poly_init2(G, poly_size);
   
   unsigned long i, temp, h;
   
   for(i = 0; i < poly_size; i++)
   {  
      // compute h(g^i)/g^i (h(x) is as in latex notes)
      temp = g * g_power;
            
      h = z_mulmod_precomp(p + constant - (temp / p), g_power_inv, p, p_inv);
      
      g_power = z_mod_precomp(temp, p, p_inv);
      g_power_inv = z_mulmod_precomp(g_power_inv, g_inv, p, p_inv);
      
      // store coefficient g^{i^2} h(g^i)/g^i
      mpz_poly_set_coeff_ui(G, i, z_mulmod_precomp(h, fudge, p, p_inv));
      mpz_poly_set_coeff_ui(F, i, fudge_inv);
      
      // update fudge and fudge_inv
      fudge = z_mulmod_precomp(z_mulmod_precomp(fudge, g_power, p, p_inv), z_mulmod_precomp(g_power, g, p, p_inv), p, p_inv);
      fudge_inv = z_mulmod_precomp(z_mulmod_precomp(fudge_inv, g_power_inv, p, p_inv), z_mulmod_precomp(g_power_inv, g, p, p_inv), p, p_inv);
   }
   
   mpz_poly_set_coeff_ui(F, 0, 0);
   
   // step 2: multiply the polynomials...
   mpz_poly_t product;
   mpz_poly_init(product);
   mpz_poly_mul(product, G, F);
   
   // step 3: assemble the result...   
   unsigned long g_sqr_power, value;
   g_sqr_power = g_sqr;
   fudge = g;

   res[0] = 1;
   
   mpz_t value_coeff;
   mpz_init(value_coeff);
   
   unsigned long value_coeff_ui;

   for(i = 1; i < poly_size; i++)
   {
      mpz_poly_get_coeff(value_coeff, product, i + poly_size);
      value = mpz_fdiv_ui(value_coeff, p);
      
      value = z_mod_precomp(mpz_poly_get_coeff_ui(product, i + poly_size), p, p_inv);
      
      mpz_poly_get_coeff(value_coeff, product, i);
      if(is_odd)
      {
         value = z_mod_precomp(mpz_poly_get_coeff_ui(G, i) + mpz_fdiv_ui(value_coeff, p) + p - value, p, p_inv);
      }
      else
      {
         value = z_mod_precomp(mpz_poly_get_coeff_ui(G, i) + mpz_fdiv_ui(value_coeff, p) + value, p, p_inv);
      }
      
      value = z_mulmod_precomp(z_mulmod_precomp(z_mulmod_precomp(4, i, p, p_inv), fudge, p, p_inv), value, p, p_inv);
      value = z_mulmod_precomp(value, z_invert(p+1-g_sqr_power, p), p, p_inv);

      res[i] = value;
      
      g_sqr_power = z_mulmod_precomp(g_sqr_power, g, p, p_inv);
      fudge = z_mulmod_precomp(fudge, g_sqr_power, p, p_inv);
      g_sqr_power = z_mulmod_precomp(g_sqr_power, g, p, p_inv);
   }
   
   mpz_clear(value_coeff);
   
   mpz_poly_clear(F);
   mpz_poly_clear(G);
   mpz_poly_clear(product);
   
   return TRUE;
}
Example #5
0
unsigned long knuth_schroeppel(QS_t * qs_inf)
{
    float best_factor = -10.0f;
    unsigned long multiplier = 1;
    unsigned long nmod8, mod8, multindex, prime, nmod, mult;
    const unsigned long max_fb_primes = qs_inf->num_primes;
    unsigned long fb_prime = 2; // leave space for the multiplier and 2
    float factors[NUMMULTS];
    float logpdivp;
    double pinv;
    int kron;
    
    uint32_t * sqrts = qs_inf->sqrts;
    
    fmpz_t n = qs_inf->n;
    nmod8 = n[1]%8;
    
    mpz_t r;
        
    for (multindex = 0; multindex < NUMMULTS; multindex++)
    {
       mod8 = ((nmod8*multipliers[multindex])%8);
       factors[multindex] = 0.34657359; // ln2/2 
       if (mod8 == 1) factors[multindex] *= 4.0;   
       if (mod8 == 5) factors[multindex] *= 2.0;   
       factors[multindex] -= (log((float) multipliers[multindex]) / 2.0);
    }
    
    prime = 3;
    while (prime < KSMAX)// && (fb_prime < max_fb_primes))
    {
          pinv = z_precompute_inverse(prime);
          logpdivp = log((float)prime) / (float)prime; // log p / p
          nmod = mpn_mod_1(n + 1, n[0], prime);
          if (nmod == 0) return prime;
          kron = z_jacobi(nmod, prime); 
          for (multindex = 0; multindex < NUMMULTS; multindex++)
          {
              mult = multipliers[multindex];
              if (mult >= prime) 
              {
                 if (mult >= prime*prime) mult = mult%prime; 
                 else mult = z_mod_precomp(mult, prime, pinv);
              }
              if (mult == 0) factors[multindex] += logpdivp;
              else if (kron*z_jacobi(mult, prime) == 1) 
                 factors[multindex] += 2.0*logpdivp;
          }
          
          prime = z_nextprime(prime, 0);
    }
    
    for (multindex=0; multindex<NUMMULTS; multindex++)
    {
      if (factors[multindex] > best_factor)
      { 
        best_factor = factors[multindex];
        multiplier = multipliers[multindex];
      }
    } 
    
    qs_inf->k = multiplier;
    return 0;
}
Example #6
0
void tiny_compute_A(QS_t * qs_inf, poly_t * poly_inf)
{
   unsigned long min = poly_inf->min;
   unsigned long span = poly_inf->span;
   unsigned long s = poly_inf->s;
   unsigned long * A_ind = poly_inf->A_ind;
   prime_t * factor_base = qs_inf->factor_base;
   unsigned long factor, i, p;
   unsigned long diff, best_diff, best1, best2;
   
   unsigned long A;
   
   if (s <= 4) 
   {
       A_ind[0] = z_randint(span) + min;
       do
       {
          A_ind[1] = z_randint(span) + min;
       } while (A_ind[0] == A_ind[1]);
   }
   
   if (s == 2) A = factor_base[A_ind[0]].p * factor_base[A_ind[1]].p;
   
   if ((s == 3) || (s == 4))
   {
       do
       {
          A_ind[2] = z_randint(span) + min;
       } while ((A_ind[0] == A_ind[2]) || (A_ind[1] == A_ind[2]));
       A = factor_base[A_ind[0]].p * factor_base[A_ind[1]].p * factor_base[A_ind[2]].p;
   }  
   
   if (s == 4)
   {
      factor = (poly_inf->target_A - 1) / A + 1; 
      for (i = min; i < min+span; i++)
      {
         if ((factor_base[i].p > factor) && (i != A_ind[0]) && (i != A_ind[1]) && (i != A_ind[2])) break;
      } 
      if (i == min + span)
      {
         i--;
         while ((i == A_ind[0]) || (i == A_ind[1]) || (i == A_ind[2])) i--;
      }   
      A_ind[3] = i;
      A *= factor_base[A_ind[3]].p;
   }
   
   if (s == 5) 
   {
       A_ind[0] = ((z_randint(span) + min) | 1);
       if (A_ind[0] == min + span) A_ind[0] -= 2;
       
       do
       {
          A_ind[1] = ((z_randint(span) + min) | 1);
          if (A_ind[1] == min + span) A_ind[1] -= 2;
       } while (A_ind[0] == A_ind[1]);
       
       do
       {
          A_ind[2] = ((z_randint(span) + min) | 1);
          if (A_ind[2] == min + span) A_ind[2] -= 2;
       } while ((A_ind[0] == A_ind[2]) || (A_ind[1] == A_ind[2]));
       
       A = factor_base[A_ind[0]].p * factor_base[A_ind[1]].p * factor_base[A_ind[2]].p;
       factor = poly_inf->target_A / A;
       
       for (i = 0; i < 8; i++)
       {
          A_ind[3] = ((z_randint(span) + min) & -2L);
          if (A_ind[3] < min) A_ind[3]+=2;
          
          do
          {
             A_ind[4] = ((z_randint(span) + min) & -2L);
             if (A_ind[4] < min) A_ind[4]+=2;
          } while (A_ind[3] == A_ind[4]);
          
          if (i == 0)
          {
             best_diff = FLINT_ABS(factor_base[A_ind[3]].p * factor_base[A_ind[4]].p - factor);
             best1 = A_ind[3];
             best2 = A_ind[4];
             continue;
          }
          
          diff = FLINT_ABS(factor_base[A_ind[3]].p * factor_base[A_ind[4]].p - factor);
          
          if (diff < best_diff)
          {
             best_diff = diff;
             best1 = A_ind[3];
             best2 = A_ind[4];
          }
       }
       
       A_ind[3] = best1;
       A_ind[4] = best2;
       A = A * factor_base[A_ind[3]].p * factor_base[A_ind[4]].p;
   }  
   
   poly_inf->A = A;

#if POLY_A
   if ((s == 4) || (s == 5)) printf("A = %ld, target A = %ld\n", A, poly_inf->target_A);
#endif    
 
   for (i = 0; i < s; i++)
   {
      p = factor_base[A_ind[i]].p;
      poly_inf->inv_p2[i] = z_precompute_inverse(p*p);
   }      
}