Ejemplo n.º 1
0
/**
 * Returns a binomial distributed integer between 0 and n inclusive.
 * NOTE: use n > 0 and 0.0 < p < 1.0
 *
 */
Rand::intType Rand::binomial(intType n, floatType p){
	intType i, x = 0;

	for (i = 0; i < n; ++i)
		x += bernoulli(p);
	return (x);
}
Ejemplo n.º 2
0
bool Bee:: movebee(sf::Time dt) // on modularise car on en a besoin pour targetmove() et randomMove()
{
	double beta(0);
	
	// calcule de la position envisagée en fonction du vecteur vitesse
	Vec2d possible_pos = centre + speed_*dt.asSeconds();
	
	//verifier que l'abeille peut occuper cette position
	if(getAppEnv().world_.isFlyable(possible_pos))
	{
		//si oui bouger le centre du collider abeille
		centre=possible_pos;
		//on s'assure que il fait toujorus partie de la carte
		clamping();
		return 1;
	} else //si la position envisagée n'est pas libre
	{
		//changement de direction dans la sens opposé
		if(bernoulli(prob))
		{	
			beta=PI/4;
		} else
		{
			beta= -PI/4;
		}
		speed_.rotate(beta);
		clamping();
		return 0;
	}
}
Ejemplo n.º 3
0
//déplacement aléatoire
void Bee::randomMove(sf::Time dt)
{
	//changement aléatoire de direction
	if(bernoulli(getConfig()["moving behaviour"]["random"]["rotation probability"].toDouble()))
	{
		double alpha (uniform(-alpha_max,alpha_max));
		speed_.rotate(alpha);
	}
	//avance dans le sens du vecteur vitesse
	movebee(dt);
}
Ejemplo n.º 4
0
static ex zeta1_eval(const ex& m)
{
	if (is_exactly_a<lst>(m)) {
		if (m.nops() == 1) {
			return zeta(m.op(0));
		}
		return zeta(m).hold();
	}

	if (m.info(info_flags::numeric)) {
		const numeric& y = ex_to<numeric>(m);
		// trap integer arguments:
		if (y.is_integer()) {
			if (y.is_zero()) {
				return _ex_1_2;
			}
			if (y.is_equal(*_num1_p)) {
				//return zeta(m).hold();
				return UnsignedInfinity;
			}
			if (y.info(info_flags::posint)) {
				if (y.info(info_flags::odd)) {
					return zeta(m).hold();
				} else {
					return abs(bernoulli(y)) * pow(Pi, y) * pow(*_num2_p, y-(*_num1_p)) / factorial(y);
				}
			} else {
				if (y.info(info_flags::odd)) {
					return -bernoulli((*_num1_p)-y) / ((*_num1_p)-y);
				} else {
					return _ex0;
				}
			}
		}
		// zeta(float)
		if (y.info(info_flags::numeric) && !y.info(info_flags::crational)) {
			return zeta(y); // y is numeric
		}
	}
	return zeta(m).hold();
}
Ejemplo n.º 5
0
void Map::step()
{
	for(int i(0); i < int(seeds_.size()); ++i)
	{
		if(seeds_[i].tileType_ == "water")
		{
			if(bernoulli(waterTpProb_))
			{
				seeds_[i].pos_.y = uniform(0, int(height_-1));
				seeds_[i].pos_.x = uniform(0, int(width_-1));
				tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x] = getCurrentGame().tileAtlas_.at(seeds_[i].tileType_);
				for(int j(-humidityRange_); j<=humidityRange_; ++j)
				{
					for(int k(-humidityRange_); k<=humidityRange_; ++k)
					{
						int index(j*width_ + k + seeds_[i].pos_.y*width_+seeds_[i].pos_.x);
						if(!(index < 0 || index > humidity_.size()-1))
						{
							humidity_[index] += eta_*exp(-sqrt(pow(j,2)+pow(k,2))/lambda_);
						}
					}
				}
			}
			else{ 
				displace(seeds_[i].pos_, width_, height_);
				tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x] = getCurrentGame().tileAtlas_.at(seeds_[i].tileType_);
				for(int j(-humidityRange_); j<=humidityRange_; ++j)
				{
					for(int k(-humidityRange_); k<=humidityRange_; ++k)
					{
						int index(j*width_ + k + seeds_[i].pos_.y*width_+seeds_[i].pos_.x);
						if(!(index < 0 || index > humidity_.size()-1))
						{
							humidity_[index] += eta_*exp(-sqrt(pow(j,2)+pow(k,2))/lambda_);
						}
					}
				}
			}
		}
		else if(seeds_[i].tileType_ == "grass")
		{
			displace(seeds_[i].pos_, width_, height_);
			if(tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x].tileType() != TileType::WATER)
				tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x] = getCurrentGame().tileAtlas_.at(seeds_[i].tileType_);
		}
		else if(seeds_[i].tileType_ == "forest")
		{
			displace(seeds_[i].pos_, width_, height_);
			if(tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x].tileType() != TileType::WATER)
				tiles_[seeds_[i].pos_.y*width_+seeds_[i].pos_.x] = getCurrentGame().tileAtlas_.at(seeds_[i].tileType_);
		}
	}
}
Ejemplo n.º 6
0
ObjectNode* genLeaf(float prob, const mat4& initTrans, const mat4& initSkew) {
	const int colorInd = bernoulli() < prob ? 1 : 0;
	return new ObjectNode(	Global::leaf[colorInd], initTrans * rZ(M_PI/12.0),
							initSkew * rZ(M_PI/12.0)							);
}
Ejemplo n.º 7
0
void 
ONE_commonTerms(ONEdevice *pDevice, BOOLEAN currentOnly, 
                BOOLEAN tranAnalysis, ONEtranInfo *info)
{
  ONEelem *pElem;
  ONEedge *pEdge;
  ONEnode *pNode;
  int index, eIndex;
  double psi1, psi2, psi, nConc=0.0, pConc=0.0, nC, pC, nP1, pP1;
  double dPsiN, dPsiP;
  double bPsiN, dbPsiN, bMPsiN, dbMPsiN;
  double bPsiP, dbPsiP, bMPsiP, dbMPsiP;
  double mun, dMun, mup, dMup;
  double conc1, conc2;
  double cnAug, cpAug;


  /* evaluate all node (including recombination) and edge quantities */
  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
    pElem = pDevice->elemArray[eIndex];
    cnAug = pElem->matlInfo->cAug[ELEC];
    cpAug = pElem->matlInfo->cAug[HOLE];
    for (index = 0; index <= 1; index++) {
      if (pElem->evalNodes[index]) {
	pNode = pElem->pNodes[index];
	if (pNode->nodeType != CONTACT) {
	  psi = pDevice->dcSolution[pNode->psiEqn];
	  if (pElem->elemType == SEMICON) {
	    nConc = pDevice->dcSolution[pNode->nEqn];
	    pConc = pDevice->dcSolution[pNode->pEqn];
	    if (Srh) {
	      recomb(nConc, pConc,
		  pNode->tn, pNode->tp, cnAug, cpAug, pNode->nie,
		  &pNode->uNet, &pNode->dUdN, &pNode->dUdP);
	    } else {
	      pNode->uNet = 0.0;
	      pNode->dUdN = 0.0;
	      pNode->dUdP = 0.0;
	    }
	    if (pNode->baseType == P_TYPE && pConc <= 0.0) {
	      pConc = pNode->na;
	    } else if (pNode->baseType == N_TYPE && nConc <= 0.0) {
	      nConc = pNode->nd;
	    }
	  }
	} else {
	  /* a contact node */
	  psi = pNode->psi;
	  if (pElem->elemType == SEMICON) {
	    nConc = pNode->nConc;
	    pConc = pNode->pConc;
	  }
	}
	/* store info in the state tables */
	*(pDevice->devState0 + pNode->nodePsi) = psi;
	if (pElem->elemType == SEMICON) {
	  *(pDevice->devState0 + pNode->nodeN) = nConc;
	  *(pDevice->devState0 + pNode->nodeP) = pConc;
	  if (tranAnalysis && pNode->nodeType != CONTACT) {
	    pNode->dNdT = integrate(pDevice->devStates, info, pNode->nodeN);
	    pNode->dPdT = integrate(pDevice->devStates, info, pNode->nodeP);
	  }
	}
      }
    }
    pEdge = pElem->pEdge;
    pNode = pElem->pLeftNode;
    if (pNode->nodeType != CONTACT) {
      psi1 = pDevice->dcSolution[pNode->psiEqn];
    } else {
      psi1 = pNode->psi;
    }
    pNode = pElem->pRightNode;
    if (pNode->nodeType != CONTACT) {
      psi2 = pDevice->dcSolution[pNode->psiEqn];
    } else {
      psi2 = pNode->psi;
    }
    pEdge->dPsi = psi2 - psi1;
    *(pDevice->devState0 + pEdge->edgeDpsi) = pEdge->dPsi;
  }
  /* calculate the current densities and mobility values */
  for (eIndex = 1; eIndex < pDevice->numNodes; eIndex++) {
    pElem = pDevice->elemArray[eIndex];
    pEdge = pElem->pEdge;
    if (pElem->elemType == SEMICON) {
      dPsiN = pEdge->dPsi + pEdge->dCBand;
      dPsiP = pEdge->dPsi - pEdge->dVBand;
      bernoulli(dPsiN, &bPsiN, &dbPsiN, &bMPsiN, &dbMPsiN, !currentOnly);
      bernoulli(dPsiP, &bPsiP, &dbPsiP, &bMPsiP, &dbMPsiP, !currentOnly);
      nC = *(pDevice->devState0 + pElem->pLeftNode->nodeN);
      nP1 = *(pDevice->devState0 + pElem->pRightNode->nodeN);
      pC = *(pDevice->devState0 + pElem->pLeftNode->nodeP);
      pP1 = *(pDevice->devState0 + pElem->pRightNode->nodeP);
      conc1 = pElem->pLeftNode->totalConc;
      conc2 = pElem->pRightNode->totalConc;
      pEdge->jn = (bPsiN * nP1 - bMPsiN * nC);
      pEdge->jp = (bPsiP * pC - bMPsiP * pP1);
      
      
      mun = pEdge->mun;
      dMun = 0.0;
      mup = pEdge->mup;
      dMup = 0.0;
      MOBfieldDep(pElem->matlInfo, ELEC, dPsiN * pElem->rDx, &mun, &dMun);
      MOBfieldDep(pElem->matlInfo, HOLE, dPsiP * pElem->rDx, &mup, &dMup);
      
      
      mun *= pElem->rDx;
      dMun *= pElem->rDx * pElem->rDx;
      mup *= pElem->rDx;
      dMup *= pElem->rDx * pElem->rDx;
      

      
      /*
       * The base continuity equation makes use of mu/dx in eg. The base
       * length has already been calculated and converted to normalized,
       * reciprocal form during setup. The name should be changed, but that's
       * a big hassle.
       */
      for (index = 0; index <= 1; index++) {
	if (pElem->evalNodes[index]) {
	  pNode = pElem->pNodes[index];
	  if (pNode->baseType == N_TYPE) {
	    pNode->eg = pEdge->mun * pDevice->baseLength;
	  } else if (pNode->baseType == P_TYPE) {
	    pNode->eg = pEdge->mup * pDevice->baseLength;
	  }
	}
      }

      pEdge->jn *= mun;
      pEdge->jp *= mup;
      
      
      if (!currentOnly) {
	if (dMun == 0.0) {
	  pEdge->dJnDpsiP1 = mun * (dbPsiN * nP1 - dbMPsiN * nC);
	} else {
	  pEdge->dJnDpsiP1 = dMun * (bPsiN * nP1 - bMPsiN * nC)
	      + mun * (dbPsiN * nP1 - dbMPsiN * nC);
	}
	pEdge->dJnDn = -mun * bMPsiN;
	pEdge->dJnDnP1 = mun * bPsiN;
	if (dMup == 0.0) {
	  pEdge->dJpDpsiP1 = mup * (dbPsiP * pC - dbMPsiP * pP1);
	} else {
	  pEdge->dJpDpsiP1 = dMup * (bPsiP * pC - bMPsiP * pP1)
	      + mup * (dbPsiP * pC - dbMPsiP * pP1);
	}
	pEdge->dJpDp = mup * bPsiP;
	pEdge->dJpDpP1 = -mup * bMPsiP;
      }
    }
    if (tranAnalysis) {
      pEdge->jd = -integrate(pDevice->devStates, info,
	  pEdge->edgeDpsi) * pElem->rDx;
    }
  }
}
Ejemplo n.º 8
0
T& Random< T, G, I, F >::bernoulli(T &t, F p) {
  return const_cast< T& >(bernoulli(const_cast< const T& >(t), p));
}
	SEXP importanceResamplingAuxiliary(SEXP lowerBound_sexp, SEXP trueProbabilities_sexp, SEXP n_sexp, SEXP seed_sexp)
	{
	BEGIN_RCPP
		std::vector<double> trueProbabilities;
		try
		{
			trueProbabilities = Rcpp::as<std::vector<double> >(trueProbabilities_sexp);
		}
		catch(...)
		{
			throw std::runtime_error("Input trueProbabilities must be a numeric vector");
		}
		for(std::vector<double>::iterator trueProbability = trueProbabilities.begin(); trueProbability != trueProbabilities.end(); trueProbability++)
		{
			if(*trueProbability <= 0 || *trueProbability >= 1)
			{
				throw std::runtime_error("Input trueProbability must be in (0, 1)");
			}
		}
		int nBernoullis = trueProbabilities.size();

		int lowerBound;
		try
		{
			lowerBound = Rcpp::as<int>(lowerBound_sexp);
		}
		catch(...)
		{
			throw std::runtime_error("Input lowerBound must be an integer");
		}
		if(lowerBound <= nBernoullis/2)
		{
			throw std::runtime_error("Input lowerBound must be bigger than nBernoullis/2");
		}
		if(lowerBound >= nBernoullis)
		{
			throw std::runtime_error("Input lowerBound must be smaller than nBernoullis");
		}

		int n;
		try
		{
			n = Rcpp::as<int>(n_sexp);
		}
		catch(...)
		{
			throw std::runtime_error("Input n must be an integer");
		}
		if(n < 1)
		{
			throw std::runtime_error("Input n must be positive");
		}

		int seed;
		try
		{
			seed = Rcpp::as<int>(seed_sexp);
		}
		catch(...)
		{
			throw std::runtime_error("Input seed must be an integer");
		}

		boost::mt19937 randomSource;
		randomSource.seed(seed);
		double newProbability = (double)lowerBound / (double)nBernoullis;
		std::vector<double> ratio1, ratio2;
		for(std::vector<double>::iterator trueProbability = trueProbabilities.begin(); trueProbability != trueProbabilities.end(); trueProbability++)
		{
			ratio1.push_back(*trueProbability / newProbability);
			ratio2.push_back((1 - *trueProbability) / (1 - newProbability));
		}
		boost::random::bernoulli_distribution<> bernoulli(newProbability);
		std::vector<int> valuesOfOne(n, 0);
		std::vector<int> newValuesOfOne(n, 0);
		std::vector<int> toSample;
		std::vector<mpfr_class> weights(n, 1), newWeights(n, 1);

		mpfr_class product = 1;
		for(int bernoulliCounter = 0; bernoulliCounter < nBernoullis; bernoulliCounter++)
		{
			toSample.clear();
			//Sample and update the weights. Everything in weightRatio1 has a weight of averageWeight * ratio1. Everything in weightRatio2 has a weight of averageWeight * ratio2. Anything in neither has a weight of 0. 
			for(int i = 0; i < n; i++)
			{
				int value = bernoulli(randomSource);
				if(value)
				{
					valuesOfOne[i]++;
					weights[i] *= ratio1[bernoulliCounter];
					toSample.push_back(i);
				}
				else
				{
					if(valuesOfOne[i] + nBernoullis - 1 - bernoulliCounter > lowerBound)
					{
						toSample.push_back(i);
						weights[i] *= ratio2[bernoulliCounter];
					}
				}
			}
			product *= (double) toSample.size() / (double)n;
			//Resampling step
			if(toSample.size() == 0)
			{
				return Rcpp::List::create(Rcpp::Named("estimate") = 0.0);
			}
			else
			{
				//With this probability we select something with weight ratio1
				boost::random::uniform_int_distribution<> simpleRandom(0, toSample.size()-1);
				for(int i = 0; i < n; i++)
				{
					int sampled = toSample[simpleRandom(randomSource)];
					newValuesOfOne[i] = valuesOfOne[sampled];
					newWeights[i] = weights[sampled];
				}
			}
			valuesOfOne.swap(newValuesOfOne);
			weights.swap(newWeights);
		}
		mpfr_class sum = 0;
		for(int i = 0; i < n; i++)
		{
			sum += weights[i];
		}
		sum /= n;
		sum *= product;
		return Rcpp::List::create(Rcpp::Named("estimate") = sum.convert_to<double>());
	END_RCPP
	}
