Пример #1
0
void
check_one (const char *name, mpz_srcptr x, double y, int cmp, int cmpabs)
{
  int   got;

  got = mpz_cmp_d (x, y);
  if (SGN(got) != cmp)
    {
      unsigned i;
      printf    ("mpz_cmp_d wrong (from %s)\n", name);
      printf    ("  got  %d\n", got);
      printf    ("  want %d\n", cmp);
    fail:
      printf ("  x=");
      mpz_out_str (stdout, 10, x);
      printf    ("\n  y %g\n", y);
      printf ("  x=0x");
      mpz_out_str (stdout, -16, x);
      printf    ("\n  y %g\n", y);
      printf    ("  y");
      for (i = 0; i < sizeof(y); i++)
        printf (" %02X", (unsigned) ((unsigned char *) &y)[i]);
      printf ("\n");
      abort ();
    }

  got = mpz_cmpabs_d (x, y);
  if (SGN(got) != cmpabs)
    {
      printf    ("mpz_cmpabs_d wrong\n");
      printf    ("  got  %d\n", got);
      printf    ("  want %d\n", cmpabs);
      goto fail;
    }
}
Пример #2
0
void
testmain (int argc, char **argv)
{
  unsigned i;
  mpz_t a, b, res, ref;

  mpz_init (a);
  mpz_init (b);
  mpz_init (res);
  mpz_init (ref);

  for (i = 0; i < COUNT; i++)
    {
      mini_random_op3 (OP_MUL, MAXBITS, a, b, ref);
      if (mpz_sgn(ref) == 0)
	/* my_mpz_mul requires a != 0, b != 0 */
	continue;
      my_mpz_mul (res, a, b);
      if (mpz_cmp (res, ref))
	{
	  fprintf (stderr, "my_mpz_mul failed:\n");
	  dump ("a", a);
	  dump ("b", b);
	  dump ("r", res);
	  dump ("ref", ref);
	  abort ();
	}
      /* The following test exploits a side-effect of my_mpz_mul: res
	 points to a buffer with at least an+bn limbs, and the limbs
	 above the result are zeroed. */
      if (mpz_size (b) > 0 && mpz_getlimbn (res, mpz_size(a)) != mpz_limbs_read (res) [mpz_size(a)])
	{
	  fprintf (stderr, "getlimbn - limbs_read differ.\n");
	  abort ();
	}
      if ((i % 4 == 0) && mpz_size (res) > 1)
	{
	  mpz_realloc2 (res, 1);
	  if (mpz_cmp_ui (res, 0))
	    {
	      fprintf (stderr, "mpz_realloc2 did not clear res.\n");
	      abort ();
	    }
	  mpz_limbs_finish (ref, 0);
	  if (mpz_cmp_d (ref, 0))
	    {
	      fprintf (stderr, "mpz_limbs_finish did not clear res.\n");
	      abort ();
	    }
	}
    }
  mpz_clear (a);
  mpz_clear (b);
  mpz_clear (res);
  mpz_clear (ref);
}
/*
 * Function:  compute_bbp_first_sum_gmp 
 * --------------------
 * Computes the first summand in the BBP formula using GNU GMP.
 *
 *  d: digit to be calculated
 *  base: the base
 *  c: a fixed positive integer
 *  p: a simple polynomial like x or x^2
 *  start_at_0: start the summation at k=0, if true, at k=1, otherwise.  Most 
 *              instances of the BBP formula, such as pi, have you start at 0.  
 *              But some, such as log(2), have you start at 1.
 *
 *  returns: the value of the first sum
 */
