Beispiel #1
0
/*
   Reference implementation of zn_array_pack().
   
   (doesn't take into account the s or r parameters)
*/
void
ref_zn_array_pack (mp_limb_t* res, const ulong* op, size_t n, unsigned b,
                   unsigned k)
{
   mpz_t x;
   mpz_init (x);
   ref_zn_array_pack_helper (x, op, n, b, k);
   mpz_to_mpn (res, CEIL_DIV (n * b + k, GMP_NUMB_BITS), x);
   mpz_clear (x);
}
Beispiel #2
0
/*
   tests zn_array_unpack() once for given n, b, k
*/
int
testcase_zn_array_unpack (size_t n, unsigned b, unsigned k)
{
   size_t buf_size = CEIL_DIV (n * b + k, GMP_NUMB_BITS);
   size_t size = n * CEIL_DIV (b, ULONG_BITS);

   mp_limb_t* buf = (mp_limb_t*) malloc (sizeof (mp_limb_t) * buf_size);
   ulong* res = (ulong*) malloc (sizeof (ulong) * (size + 2));
   ulong* ref = (ulong*) malloc (sizeof (ulong) * (size + 2));

   // sentries to check buffer overflow
   res[0] = res[size + 1] = ref[0] = ref[size + 1] = 0x1234;

   // generate random data
   mpz_t x;
   mpz_init (x);
   mpz_urandomb (x, randstate, n * b);
   mpz_mul_2exp (x, x, k);
   mpz_to_mpn (buf, buf_size, x);
   mpz_clear (x);

   // run target and reference implementation
   zn_array_unpack (res + 1, buf, n, b, k);
   ref_zn_array_unpack (ref + 1, buf, n, b, k);
   
   int success = 1;

   // check sentries
   success = success && (res[0] == 0x1234);
   success = success && (ref[0] == 0x1234);
   success = success && (res[size + 1] == 0x1234);
   success = success && (ref[size + 1] == 0x1234);
   // check correct result
   success = success && (zn_array_cmp (res + 1, ref + 1, size) == 0);
   
   free (ref);
   free (res);
   free (buf);

   return success;
}
Beispiel #3
0
int
main (int argc, char **argv)
{
  gmp_randstate_ptr rands;
  long count = COUNT;
  mp_ptr mp;
  mp_ptr ap;
  mp_ptr tp;
  mp_ptr scratch;
  mpz_t m, a, r, g;
  int test;
  mp_limb_t ran;
  mp_size_t itch;
  TMP_DECL;

  tests_start ();
  rands = RANDS;


  TMP_MARK;
  mpz_init (m);
  mpz_init (a);
  mpz_init (r);
  mpz_init (g);

  if (argc > 1)
    {
      char *end;
      count = strtol (argv[1], &end, 0);
      if (*end || count <= 0)
	{
	  fprintf (stderr, "Invalid test count: %s.\n", argv[1]);
	  return 1;
	}
    }

  mp = TMP_ALLOC_LIMBS (MAX_SIZE);
  ap = TMP_ALLOC_LIMBS (MAX_SIZE);
  tp = TMP_ALLOC_LIMBS (MAX_SIZE);
  scratch = TMP_ALLOC_LIMBS (mpn_sec_invert_itch (MAX_SIZE) + 1);

  for (test = 0; test < count; test++)
    {
      mp_bitcnt_t bits;
      int rres, tres;
      mp_size_t n;

      bits = urandom () % (GMP_NUMB_BITS * MAX_SIZE) + 1;

      if (test & 1)
	mpz_rrandomb (m, rands, bits);
      else
	mpz_urandomb (m, rands, bits);
      if (test & 2)
	mpz_rrandomb (a, rands, bits);
      else
	mpz_urandomb (a, rands, bits);

      mpz_setbit (m, 0);
      if (test & 4)
	{
	  /* Ensure it really is invertible */
	  if (mpz_sgn (a) == 0)
	    mpz_set_ui (a, 1);
	  else
	    for (;;)
	      {
		mpz_gcd (g, a, m);
		if (mpz_cmp_ui (g, 1) == 0)
		  break;
		mpz_remove (a, a, g);
	      }
	}

      rres = mpz_invert (r, a, m);
      if ( (test & 4) && !rres)
	{
	  gmp_fprintf (stderr, "test %d: Not invertible!\n"
		       "m = %Zd\n"
		       "a = %Zd\n", test, m, a);
	  abort ();
	}
      ASSERT_ALWAYS (! (test & 4) || rres);

      n = (bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
      ASSERT_ALWAYS (n <= MAX_SIZE);
      itch = mpn_sec_invert_itch (n);
      scratch[itch] = ran = urandom ();

      mpz_to_mpn (ap, n, a);
      mpz_to_mpn (mp, n, m);
      tres = mpn_sec_invert (tp, ap, mp, n,
			     bit_size (ap, n) + bit_size (mp, n),
			     scratch);

      if (rres != tres || (rres == 1 && !mpz_eq_mpn (tp, n, r)) || ran != scratch[itch])
	{
	  gmp_fprintf (stderr, "Test %d failed.\n"
		       "m = %Zd\n"
		       "a = %Zd\n", test, m, a);
	  fprintf (stderr, "ref ret: %d\n"
		  "got ret: %d\n", rres, tres);
	  if (rres)
	    gmp_fprintf (stderr, "ref: %Zd\n", r);
	  if (tres)
	    gmp_fprintf (stderr, "got: %Nd\n", tp, n);
	  if (ran != scratch[itch])
	    fprintf (stderr, "scratch[itch] changed.\n");
	  abort ();
	}
    }

  TMP_FREE;

  mpz_clear (m);
  mpz_clear (a);
  mpz_clear (r);
  mpz_clear (g);

  tests_end ();
  return 0;
}
Beispiel #4
0
int test__ZmodF_mul_threeway_reduce()
{
   int success = 1;

   mp_limb_t in[2000];
   mp_limb_t out1[2000];
   mp_limb_t out2[2000];
   mp_limb_t test[2000];

   mpz_t x, y, power, power2, mod1, mod2;
   mpz_init(x);
   mpz_init(y);
   mpz_init(power);
   mpz_init(power2);
   mpz_init(mod1);
   mpz_init(mod2);

   for (unsigned long n = 3; n < 300 && success; n += 3)
   {
#if DEBUG
      printf("n = %d\n", n);
#endif
      
      // power = B^n
      mpz_set_ui(power, 1);
      mpz_mul_2exp(power, power, n*FLINT_BITS);

      // power2 = B^(2n/3)
      mpz_set_ui(power2, 1);
      mpz_mul_2exp(power2, power2, 2*n/3*FLINT_BITS);

      // mod1 = B^(n/3) + 1
      mpz_set_ui(mod1, 1);
      mpz_mul_2exp(mod1, mod1, n/3*FLINT_BITS);
      mpz_add_ui(mod1, mod1, 1);

      // mod2 = B^(2n/3) - B^(n/3) + 1
      mpz_set(mod2, mod1);
      mpz_mul_2exp(mod2, mod2, n/3*FLINT_BITS);
      mpz_sub(mod2, mod2, mod1);
      mpz_sub(mod2, mod2, mod1);
      mpz_add_ui(mod2, mod2, 3);

      for (unsigned long trial = 0; trial < 250 && success; trial++)
      {
         random_limbs(in, n);
         in[n] = 0;
         mpn_to_mpz(x, in, n+1);

         _ZmodF_mul_threeway_reduce1(out1, in, n/3);
         ZmodF_normalise(out1, n/3);
         mpz_mod(y, x, mod1);
         mpz_to_mpn(test, n/3 + 1, y);
         if (mpn_cmp(test, out1, n/3 + 1))
             success = 0;

         _ZmodF_mul_threeway_reduce2(out2, in, n/3);
         mpz_mod(y, x, mod2);
         mpz_to_mpn(test, 2*n/3, y);
         if (mpn_cmp(test, out2, 2*n/3))
         {
            // didn't work... check if the "other answer" is correct
            mpz_add(y, y, mod2);
            if (mpz_cmp(y, power2) >= 0)
               success = 0;
            else
            {
               mpz_to_mpn(test, 2*n/3, y);
               if (mpn_cmp(test, out2, 2*n/3))
                  success = 0;
            }
         }
      }
   }

   mpz_clear(mod2);
   mpz_clear(mod1);
   mpz_clear(power2);
   mpz_clear(power);
   mpz_clear(y);
   mpz_clear(x);

   return success;
}
Beispiel #5
0
int test__ZmodF_mul_fft_combine()
{
   int success = 1;
   
   mpz_t x, y, p, q, r, s, total;
   mpz_init(x);
   mpz_init(y);
   mpz_init(s);
   mpz_init(r);
   mpz_init(q);
   mpz_init(p);
   mpz_init(total);

   mp_limb_t buf[300];

   for (unsigned long n = 1; n < 80 && success; n++)
   {
      for (unsigned long depth = 0;
           ((n*FLINT_BITS) % (1 << depth) == 0) && success; depth++)
      {
         for (unsigned long m = 1; m < n/4 && success; m++)
         {
            for (unsigned long k = 0; k < 5 && success; k++)
            {
#if DEBUG
               printf("n = %ld, depth = %ld, m = %ld, k = %ld\n", n, depth, m, k);
#endif

               ZmodF_poly_t poly;
               ZmodF_poly_init(poly, depth, m+k, 1);

               // p := B^n + 1
               mpz_set_ui(p, 1);
               mpz_mul_2exp(p, p, n*FLINT_BITS);
               mpz_add_ui(p, p, 1);
               
               // q := (B^m + 1)*B^k
               mpz_set_ui(q, 1);
               mpz_mul_2exp(q, q, m*FLINT_BITS);
               mpz_add_ui(q, q, 1);
               mpz_mul_2exp(q, q, k*FLINT_BITS);

               // r := B^(m+k) - 1
               mpz_set_ui(r, 1);
               mpz_mul_2exp(r, r, (m+k)*FLINT_BITS);
               mpz_sub_ui(r, r, 1);
               
               // s := B^(m+k)/2
               mpz_set_ui(s, 1);
               mpz_mul_2exp(s, s, (m+k)*FLINT_BITS - 1);
                  
               for (unsigned long trial = 0; trial < 20 && success; trial++)
               {
                  mpz_set_ui(total, 0);
               
                  for (long i = (1 << depth) - 1; i >= 0; i--)
                  {
                     // select random x in (0, B^(m+k))
                     mpz_set_ui(x, 0);
                     while (!mpz_sgn(x))
                     {
                        mpz_rrandomb(x, randstate, (m+k)*FLINT_BITS);
                        if (random_ulong(2))    // to get high bit 0 sometimes
                           mpz_sub(x, r, x);
                     }
                        
                     // push it down to (-B^(m+k)/2, B^(m+k)/2)
                     mpz_sub(x, x, s);
                     
                     // add it to running total
                     mpz_mul_2exp(total, total, (n*FLINT_BITS) >> depth);
                     mpz_add(total, total, x);
                     
                     // normalise it into [0, q), and store in polynomial
                     mpz_mod(x, x, q);
                     mpz_to_mpn(poly->coeffs[i], m+k+1, x);
                  }
                  
                  // compare result to target function
                  _ZmodF_mul_fft_combine(buf, poly, m, k, n);
                  ZmodF_normalise(buf, n);
                  mpn_to_mpz(y, buf, n+1);
                  
                  mpz_mod(total, total, p);
                  if (mpz_cmp(total, y))
                     success = 0;
               }

               ZmodF_poly_clear(poly);
            }
         }
      }
   }

   mpz_clear(x);
   mpz_clear(y);
   mpz_clear(s);
   mpz_clear(r);
   mpz_clear(q);
   mpz_clear(p);
   mpz_clear(total);

   return success;
}