Ejemplo n.º 10
0
void TContact::comp_electron_current(void)
{
	TNode *next_node, *prev_node;
	prec temp_next, temp_prev;
	prec mass_next, mass_prev;
	prec grad_band, grad_mass, grad_temp;
	prec current;
	prec planck_potential;
	prec mobility;
	prec element_length;
	long collision_factor;
	flag grid_effects;
	prec fermi_ratio_1_half_minus_1_half;
	prec fermi_ratio_3_half_1_half_col;
	prec bernoulli_param;

	if (second_node_number>contact_node_number) {
		next_node=second_node;
		prev_node=contact_node;
	}
	else {
		next_node=contact_node;
		prev_node=second_node;
	}

	element_length=next_node->get_value(GRID_ELECTRICAL,POSITION,NORMALIZED)-
				   prev_node->get_value(GRID_ELECTRICAL,POSITION,NORMALIZED);

	grid_effects=(flag)next_node->get_value(GRID_ELECTRICAL,EFFECTS,NORMALIZED);

	temp_next=next_node->get_value(ELECTRON,TEMPERATURE,NORMALIZED);
	temp_prev=prev_node->get_value(ELECTRON,TEMPERATURE,NORMALIZED);

	mobility=contact_node->get_value(FREE_ELECTRON,MOBILITY,NORMALIZED);

	mass_next=next_node->get_value(ELECTRON,DOS_MASS,NORMALIZED);
	mass_prev=prev_node->get_value(ELECTRON,DOS_MASS,NORMALIZED);

	planck_potential=(next_node->get_value(ELECTRON,PLANCK_POT,NORMALIZED)+
					  prev_node->get_value(ELECTRON,PLANCK_POT,NORMALIZED))/2.0;

	collision_factor=(long)(prev_node->get_value(ELECTRON,COLLISION_FACTOR,NORMALIZED)*2.0);

	if (grid_effects & GRID_FERMI_DIRAC) {
		fermi_ratio_1_half_minus_1_half=fermi_integral_1_half(planck_potential)/
										fermi_integral_minus_1_half(planck_potential);

		switch(collision_factor) {
			case -1:
				fermi_ratio_3_half_1_half_col=fermi_integral_2_half(planck_potential)/
											  fermi_integral_0_half(planck_potential);
				break;
			case 0:
				fermi_ratio_3_half_1_half_col=fermi_integral_3_half(planck_potential)/
											  fermi_integral_1_half(planck_potential);
				break;
			case 1:
				fermi_ratio_3_half_1_half_col=fermi_integral_4_half(planck_potential)/
											  fermi_integral_2_half(planck_potential);
				break;
			case 3:
				fermi_ratio_3_half_1_half_col=fermi_integral_6_half(planck_potential)/
											  fermi_integral_4_half(planck_potential);
				break;
			default: assert(FALSE); break;
		}
	}
	else {
		fermi_ratio_1_half_minus_1_half=1.0;
		fermi_ratio_3_half_1_half_col=1.0;
	}

	grad_temp=((2.5+(prec)collision_factor/2.0)*fermi_ratio_3_half_1_half_col/fermi_ratio_1_half_minus_1_half-1.5)*
			   (temp_next-temp_prev);

	grad_band=(next_node->get_value(ELECTRON,BAND_EDGE,NORMALIZED)-
			   prev_node->get_value(ELECTRON,BAND_EDGE,NORMALIZED))/fermi_ratio_1_half_minus_1_half;

	grad_mass=1.5*(temp_next+temp_prev)*((mass_next-mass_prev)/(mass_next+mass_prev));

	bernoulli_param=-grad_temp-grad_band+grad_mass;

	current=mobility*fermi_ratio_1_half_minus_1_half/element_length*
			(next_node->get_value(ELECTRON,CONCENTRATION,NORMALIZED)*temp_next*
			 bernoulli(bernoulli_param/temp_next)-
			 prev_node->get_value(ELECTRON,CONCENTRATION,NORMALIZED)*temp_prev*
			 bernoulli(-bernoulli_param/temp_prev));

	contact_node->put_value(ELECTRON,CURRENT,current,NORMALIZED);
}
Ejemplo n.º 11
0
/* Compute the alternating series
   s = S(z) = \sum_{k=0}^infty B_{2k} (z))^{2k+1} / (2k+1)!
   with 0 < z <= log(2) to the precision of s rounded in the direction
   rnd_mode.
   Return the maximum index of the truncature which is useful
   for determinating the relative error.
*/
static int
li2_series (mpfr_t sum, mpfr_srcptr z, mpfr_rnd_t rnd_mode)
{
  int i, Bm, Bmax;
  mpfr_t s, u, v, w;
  mpfr_prec_t sump, p;
  mp_exp_t se, err;
  mpz_t *B;
  MPFR_ZIV_DECL (loop);

  /* The series converges for |z| < 2 pi, but in mpfr_li2 the argument is
     reduced so that 0 < z <= log(2). Here is additionnal check that z is
     (nearly) correct */
  MPFR_ASSERTD (MPFR_IS_STRICTPOS (z));
  MPFR_ASSERTD (mpfr_cmp_d (z, 0.6953125) <= 0);

  sump = MPFR_PREC (sum);       /* target precision */
  p = sump + MPFR_INT_CEIL_LOG2 (sump) + 4;     /* the working precision */
  mpfr_init2 (s, p);
  mpfr_init2 (u, p);
  mpfr_init2 (v, p);
  mpfr_init2 (w, p);

  B = bernoulli ((mpz_t *) 0, 0);
  Bm = Bmax = 1;

  MPFR_ZIV_INIT (loop, p);
  for (;;)
    {
      mpfr_sqr (u, z, GMP_RNDU);
      mpfr_set (v, z, GMP_RNDU);
      mpfr_set (s, z, GMP_RNDU);
      se = MPFR_GET_EXP (s);
      err = 0;

      for (i = 1;; i++)
        {
          if (i >= Bmax)
            B = bernoulli (B, Bmax++);  /* B_2i * (2i+1)!, exact */

          mpfr_mul (v, u, v, GMP_RNDU);
          mpfr_div_ui (v, v, 2 * i, GMP_RNDU);
          mpfr_div_ui (v, v, 2 * i, GMP_RNDU);
          mpfr_div_ui (v, v, 2 * i + 1, GMP_RNDU);
          mpfr_div_ui (v, v, 2 * i + 1, GMP_RNDU);
          /* here, v_2i = v_{2i-2} / (2i * (2i+1))^2 */

          mpfr_mul_z (w, v, B[i], GMP_RNDN);
          /* here, w_2i = v_2i * B_2i * (2i+1)! with
             error(w_2i) < 2^(5 * i + 8) ulp(w_2i) (see algorithms.tex) */

          mpfr_add (s, s, w, GMP_RNDN);

          err = MAX (err + se, 5 * i + 8 + MPFR_GET_EXP (w))
            - MPFR_GET_EXP (s);
          err = 2 + MAX (-1, err);
          se = MPFR_GET_EXP (s);
          if (MPFR_GET_EXP (w) <= se - (mp_exp_t) p)
            break;
        }

      /* the previous value of err is the rounding error,
         the truncation error is less than EXP(z) - 6 * i - 5
         (see algorithms.tex) */
      err = MAX (err, MPFR_GET_EXP (z) - 6 * i - 5) + 1;
      if (MPFR_CAN_ROUND (s, (mp_exp_t) p - err, sump, rnd_mode))
        break;

      MPFR_ZIV_NEXT (loop, p);
      mpfr_set_prec (s, p);
      mpfr_set_prec (u, p);
      mpfr_set_prec (v, p);
      mpfr_set_prec (w, p);
    }
  MPFR_ZIV_FREE (loop);
  mpfr_set (sum, s, rnd_mode);

  Bm = Bmax;
  while (Bm--)
    mpz_clear (B[Bm]);
  (*__gmp_free_func) (B, Bmax * sizeof (mpz_t));
  mpfr_clears (s, u, v, w, (mpfr_ptr) 0);

  /* Let K be the returned value.
     1. As we compute an alternating series, the truncation error has the same
     sign as the next term w_{K+2} which is positive iff K%4 == 0.
     2. Assume that error(z) <= (1+t) z', where z' is the actual value, then
     error(s) <= 2 * (K+1) * t (see algorithms.tex).
   */
  return 2 * i;
}