void compute_bbp_first_sum_gmp(mpf_t sum, unsigned long int d, int base, long int c, void (*p)(mpz_t, mpz_t), bool start_at_0) {
    mpf_set_d(sum, 0.0);
    signed long int k_start = start_at_0 ? 0 : 1;

    mpz_t k;
    mpz_init_set_si(k, k_start);
    double upper = floor((double) d / (double) c);
    while (mpz_cmp_d(k, upper) <= 0)
    {        
        mpz_t poly_result;
        mpz_init(poly_result);
        (*p)(poly_result, k);
        
        mpz_t num;
        mpz_init(num);
        
        mpz_t exponent;
        mpz_init_set(exponent, k);
        mpz_mul_si(exponent, exponent, c);
        mpz_mul_si(exponent, exponent, -1);
        mpz_add_ui(exponent, exponent, d);
        
        modular_pow_gmp(num, base, exponent, poly_result);
        mpf_t num_float;
        mpf_init(num_float);
        mpf_set_z(num_float, num);
        mpz_clear(num);
        mpz_clear(exponent);
        
        mpf_t denom;
        mpf_init_set_d(denom, mpz_get_d(poly_result));
        
        mpz_clear(poly_result);
        
        mpf_t quotient;
        mpf_init(quotient);
        mpf_div(quotient, num_float, denom);        
        mpf_clear(num_float);
        mpf_clear(denom);
        
        mpf_add(sum, sum, quotient);
        mpf_clear(quotient);
        
        mod_one_gmp(sum, sum);
        
        mpz_add_ui(k, k, 1);
    }
    mpz_clear(k);
        
    mod_one_gmp(sum, sum);
}
Пример #4
0
/* Input: p is the initial generator (sigma), if 0, generate it at random.
          N is the number to factor
	  B1 is the stage 1 bound
	  B2 is the stage 2 bound
	  B1done is the stage 1 limit to which supplied residue has 
	    already been computed
          k is the number of blocks for stage 2
          verbose is the verbosity level
   Output: f is the factor found, p is the residue at end of stage 1
   Return value: non-zero iff a factor is found (1 for stage 1, 2 for stage 2)
*/
int
pm1 (mpz_t f, mpz_t p, mpz_t N, mpz_t go, double *B1done, double B1,
     mpz_t B2min_parm, mpz_t B2_parm, double B2scale, unsigned long k, 
     const int S, int verbose, int repr, int use_ntt, FILE *os, FILE *es, 
     char *chkfilename, char *TreeFilename, double maxmem, 
     gmp_randstate_t rng, int (*stop_asap)(void))
{
  int youpi = ECM_NO_FACTOR_FOUND;
  int base2 = 0;
  int Nbits, smallbase;
  int po2 = 0;    /* Whether we should use power-of-2 poly degree */
  long st;
  mpmod_t modulus;
  mpres_t x;
  mpz_t B2min, B2; /* Local B2, B2min to avoid changing caller's values */
  unsigned long dF;
  root_params_t root_params;
  faststage2_param_t faststage2_params;
  /* If stage2_variant != 0, we use the new fast stage 2 */
  const int stage2_variant = (S == 1 || S == ECM_DEFAULT_S);

  set_verbose (verbose);
  ECM_STDOUT = (os == NULL) ? stdout : os;
  ECM_STDERR = (es == NULL) ? stdout : es;

  /* if n is even, return 2 */
  if (mpz_divisible_2exp_p (N, 1))
    {
      mpz_set_ui (f, 2);
      return ECM_FACTOR_FOUND_STEP1;
    }

  st = cputime ();

  if (mpz_cmp_ui (p, 0) == 0)
    pm1_random_seed (p, N, rng);
  
  mpz_init_set (B2min, B2min_parm);
  mpz_init_set (B2, B2_parm);
  
  /* Set default B2. See ecm.c for comments */
  if (ECM_IS_DEFAULT_B2(B2))
    {
      if (stage2_variant == 0)
        mpz_set_d (B2, B2scale * pow (B1 * PM1_COST, DEFAULT_B2_EXPONENT));
      else
        mpz_set_d (B2, B2scale * pow (B1 * PM1FS2_COST, 
                   PM1FS2_DEFAULT_B2_EXPONENT));
    }
  
  /* set B2min */
  if (mpz_sgn (B2min) < 0)
    mpz_set_d (B2min, B1);

  if (repr != ECM_MOD_DEFAULT && repr != ECM_MOD_NOBASE2)
    {
      if (repr == ECM_MOD_MODMULN)
        mpmod_init_MODMULN (modulus, N);
      else if (repr == ECM_MOD_REDC)
        mpmod_init_REDC (modulus, N);
      else if (abs (repr) > 16)
        {
          if (mpmod_init_BASE2 (modulus, repr, N) == ECM_ERROR)
            return ECM_ERROR;
        }
      else
        mpmod_init_MPZ (modulus, N);
    }
  else /* automatic choice */
    {
      /* Find a good arithmetic for this number */
      Nbits = mpz_sizeinbase (N, 2);
      base2 = (repr == 0) ? isbase2 (N, BASE2_THRESHOLD) : 0;
      smallbase = mpz_fits_uint_p (p);

      /* TODO: make dependent on Nbits and base2 */
      if (base2)
        {
          mpmod_init_BASE2 (modulus, base2, N);
        }

      else if (mpz_size (N) <= 2 * POWM_THRESHOLD && smallbase && B1 <= 1e6)
      /* Below POWM_THRESHOLD, mpz_powm uses MODMULN reduction, too, but 
         without special code for small bases which makes our MODMULN
         faster. Above POWM_THRESHOLD mpz_powm uses faster mod reduction,
         at about 2*POWM_THRESHOLD it catches up with our smallbase-MODMULN
         and then is faster until REDC takes over. */
        {
	  outputf (OUTPUT_VERBOSE, "Using MODMULN\n");
          mpmod_init_MODMULN (modulus, N);
        }
      else if (Nbits > 50000 ||  (Nbits > 3500 && smallbase))
        {
	  outputf (OUTPUT_VERBOSE, "Using REDC\n");
          mpmod_init_REDC (modulus, N);
        }
      else
        {
	  outputf (OUTPUT_VERBOSE, "Using mpz_powm\n");
          mpmod_init_MPZ (modulus, N);
        }
    }
  

  /* Determine parameters (polynomial degree etc.) */

  if (stage2_variant != 0)
    {
      long P_ntt, P_nontt;
      const unsigned long lmax = 1UL<<28; /* An upper bound */
      unsigned long lmax_NTT, lmax_noNTT;
      faststage2_param_t params_ntt, params_nontt, *better_params;

      mpz_init (faststage2_params.m_1);
      faststage2_params.l = 0;
      mpz_init (params_ntt.m_1);
      params_ntt.l = 0;
      mpz_init (params_nontt.m_1);
      params_nontt.l = 0;

      /* Find out what the longest transform length is we can do at all.
	 If no maxmem is given, the non-NTT can theoretically do any length. */

      lmax_NTT = 0;
      if (use_ntt)
	{
	  unsigned long t;
	  /* See what transform length the NTT can handle (due to limited 
	     primes and limited memory) */
	  t = mpzspm_max_len (N);
	  lmax_NTT = MIN (lmax, t);
	  if (maxmem != 0.)
	    {
	      t = pm1fs2_maxlen (double_to_size (maxmem), N, use_ntt);
	      lmax_NTT = MIN (lmax_NTT, t);
	    }
	  outputf (OUTPUT_DEVVERBOSE, "NTT can handle lmax <= %lu\n", lmax_NTT);
          /* FIXME: if both ntt and no-ntt are tried, but finally ntt is
             preferred, the last B2 bound computed is that of no-ntt,
             which is thus wrong */
          P_ntt = choose_P (B2min, B2, lmax_NTT, k, &params_ntt, 
                            B2min, B2, 1, ECM_PM1);
          if (P_ntt != ECM_ERROR)
            outputf (OUTPUT_DEVVERBOSE, 
	             "Parameters for NTT: P=%lu, l=%lu\n", 
	             params_ntt.P, params_ntt.l);
	}
      else
        P_ntt = 0; /* or GCC complains about uninitialized var */
      
      /* See what transform length the non-NTT code can handle */
      lmax_noNTT = lmax;
      if (maxmem != 0.)
	{
	  unsigned long t;
	  t = pm1fs2_maxlen (double_to_size (maxmem), N, 0);
	  lmax_noNTT = MIN (lmax_noNTT, t);
	  outputf (OUTPUT_DEVVERBOSE, "non-NTT can handle lmax <= %lu\n", 
		   lmax_noNTT);
	}
      if (use_ntt != 2)
        P_nontt = choose_P (B2min, B2, lmax_noNTT, k, &params_nontt, 
                            B2min, B2, 0, ECM_PM1);
      else
        P_nontt = ECM_ERROR;
      if (P_nontt != ECM_ERROR)
        outputf (OUTPUT_DEVVERBOSE, 
                 "Parameters for non-NTT: P=%lu, l=%lu\n", 
                 params_nontt.P, params_nontt.l);
      
      if (((!use_ntt || P_ntt == ECM_ERROR) && P_nontt == ECM_ERROR) ||
          (use_ntt == 2 && P_ntt == ECM_ERROR))
        {
          outputf (OUTPUT_ERROR, 
                   "Error: cannot choose suitable P value for your stage 2 "
                   "parameters.\nTry a shorter B2min,B2 interval.\n");
          mpz_clear (faststage2_params.m_1);
          mpz_clear (params_ntt.m_1);
          mpz_clear (params_nontt.m_1);
          return ECM_ERROR;
        }

      /* Now decide wether to take NTT or non-NTT.
         How to choose the better one is not an easy question.
         It will depend on the speed ratio between NTT/non-NTT code,
         their difference in memory use and available memory.
         For now, we choose the one that uses a longer transform length.
         FIXME: Write something not brain-dead here */
      if (use_ntt == 0 || P_ntt == ECM_ERROR ||
          (use_ntt == 1 && params_nontt.l > params_ntt.l))
        {
          better_params = &params_nontt;
          use_ntt = 0;
        }
      else
        {
          better_params = &params_ntt;
          use_ntt = 1;
        }

      faststage2_params.P = better_params->P;
      faststage2_params.s_1 = better_params->s_1;
      faststage2_params.s_2 = better_params->s_2;
      faststage2_params.l = better_params->l;
      mpz_set (faststage2_params.m_1, better_params->m_1);

      mpz_clear (params_ntt.m_1);
      mpz_clear (params_nontt.m_1);
      
      if (maxmem != 0.)
	  outputf (OUTPUT_VERBOSE, "Using lmax = %lu with%s NTT which takes "
		   "about %luMB of memory\n", faststage2_params.l, 
		   (use_ntt) ? "" : "out", 
		   pm1fs2_memory_use (faststage2_params.l, N, use_ntt)/1048576);
    }
  else
    {
      mpz_init (root_params.i0);
      root_params.d2 = 0; /* Enable automatic choice of d2 */
      
      if (use_ntt || (modulus->repr == ECM_MOD_BASE2 && modulus->Fermat > 0))
	po2 = 1;

      if (bestD (&root_params, &k, &dF, B2min, B2, po2, use_ntt, maxmem,
                 (TreeFilename != NULL), modulus) == ECM_ERROR)
	{
	  youpi = ECM_ERROR;
	  goto clear_and_exit;
	}
  
      root_params.S = S;
      /* Set default degree for Brent-Suyama extension */
      if (root_params.S == ECM_DEFAULT_S)
	{
	  if (modulus->repr == ECM_MOD_BASE2 && modulus->Fermat > 0)
	    {
	      /* For Fermat numbers, default is 2 (no Brent-Suyama) */
	      root_params.S = 2;
	    }
	  else
	    {
	      mpz_t t;
	      mpz_init (t);
	      mpz_sub (t, B2, B2min);
	      if (mpz_cmp_d (t, 3.5e5) < 0) /* B1 < 50000 */
		root_params.S = -4; /* Dickson polys give a slightly better chance of success */
	      else if (mpz_cmp_d (t, 1.1e7) < 0) /* B1 < 500000 */
		root_params.S = -6;
	      else if (mpz_cmp_d (t, 1.25e8) < 0) /* B1 < 3000000 */
		root_params.S = 12; /* but for S>6, S-th powers are faster thanks to invtrick */
	      else if (mpz_cmp_d (t, 7.e9) < 0) /* B1 < 50000000 */
		root_params.S = 24;
	      else if (mpz_cmp_d (t, 1.9e10) < 0) /* B1 < 100000000 */
		root_params.S = 48;
	      else if (mpz_cmp_d (t, 5.e11) < 0) /* B1 < 1000000000 */
		root_params.S = 60;
	      else
		root_params.S = 120;
	      mpz_clear (t);
	    }
	}
      
      /* We need Suyama's power even and at least 2 for P-1 stage 2 to work 
	 correctly */

      if (root_params.S & 1)
	root_params.S *= 2; /* FIXME: Is this what the user would expect? */
    }
  
  /* Print B1, B2, polynomial and x0 */
  print_B1_B2_poly (OUTPUT_NORMAL, ECM_PM1, B1, *B1done, B2min_parm, B2min, 
		    B2, (stage2_variant == 0) ? root_params.S : 1, p, 0, NULL);

  /* If we do a stage 2, print its parameters */
  if (mpz_cmp (B2, B2min) >= 0)
    {
      if (stage2_variant != 0)
        outputf (OUTPUT_VERBOSE, "P = %lu, l = %lu, s_1 = %lu, k = s_2 = %lu, "
                 "m_1 = %Zd\n", faststage2_params.P, faststage2_params.l,
                 faststage2_params.s_1,faststage2_params.s_2,
                 faststage2_params.m_1);
      else
        outputf (OUTPUT_VERBOSE, "dF=%lu, k=%lu, d=%lu, d2=%lu, i0=%Zd\n", 
                 dF, k, root_params.d1, root_params.d2, root_params.i0);
    }

  if (test_verbose (OUTPUT_VERBOSE))
    {
      if (mpz_sgn (B2min_parm) >= 0)
        {
          outputf (OUTPUT_VERBOSE, 
            "Can't compute success probabilities for B1 <> B2min\n");
        }
      else
        {
          rhoinit (256, 10);
          print_prob (B1, B2, dF, k, 
                      (stage2_variant == 0) ? root_params.S : 1, go);
        }
    }


  mpres_init (x, modulus);
  mpres_set_z (x, p, modulus);

  st = cputime ();

  if (B1 > *B1done)
    youpi = pm1_stage1 (f, x, modulus, B1, B1done, go, stop_asap, chkfilename);

  st = elltime (st, cputime ());

  outputf (OUTPUT_NORMAL, "Step 1 took %ldms\n", st);
  if (test_verbose (OUTPUT_RESVERBOSE))
    {
      mpz_t tx;
      mpz_init (tx);
      mpres_get_z (tx, x, modulus);
      outputf (OUTPUT_RESVERBOSE, "x=%Zd\n", tx);
      mpz_clear (tx);
    }

  if (stop_asap != NULL && (*stop_asap) ())
    goto clear_and_exit;

  if (youpi == ECM_NO_FACTOR_FOUND && mpz_cmp (B2, B2min) >= 0)
    {
      if (stage2_variant != 0)
        {
          if (use_ntt)
            youpi = pm1fs2_ntt (f, x, modulus, &faststage2_params);
          else
            youpi = pm1fs2 (f, x, modulus, &faststage2_params);
        }
      else
        youpi = stage2 (f, &x, modulus, dF, k, &root_params, ECM_PM1, 
                        use_ntt, TreeFilename, stop_asap);
    }

  if (test_verbose (OUTPUT_VERBOSE))
    {
      if (mpz_sgn (B2min_parm) < 0)
        rhoinit (1, 0); /* Free memory of rhotable */
    }

clear_and_exit:
  mpres_get_z (p, x, modulus);
  mpres_clear (x, modulus);
  mpmod_clear (modulus);
  if (stage2_variant != 0)
    mpz_clear (faststage2_params.m_1);
  else
    mpz_clear (root_params.i0);
  mpz_clear (B2);
  mpz_clear (B2min);

  return youpi;
}
Пример #5
0
static int _compf(CBIGINT *a, double f, bool invert)
{
	return mpz_cmp_d(a->n, f);
}
Пример #6
0
static int _equalf(CBIGINT *a, double f, bool invert)
{
	return mpz_cmp_d(a->n, f) == 0;
}
Пример #7
0
void
testmain (int argc, char **argv)
{
  unsigned i;
  mpz_t x;

  for (i = 0; values[i].s; i++)
    {
      char *s;
      mpz_init_set_d (x, values[i].d);
      s = mpz_get_str (NULL, 16, x);
      if (strcmp (s, values[i].s) != 0)
	{
	  fprintf (stderr, "mpz_set_d failed:\n"
		   "d = %.20g\n"
		   "s = %s\n"
		   "r = %s\n",
		   values[i].d, s, values[i].s);
	  abort ();
	}
      testfree (s);
      mpz_clear (x);
    }

  mpz_init (x);

  for (i = 0; i < COUNT; i++)
    {
      /* Use volatile, to avoid extended precision in floating point
	 registers, e.g., on m68k and 80387. */
      volatile double d, f;
      unsigned long m;
      int e;

      mini_rrandomb (x, GMP_LIMB_BITS);
      m = mpz_get_ui (x);
      mini_urandomb (x, 8);
      e = mpz_get_ui (x) - 100;

      d = ldexp ((double) m, e);
      mpz_set_d (x, d);
      f = mpz_get_d (x);
      if (f != floor (d))
	{
	  fprintf (stderr, "mpz_set_d/mpz_get_d failed:\n");
	  goto dumperror;
	}
      if ((f == d) ? (mpz_cmp_d (x, d) != 0) : (mpz_cmp_d (x, d) >= 0))
	{
	  fprintf (stderr, "mpz_cmp_d (x, d) failed:\n");
	  goto dumperror;
	}
      f = d + 1.0;
      if (f > d && ! (mpz_cmp_d (x, f) < 0))
	{
	  fprintf (stderr, "mpz_cmp_d (x, f) failed:\n");
	  goto dumperror;
	}

      d = - d;

      mpz_set_d (x, d);
      f = mpz_get_d (x);
      if (f != ceil (d))
	{
	  fprintf (stderr, "mpz_set_d/mpz_get_d failed:\n");
	dumperror:
	  dump ("x", x);
	  fprintf (stderr, "m = %lx, e = %i\n", m, e);
	  fprintf (stderr, "d = %.15g\n", d);
	  fprintf (stderr, "f = %.15g\n", f);
	  fprintf (stderr, "f - d = %.5g\n", f - d);
	  abort ();
	}
      if ((f == d) ? (mpz_cmp_d (x, d) != 0) : (mpz_cmp_d (x, d) <= 0))
	{
	  fprintf (stderr, "mpz_cmp_d (x, d) failed:\n");
	  goto dumperror;
	}
      f = d - 1.0;
      if (f < d && ! (mpz_cmp_d (x, f) > 0))
	{
	  fprintf (stderr, "mpz_cmp_d (x, f) failed:\n");
	  goto dumperror;
	}
    }

  mpz_clear (x);
}
Пример #8
0
	int32_t Integer::operator != (const float l) const
	{
		return mpz_cmp_d((mpz_srcptr)&gmp_rep, (float)  l) != 0;
	}
