hmmer-3.3/easel/esl_random.c
/* Function:  esl_rnd_DChooseCDF()
 * Synopsis:  Return random choice from cumulative multinomial distribution.
 *
 * Purpose:   Given a random number generator <r> and a cumulative
 *            multinomial distribution <cdf[0..N-1]>, sample an element
 *            <0..N-1> from that distribution. Return the index <0..N-1>.
 *
 *            Caller should be sure that <cdf[0..N-1]> is indeed a
 *            cumulative multinomial distribution -- in particular, that
 *            <cdf[N-1]> is tolerably close to 1.0 (within roundoff error).
 *            
 *            When sampling many times from the same multinomial
 *            distribution <p>, it will generally be faster to
 *            calculate the CDF once using <esl_vec_DCDF(p, N, cdf)>,
 *            then sampling many times from the CDF with
 *            <esl_rnd_DChooseCDF(r, cdf, N)>, as opposed to calling
 *            <esl_rnd_DChoose(r, p, N)> many times, because
 *            <esl_rnd_DChoose()> has to calculated the CDF before
 *            sampling. This also gives you a bit more control over
 *            error detection: you can make sure that the CDF is ok (p
 *            does sum to ~1.0) before doing a lot of sampling from
 *            it.
 *            
 *            <esl_rnd_FChooseCDF()> is the same, but for
 *            a single-precision float <cdf>.
 *            
 * Args:      r    - random number generator
 *            cdf  - cumulative multinomial distribution, cdf[0..N-1]
 *            N    - number of elements in <cdf>
 *
 * Returns:   index 0..N-1 of the randomly sampled choice from <cdf>.
 * 
 * Note:      For large N, it might be advantageous to bisection search the
 *            cdf. For typical N in Easel (up to 20, for amino acid
 *            prob vectors, for example), the naive code below is
 *            faster. We could revisit this if we start sampling
 *            larger vectors.
 */
esl_rnd_DChooseCDF()
Synopsis:  Return random choice from cumulative multinomial distribution.

Given a random number generator  and a cumulative
multinomial distribution , sample an element
<0..N-1> from that distribution. Return the index <0..N-1>.

Caller should be sure that  is indeed a
cumulative multinomial distribution -- in particular, that
 is tolerably close to 1.0 (within roundoff error).

When sampling many times from the same multinomial
distribution , it will generally be faster to
calculate the CDF once using ,
then sampling many times from the CDF with
, as opposed to calling
 many times, because
 has to calculated the CDF before
sampling. This also gives you a bit more control over
error detection: you can make sure that the CDF is ok (p
does sum to ~1.0) before doing a lot of sampling from
it.

 is the same, but for
a single-precision float .

r    - random number generator
cdf  - cumulative multinomial distribution, cdf[0..N-1]
N    - number of elements in 

index 0..N-1 of the randomly sampled choice from .

For large N, it might be advantageous to bisection search the
cdf. For typical N in Easel (up to 20, for amino acid
prob vectors, for example), the naive code below is
faster. We could revisit this if we start sampling
larger vectors.
esl_rnd_DChooseCDF () Synopsis : Return random choice from cumulative multinomial distribution . Given a random number generator and a cumulative multinomial distribution sample an element <0 .. N - 1 > from that distribution . Return the index <0 .. N - 1 > . Caller should be sure that is indeed a cumulative multinomial distribution -- in particular that is tolerably close to 1 . 0 ( within roundoff error ) . When sampling many times from the same multinomial distribution it will generally be faster to calculate the CDF once using then sampling many times from the CDF with as opposed to calling many times because has to calculated the CDF before sampling . This also gives you a bit more control over error detection : you can make sure that the CDF is ok ( p does sum to ~1 . 0 ) before doing a lot of sampling from it . is the same but for a single - precision float . r - random number generator cdf - cumulative multinomial distribution cdf [ 0 .. N - 1 ] N - number of elements in index 0 .. N - 1 of the randomly sampled choice from . For large N it might be advantageous to bisection search the cdf . For typical N in Easel ( up to 20 for amino acid prob vectors for example ) the naive code below is faster . We could revisit this if we start sampling larger vectors .
int
esl_rnd_DChooseCDF(ESL_RANDOMNESS *r, const double *cdf, int N)
{
  double roll = esl_random(r);	
  int    i;
  ESL_DASSERT1((cdf[0] >= 0.0));
  ESL_DASSERT1((cdf[N-1] > 0.999 && cdf[N-1] < 1.001));
  for (i = 0; i < N; i++)
    if (roll < cdf[i] / cdf[N-1]) return i; 
  esl_fatal("unreached code is reached. universe goes foom");
  return 0; 
}
int esl_rnd_DChooseCDF ( ESL_RANDOMNESS * r , const double * cdf , int N ) { double roll = esl_random ( r ) ; int i ; ESL_DASSERT1 ( ( cdf [ 0 ] >= 0.0 ) ) ; ESL_DASSERT1 ( ( cdf [ N - 1 ] > 0.999 && cdf [ N - 1 ] < 1.001 ) ) ; for ( i = 0 ; i < N ; i ++ ) if ( roll < cdf [ i ] / cdf [ N - 1 ] ) return i ; esl_fatal ( " " ) ; return 0 ; }
Function:  esl_rnd_DChooseCDF()
 Synopsis:  Return random choice from cumulative multinomial distribution.
Function : esl_rnd_DChooseCDF () Synopsis : Return random choice from cumulative multinomial distribution .
/* uniform 0.0 <= x < 1.0 */ /*notreached*/