/*****************************************************************************
 *                                                                           *
 *          UNURAN -- Universal Non-Uniform Random number generator          *
 *                                                                           *
 *****************************************************************************
 *                                                                           *
 *   FILE: dgt.h                                                             *
 *                                                                           *
 *   PURPOSE:                                                                *
 *         function prototypes for method DGT                                *
 *         ((Discrete) Guide Table method (indexed search))                  *
 *                                                                           *
 *   USAGE:                                                                  *
 *         only included in unuran.h                                         *
 *                                                                           *
 *****************************************************************************
 *                                                                           *
 *   Copyright (c) 2000-2022 Wolfgang Hoermann and Josef Leydold             *
 *   Department of Statistics and Mathematics, WU Wien, Austria              *
 *   SPDX-License-Identifier: BSD-3-Clause                                   *
 *                                                                           *

 *                                                                           *
 *****************************************************************************/

/* 
   =METHOD  DGT  (Discrete) Guide Table method (indexed search)

   =UP  Methods_for_DISCR

   =REQUIRED probability vector (PV)

   =SPEED Set-up: slow (linear with the vector-length), Sampling: very fast

   =REINIT supported

   =REF  [CAa74] [HLD04: Sect.3.1.2]

   =DESCRIPTION
      DGT samples from arbitrary but finite probability vectors. Random
      numbers are generated by the inversion method, i.e.,

      @enumerate
      @item
      Generate a random number U ~ U(0,1).
      @item
      Find smallest integer I such that F(I) = P(X<=I) >= U.
      @end enumerate

      Step (2) is the crucial step. Using sequential search requires
      @i{O(E(X))} comparisons, where @i{E(X)} is the expectation of
      the distribution. Indexed search, however, uses a guide table to
      jump to some @i{I'} <= @i{I} near @i{I} to find @i{X} in constant
      time. Indeed the expected number of comparisons is reduced to 2,
      when the guide table has the same size as the probability vector
      (this is the default). For larger guide tables this number
      becomes smaller (but is always larger than 1), for smaller
      tables it becomes larger. For the limit case of table size 1 the
      algorithm simply does sequential search (but uses a more expensive
      setup then method DSS (@pxref{DSS}). On the other hand the
      setup time for guide table is @i{O(N)}, where @i{N} denotes the
      length of the probability vector (for size 1 no preprocessing is
      required). Moreover, for very large guide tables memory effects might 
      even reduce the speed of the algorithm. So we do not recommend to
      use guide tables that are more than three times larger than the
      given probability vector. If only a few random numbers have to be
      generated, (much) smaller table sizes are better.
      The size of the guide table relative to the length of the given
      probability vector can be set by a unur_dgt_set_guidefactor() call.

      There exist two variants for the setup step which can be set by a 
      unur_dgt_set_variant() call: Variants 1 and 2.
      Variant 2 is faster but more sensitive to roundoff errors when the
      guide table is large. By default variant 2 is used for short
      probability vectors (@i{N}<1000) and variant 1 otherwise.
      
      By default the probability vector is indexed starting at
      @code{0}. However this can be changed in the distribution object by
      a unur_distr_discr_set_domain() call.

      The method also works when no probability vector but a PMF is
      given. However, then additionally a bounded (not too large) domain
      must be given or the sum over the PMF. In the latter case the
      domain of the distribution is trucated (see
      unur_distr_discr_make_pv() for details).

   =HOWTOUSE
      Create an object for a discrete distribution either by setting a
      probability vector or a PMF. The performance can be slightly
      influenced by setting the size of the used table which can be
      changed by unur_dgt_set_guidefactor().

      It is possible to change the parameters and the domain of the chosen 
      distribution and run unur_reinit() to reinitialize the generator object.
   =END
*/

/*---------------------------------------------------------------------------*/
/* Routines for user interface                                               */

/* =ROUTINES */

UNUR_PAR *unur_dgt_new( const UNUR_DISTR *distribution );
/* 
   Get default parameters for generator.
*/

/*...........................................................................*/

int unur_dgt_set_guidefactor( UNUR_PAR *parameters, double factor );
/* 
   Set size of guide table relative to length of PV.
   Larger guide tables result in faster generation time but require a
   more expensive setup. Sizes larger than 3 are not recommended.
   If the relative size is set to 0, sequential search is used.
   However, this is not recommended, except in exceptional cases, since 
   method DSS (@pxref{DSS}) is has almost no setup and is thus faster
   (but requires the sum over the PV as input parameter).

   Default is @code{1}. 
*/

int unur_dgt_set_variant( UNUR_PAR *parameters, unsigned variant );
/* 
   Set variant for setup step. Possible values are @code{1} or
   @code{2}.
   Variant @code{2} is faster but more sensitive to roundoff errors
   when the guide table is large. 
   By default variant @code{2} is used for short probability
   vectors (@i{N}<1000) and variant @code{1} otherwise.
*/

/* =END */

/*---------------------------------------------------------------------------*/

/** NOT IN MANUAL **/
int unur_dgt_eval_invcdf_recycle( const UNUR_GEN *generator, double u, double *recycle );
/*
   Compute the @var{U} quantile of the discrete distribution in
   @var{generator}, i.e., the smallest integer I such that P(X<=I) >= U.
   If @var{u} is out of the domain (0,1) then @code{unur_errno} is set
   to @code{UNUR_ERR_DOMAIN} and the respective bound of
   the domain of the distribution are returned.

   If @var{recycle} is not NULL then @var{u} is recycled, i.e., 
   the value of [ P(X<=I) - U] / [ P(X<=I) - P(X<=I-1) ]
   is stored in @var{recycle}.
*/

int unur_dgt_eval_invcdf( const UNUR_GEN *generator, double u );
/* 
   Short for  unur_dgt_eval_invcdf_recycle( generator, u, NULL).
 */

/*---------------------------------------------------------------------------*/