Пример #9
0
	int32_t Integer::operator != (const double l) const
	{
		return mpz_cmp_d((mpz_srcptr)&gmp_rep,  l) != 0;
	}
float check_contraction(int fil,int stickers,int lane, float c0, mpz_t states,gsl_rng *r,FILE *fp){
	int newlane=lane-1;
	int ret=0;
	mpz_t newstates;
	mpz_init(newstates);
	float domega=0;
	// clock_t t3 = clock();
	count_isl_single(&newstates,fil,stickers,newlane);
	// clock_t t4 = clock();
	// printf("contraction time: %f\n",(double)(t4-t3)/CLOCKS_PER_SEC);
	float curv1=1.0/lane;
	float curv2=1.0/newlane;
	float k=10000.0;
	if (mpz_cmp_d(newstates,0.0)){
		domega=k*(curv2*curv2 - curv1*curv1 -2.0*c0*(curv2-curv1))-mpzln(newstates)+mpzln(states);
		//fprintf(fp,"curvature: %f entropy: %f\n",k*(curv2*curv2 - curv1*curv1 -2.0*c0*(curv2-curv1)),-mpzln(newstates)+mpzln(states));

	}else{
		domega=VERYBIG;
	}
	// fprintf(fp, "current domega for contraction=%f\n",domega);


// 	if (domega<0){
// 		ret=ret-1;
//
// 		//fprintf(fp,"contraction - domega=%f\n",domega);
// 	}
//
//
// /*if it's positive, we calculate the probability of acceptance
//  * and test for it*/
// 	else{
// 		double prob=exp(-1.0*domega);
// 		double fromthehat=gsl_rng_uniform(r);
// 		//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
// 		if (fromthehat<prob){
// 			ret=ret-1;
//
// 			//fprintf(fp,"contraction - domega=%f\n",domega);
// 		}else{
// 			//fprintf(fp,"no contraction - domega=%f\n",domega);
// 		}
// 	}
//
//
// 	newlane=lane+1;
// 	count_isl_single(&newstates,fil,stickers,newlane);
//
// 	curv2=1.0/newlane;
// 	domega=k*(curv2*curv2 - curv1*curv1 -2.0*c0*(curv2-curv1))-mpzln(newstates)+mpzln(states);
// 	if (domega<0){
// 		ret=ret+1;
//
// 		//fprintf(fp,"expansion - domega=%f\n",domega);
// 	}
//
//
// /*if it's positive, we calculate the probability of acceptance
//  * and test for it*/
// 	else{
// 		double prob=exp(-1.0*domega);
// 		double fromthehat=gsl_rng_uniform(r);
// 		//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
// 		if (fromthehat<prob){
//
// 			ret=ret+1;
// 			//fprintf(fp,"expansion - domega=%f\n",domega);
// 		}else{
// 			//fprintf(fp,"no expansion - domega=%f\n",domega);
// 		}
// 	}
//

	mpz_clear(newstates);
	return domega;
}
void simulation_single(){

	const int num_lanes=2;
	int lane_size=100;
	const gsl_rng_type * T;
	gsl_rng_env_setup();
	T = gsl_rng_default;
	gsl_rng *r;
	r = gsl_rng_alloc (T);
	unsigned long int seed;
	seed=gen_seed();
		gsl_rng_set(r,seed);
	int fil_length=150;
	int stickers=1;
	//glue-related!
	//int stickers=0;
	mpz_t states;
	mpz_t newstates;
	mpz_t deltastates;
	mpz_init(states);
	mpz_init(newstates);
	mpz_init(deltastates);

	const float timesteps=5000;
	int my_rank;
	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
	char* filename[60];
  sprintf(filename,"./output_single_filament_compact/run%d.txt",my_rank);
	// sprintf(filename,"./output_single_filament_glue_%.2f/run%d.txt",kstick,my_rank);
	printf("%s\n",filename);
	FILE *fp = fopen(filename, "w");
	if (fp == NULL) {
    	printf("Error");
			return;
    }
	float mu=6.0;
	float glue=1.0;
	float koff=1.0;
	float i;
	int j,k;
	float kstick=0.01;
	float kunstick=0.01;
	float stick_energy=3.0;
	int type=0;

	float nextoff=gsl_ran_exponential(r,1.0/koff);
	float nextstick=gsl_ran_exponential(r,1.0/((fil_length-lane_size-stickers)*kstick));
	float nextunstick=gsl_ran_exponential(r,1.0/(stickers*kunstick));
	//glue-related!
	// float nextstick=VERYBIG;
	// float nextunstick=VERYBIG;
	float peroverlap=kstick;
	double domega;
	float c0=1.0/lane_size;

	int att_depol=0;
	int acc_depol=0;
	int att_stick=0;
	int acc_stick=0;
	int att_unstick=0;
	int acc_unstick=0;
	int att_contr=0;
	int acc_contr=0;
	int att_expan=0;
	int acc_expan=0;
	int att_special=0;
	int acc_special=0;
	float eta=0.2;
	float fraction=0.0;
	float delta=0.0;
	clock_t t1 = clock();
	//printf("before first count: %f fil_length: %d\n",kstick,fil_length);
	count_isl_single(&states,fil_length,stickers,lane_size);
	gmp_printf("states= %Zd\n",states);
	int currpar=0;

	for (i=0;i<timesteps;i=i+0.01){
		fraction=fraction+0.01*delta;
		//printf("%f %f %d\n",fraction,delta,currpar);
		// if ((int)(fraction*20)%2!=currpar){
		// 	fprintf(fp, "fraction=%f delta=%f\n",fraction,delta);
		//
		// }
		// 	currpar=(int)(fraction*20)%2;

		if (fabs(fraction)>1.0){
			//fprintf(fp,"event occurring - i=%f delta=%f fraction=%f\n",i,delta,fraction);
			if (fraction>0){
				delta=check_contraction(fil_length,stickers,lane_size+1,c0,states,r,fp);
				if (delta>VERYBIG/10){

					delta=0;
					fraction=0;
					//fprintf(fp,"delta too big! delta is now %f\n",delta);
				}else{
					lane_size++;
				}

			}
			else{
				delta=check_contraction(fil_length,stickers,lane_size-1,c0,states,r,fp);
				if (delta>VERYBIG/10){
					delta=0;
					fraction=0;
					//fprintf(fp,"delta too big! delta is now %f\n",delta);
				}else{
					lane_size--;
				}
			}
			fraction=0;
			nextstick=i+gsl_ran_exponential(r,1.0/((fil_length-lane_size-stickers)*kstick));


		}

		if (stickers==0){
			nextunstick=VERYBIG;
		}
		if (fil_length-lane_size-stickers<=0){
			nextstick=VERYBIG;
		}
		//fprintf(fp, "fraction=%f delta=%f\n",fraction,delta);
		//printf("%f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d\n", i,nextoff,nextstick,nextunstick,fil_length,stickers,lane_size,att_depol,acc_depol,att_stick,acc_stick,att_unstick,acc_unstick,att_contr,acc_contr,att_expan,acc_expan);
		if (fil_length==0){
			break;
		}
		if ((int)(i*100)%(int)timesteps==0){
			clock_t t2 = clock();
			printf("%d percent %f\n",(int)(i*100)/(int)timesteps,(double)(t2-t1)/CLOCKS_PER_SEC);
		}
		//fprintf(fp,"i=%f\n",i);
		if ((int)(i*100)%50==0){
			fprintf(fp, "%f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %f %f %f %f\n", i,nextoff,nextstick,nextunstick,fil_length,stickers,lane_size,att_depol,acc_depol,att_stick,acc_stick,att_unstick,acc_unstick,att_special,acc_special,((fil_length-lane_size-stickers)*kstick),(stickers*kunstick),delta,fraction);
			//gmp_fprintf(fp,"states= %Zd\n",states);
		}

		if (i>=nextoff){
			type=1;}
		if (i>=nextstick){
			type=2;
		}
		if (i>=nextunstick){
			type=3;
		}

		if (type==1){
			int done=0;
			att_depol=att_depol+1;
			int newlength=fil_length-1;
			// clock_t t3 = clock();
			count_isl_single(&newstates,newlength,stickers,lane_size);
			// clock_t t4 = clock();
			// printf("depol time: %f\n",(double)(t4-t3)/CLOCKS_PER_SEC);
			if (mpz_cmp_d(newstates,0.0)){
				domega=-mu+glue-mpzln(newstates)+mpzln(states);
				//glue-related!
				// domega=-mu+glue+peroverlap-mpzln(newstates)+mpzln(states);
				if (domega<0){
					acc_depol++;
					fil_length=newlength;
					mpz_set(states,newstates);
					done=1;
					// fprintf(fp,"depol - domega=%f\n",domega);
				}


			/*if it's positive, we calculate the probability of acceptance
			 * and test for it*/
				else{
					double prob=exp(-1.0*domega);
					double fromthehat=gsl_rng_uniform(r);
					//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
					if (fromthehat<prob){
						fil_length=newlength;
						acc_depol++;
						mpz_set(states,newstates);
						done=1;
						// fprintf(fp,"depol - domega=%f\n",domega);

					}else{
	          // fprintf(fp,"removal not accepted - domega=%f\n",domega);
	        }
				}
			}
			if (done==0){
					att_special++;
					// clock_t t3 = clock();
					count_isl_single(&newstates,newlength,stickers-1,lane_size);
					// clock_t t4 = clock();
					// printf("special depol time: %f\n",(double)(t4-t3)/CLOCKS_PER_SEC);

					domega=stick_energy-mu+glue-mpzln(newstates)+mpzln(states);
					if (domega<0){

						fil_length=newlength;
						stickers=stickers-1;
						acc_depol++;
						acc_special++;
						mpz_set(states,newstates);
						//fprintf(fp,"depol and removal - domega=%f\n",domega);
					}
					else{
						double prob=exp(-1.0*domega);
						double fromthehat=gsl_rng_uniform(r);
						//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
						if (fromthehat<prob){
							fil_length=newlength;
							stickers=stickers-1;
							acc_depol++;
							acc_special++;
							mpz_set(states,newstates);
							 //fprintf(fp,"depol and removal - domega=%f\n",domega);

						}else{
		          // fprintf(fp,"depol w/unstick not accepted - domega=%f\n",domega);
		        }
					}
			}

			att_contr++;
			att_expan++;
			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			delta=delta/eta;
			// if (delta==-1){
			// 	acc_contr++;
			// }
			// if (delta==+1){
			// 	acc_expan++;
			// }
			// lane_size=lane_size+delta;
			nextoff=i+gsl_ran_exponential(r,1.0/koff);
			nextstick=i+gsl_ran_exponential(r,1.0/((fil_length-lane_size-stickers)*kstick));
			type=0;
		}



		if (type==2){
			att_stick++;
			int newstickers=stickers+1;
			// clock_t t3 = clock();
			count_isl_single(&newstates,fil_length,newstickers,lane_size);
			// clock_t t4 = clock();
			// printf("new sticker time: %f\n",(double)(t4-t3)/CLOCKS_PER_SEC);

			domega=-stick_energy-mpzln(newstates)+mpzln(states);
			if (domega<0){
				stickers=newstickers;
				acc_stick++;
				mpz_set(states,newstates);
				// fprintf(fp,"added sticker - domega=%f\n",domega);

			}


		/*if it's positive, we calculate the probability of acceptance
		 * and test for it*/
			else{
				double prob=exp(-1.0*domega);
				double fromthehat=gsl_rng_uniform(r);
				//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
				if (fromthehat<prob){
					stickers=newstickers;
					acc_stick++;
					mpz_set(states,newstates);
					// fprintf(fp,"added sticker - domega=%f\n",domega);
				}else{
          // fprintf(fp,"addition sticker rejected - domega=%f\n",domega);
        }
			}

			att_contr++;
			att_expan++;
			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			delta=delta/eta;
			// if (delta==-1){
			// 	acc_contr++;
			// }
			// if (delta==+1){
			// 	acc_expan++;
			// }
			// lane_size=lane_size+delta;
			nextstick=i+gsl_ran_exponential(r,1.0/((fil_length-lane_size-stickers)*kstick));
			nextunstick=i+gsl_ran_exponential(r,1.0/(stickers*kunstick));
			type=0;

		}

		if (type==3){
			att_unstick++;
			int newstickers=stickers-1;

			// clock_t t3 = clock();
			count_isl_single(&newstates,fil_length,newstickers,lane_size);
			// clock_t t4 = clock();
			// printf("remove sticker time: %f\n",(double)(t4-t3)/CLOCKS_PER_SEC);
			domega=stick_energy-mpzln(newstates)+mpzln(states);
			if (domega<0){
				acc_unstick++;
				stickers=newstickers;
				mpz_set(states,newstates);
			 //fprintf(fp,"removal - domega=%f\n",domega);
			}


		/*if it's positive, we calculate the probability of acceptance
		 * and test for it*/
			else{
				double prob=exp(-1.0*domega);
				double fromthehat=gsl_rng_uniform(r);
				//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
				if (fromthehat<prob){
					stickers=newstickers;
					acc_unstick++;
					mpz_set(states,newstates);
				 //fprintf(fp,"removal - domega=%f\n",domega);
				}else{
          // fprintf(fp,"removal of sticker not accepted - domega=%f\n",domega);
        }
			}
			att_contr++;
			att_expan++;
			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			delta=delta/eta;

			// if (delta==-1){
			// 	acc_contr++;
			// }
			// if (delta==+1){
			// 	acc_expan++;
			// }
			// lane_size=lane_size+delta;
			nextunstick=i+gsl_ran_exponential(r,1.0/(stickers*kunstick));
			nextstick=i+gsl_ran_exponential(r,1.0/((fil_length-lane_size-stickers)*kstick));
			type=0;

		}



	}
	mpz_clear(states);
  mpz_clear(newstates);
  mpz_clear(deltastates);
  gsl_rng_free (r);
 	fclose(fp);

}
void simulation_single(float kstick){

	const int num_lanes=2;
	int lane_size=1000;
	const gsl_rng_type * T;
	gsl_rng_env_setup();
	T = gsl_rng_default;
	gsl_rng *r;
	r = gsl_rng_alloc (T);
	unsigned long int seed;
	seed=gen_seed();
		gsl_rng_set(r,seed);
	int fil_length=1500;
	int stickers=1;
	//glue-related!
	//int stickers=0;
	mpz_t states;
	mpz_t newstates;
	mpz_t deltastates;
	mpz_init(states);
	mpz_init(newstates);
	mpz_init(deltastates);

	float timesteps=50000;
	int my_rank;
	MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
	char* filename[60];
  sprintf(filename,"./output_single_filament_strong_%.2f/run%d.txt",kstick,my_rank);
	// sprintf(filename,"./output_single_filament_glue_%.2f/run%d.txt",kstick,my_rank);
	printf("%s\n",filename);
	FILE *fp = fopen(filename, "w");
	if (fp == NULL) {
    	printf("Error");
			return;
    }
	float mu=6.0;
	float glue=1.0;
	float koff=1.0;
	float i;
	int j,k;
	//float kstick=0.05;
	float kunstick=kstick;
	float stick_energy=8.0;
	int type=0;
	int delta=0;
	float nextoff=gsl_ran_exponential(r,1.0/koff);
	float nextstick=gsl_ran_exponential(r,1.0/kstick);
	float nextunstick=gsl_ran_exponential(r,1.0/kunstick);
	//glue-related!
	// float nextstick=VERYBIG;
	// float nextunstick=VERYBIG;
	float peroverlap=kstick;
	double domega;
	float c0=1.0/lane_size;

	int att_depol=0;
	int acc_depol=0;
	int att_stick=0;
	int acc_stick=0;
	int att_unstick=0;
	int acc_unstick=0;
	int att_contr=0;
	int acc_contr=0;
	int att_expan=0;
	int acc_expan=0;

	count_isl_single(&states,fil_length,stickers,lane_size);


	for (i=0;i<timesteps;i=i+0.01){
		if (fil_length==0){
			break;
		}
		if ((int)(i*100)%(int)timesteps==0){
			printf("%d\%\n",(int)(i*100)/timesteps);
		}
		if ((int)(i*100)%50==0){
			fprintf(fp, "%f %f %f %f %d %d %d %d %d %d %d %d %d %d %d %d %d\n", i,nextoff,nextstick,nextunstick,fil_length,stickers,lane_size,att_depol,acc_depol,att_stick,acc_stick,att_unstick,acc_unstick,att_contr,acc_contr,att_expan,acc_expan);
		}

		if (i>=nextoff){
			type=1;}
		if (i>=nextstick){
			type=2;
		}
		if (i>=nextunstick){
			type=3;
		}

		if (type==1){
			att_depol=att_depol+1;
			int newlength=fil_length-1;
			count_isl_single(&newstates,newlength,stickers,lane_size);
			if (!mpz_cmp_d(newstates,0.0)){
					count_isl_single(&newstates,newlength,stickers-1,lane_size);
					domega=stick_energy-mu+glue-mpzln(newstates)+mpzln(states);
					if (domega<0){

						fil_length=newlength;
						stickers=stickers-1;
						acc_depol++;
						mpz_set(states,newstates);
						//fprintf(fp,"depol and removal - domega=%f\n",domega);
					}
					else{
						double prob=exp(-1.0*domega);
						double fromthehat=gsl_rng_uniform(r);
						//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
						if (fromthehat<prob){
							fil_length=newlength;
							stickers=stickers-1;
							acc_depol++;
							mpz_set(states,newstates);
							//fprintf(fp,"depol and removal - domega=%f\n",domega);

						}else{
		          //fprintf(fp,"depol w/unstick not accepted - domega=%f\n",domega);
		        }
					}
			}else{
			domega=-mu+glue-mpzln(newstates)+mpzln(states);
			//glue-related!
			// domega=-mu+glue+peroverlap-mpzln(newstates)+mpzln(states);
			if (domega<0){
				acc_depol++;
				fil_length=newlength;
				mpz_set(states,newstates);
				//fprintf(fp,"depol - domega=%f\n",domega);
			}


		/*if it's positive, we calculate the probability of acceptance
		 * and test for it*/
			else{
				double prob=exp(-1.0*domega);
				double fromthehat=gsl_rng_uniform(r);
				//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
				if (fromthehat<prob){
					fil_length=newlength;
					acc_depol++;
					mpz_set(states,newstates);
					//fprintf(fp,"depol - domega=%f\n",domega);

				}else{
          //fprintf(fp,"removal not accepted - domega=%f\n",domega);
        }
			}
		}
			att_contr++;
			att_expan++;
			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			if (delta==-1){
				acc_contr++;
			}
			if (delta==+1){
				acc_expan++;
			}
			lane_size=lane_size+delta;
			nextoff=i+gsl_ran_exponential(r,1.0/koff);
			type=0;
		}



		if (type==2){
			att_stick++;
			int newstickers=stickers+1;
			count_isl_single(&newstates,fil_length,newstickers,lane_size);
			domega=-stick_energy-mpzln(newstates)+mpzln(states);
			if (domega<0){
				stickers=newstickers;
				acc_stick++;
				mpz_set(states,newstates);
				//fprintf(fp,"added sticker - domega=%f\n",domega);

			}


		/*if it's positive, we calculate the probability of acceptance
		 * and test for it*/
			else{
				double prob=exp(-1.0*domega);
				double fromthehat=gsl_rng_uniform(r);
				//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
				if (fromthehat<prob){
					stickers=newstickers;
					acc_stick++;
					mpz_set(states,newstates);
					//fprintf(fp,"added sticker - domega=%f\n",domega);
				}else{
          //fprintf(fp,"addition sticker rejected - domega=%f\n",domega);
        }
			}


			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			if (delta==-1){
				acc_contr++;
			}
			if (delta==+1){
				acc_expan++;
			}
			lane_size=lane_size+delta;
			nextstick=i+gsl_ran_exponential(r,1.0/kstick);
			type=0;

		}

		if (type==3){
			att_unstick++;
			int newstickers=stickers-1;
			count_isl_single(&newstates,fil_length,newstickers,lane_size);
			domega=stick_energy-mpzln(newstates)+mpzln(states);
			if (domega<0){
				acc_unstick++;
				stickers=newstickers;
				mpz_set(states,newstates);
				//fprintf(fp,"removal - domega=%f\n",domega);
			}


		/*if it's positive, we calculate the probability of acceptance
		 * and test for it*/
			else{
				double prob=exp(-1.0*domega);
				double fromthehat=gsl_rng_uniform(r);
				//printf("metropolising: rng=%f, prob=%f\n",fromthehat,prob);
				if (fromthehat<prob){
					stickers=newstickers;
					acc_unstick++;
					mpz_set(states,newstates);
					//fprintf(fp,"removal - domega=%f\n",domega);
				}else{
          //fprintf(fp,"removal of sticker not accepted - domega=%f\n",domega);
        }
			}

			delta=check_contraction(fil_length,stickers,lane_size,c0,states,r,fp);
			if (delta==-1){
				acc_contr++;
			}
			if (delta==+1){
				acc_expan++;
			}
			lane_size=lane_size+delta;
			nextunstick=i+gsl_ran_exponential(r,1.0/kunstick);
			type=0;

		}



	}