=head1 NAME

PDL::GSL::Randist - Comprehensive Perl Data Language (PDL) binding to the GNU
Scientific Library (GSL) Random Distribution (randist) functions.

=head1 SYNOPSIS

    use PDL;
    use PDL::GSL::RNG;
    use PDL::GSL::Randist qw/:binomial :gaussian :multinomial/;
    
    my $rng = PDL::GSL::RNG->new('taus');
    $rng->set_seed(time);
    
    ### PDF/CDF
    # pdf's are named "ran_DISTNAME_pdf" and cdf are called "cdf_DISTNAME_P" and
    # "cdf_DISTNAME_Q". (Note: P + Q = 1)
    
    # evaluate pdf/cdf at various x's
    my $x_continuous = zeroes(21)->xlinvals(-1, 1); # -1 to -1 by .1
    my $x_discrete = long 1 .. 10;
    print ran_gaussian_pdf($x_continuous, .5);
    print cdf_gaussian_P($x_continuous, .5);
    print ran_binomial_pdf($x_discrete, .5, 20);
    print cdf_binomial_P($x_discrete, .5, 20);
    
    ### Inverse CDF
    my $P = zeroes(9)->xlinvals(.1, .9);
    print cdf_gaussian_Pinv($P, .5);
    
    # should give us back $x_continuous
    print cdf_gaussian_Pinv(cdf_gaussian_P($x_continuous, .5), .5); 
    
    ### Samplers
    # sampling functions are called ran_DISTNAME.  The first argument is always a
    # PDL::GSL::RNG object.  The following arguments are parameters specific to
    # that dist. (n, p for binomial, sigma for gaussian, mu for exponential, etc.
    # See the PDL::GSL::Randist pod).  
    #
    # There are three ways to specify the output.
    # 1) Pass nothing in the last parameter, in which case it'll return a scalar PDL.
    
    print ran_binomial($rng, pdl(.5), long(100)); # n = 100, p = .5
    print ran_gaussian($rng, pdl(3)); # sigma = 3.0
    
    # 2) Pass an output-PDL to be filled with results:
    
    my $counts = zeroes long, 10;
    my $values = zeroes double, 10;
    # draw 10 samples,put them in the outpdl
    ran_binomial($rng, pdl(.5), long(100), $counts);
    ran_gaussian($rng, pdl(3), $values);
    
    # 3) Pass dimensions 
    
    # draw 10 samples, return as 1-D pdl. 
    print ran_binomial($rng, pdl(.5), long(100), 10); 
    print ran_gaussian($rng, pdl(3), 10); 
    
    # draw 100 samples, return as 10x10 pdl
    print ran_binomial($rng, pdl(.5), long(100), 10, 10);
    print ran_gaussian($rng, pdl(3), 10, 10); 
    
    # Multivariate dists like Multinomial are slighly different because the first
    # dimensions are implicit:
    
    # sample a single n=10 draw from a multinomial dist with p = [.1, .2, # .3, .4]
    # return as a dim(4) PDL.
    print ran_multinomial($rng, 10, pdl(.1, .2, .3, .4));
    
    # draw 15 multinomial with p=[.1,.2,.3,.4] and return as 4 x 15
    print ran_multinomial($rng, 10, pdl(.1, .2, .3, .4), 15);

=head1 EXPORT

Nothing is exported by default.  :all exports everything.  :gaussian exports
all gaussian functions, :binomial all binomial functions, etc. Tag names are in
parentheses below.

=head1 NOTES

=head2 Function Naming Convention

Samplers are named "ran_RANDIST()" (eg. "ran_gaussian()"), 
probability density/mass functions are named "ran_RANDIST_pdf()" (eg. "ran_gaussian_pdf()"), 
cumulative distribution function are named "cdf_RANDIST_P()" and "cdf_RANDIST_Q()" (eg. "cdf_gaussian_P()" and "cdf_gaussian_Q()"), 
inverse cumulative distribution functions (quantiles) are named "cdf_RANDIST_Pinv()" and "cdf_RANDIST_Qinv()" (eg. "cdf_gaussian_Pinv()" and "cdf_gaussian_Qinv()").

The _Q CDF functions are complementary CDF functions: cdf_RANDIST_P
+ cdf_RANDIST_Q = 1. Both exist because it is often more accurate numerically to 
calculate the complementary CDF directly instead of calculating 1 - CDF.

A particular distribution may not have all 4 types of functions.  (Discrete
distributions don't have inverse CDF's, Levy distributions don't have pdf's,
etc.).

=head2 Arguments

All of the univariate distributions functions have arguments identical (even in
order) to their underlying C functions.  For the multivariate functions, see
their individual sections below.

=head2 Threading

Unless otherwise noted, PDL threading works on all variables expect the
PDL::GSL::RNG argument for samplers.

=head2 More Documentation

Most of the documentation is automatically generated.  For more details, see the 
L<The GSL Randist manual page|http://www.gnu.org/software/gsl/manual/html_node/Random-Number-Distributions.html>.

=head2 Location Parameters

None of the functions provided by this module contain a 'location' parameter.
For example, the gaussian functions only have a sigma argument, and not a mean.
I thought about adding the location parameters to the appropriate randists, but
this would be contrary to the goal of module to create a straight binding to
GSL's Randist.  Instead, I plan to make an alternative interface to the
functions (possibly modelled after R) which includes such conveniences.

=head2 Bad Values

All the non-sampler functions should handle PDL's BAD values appropriately.

=head2 Floating point and integer PDL's

If you pass a floating point PDL to a function where an integer PDL is
expected, it will be cast automatically to a integer, as in C, by truncation.
(ADD MORE ON THIS.)

=head1 FUNCTIONS

=head1 Bernoulli Distribution (:bernoulli)

=head2 ran_bernoulli_pdf

  Signature: (int val() ; double p() ; double [o] out())

=head2 ran_bernoulli

  Signature: (PDL::GSL::RNG rng(); double p() ; int [o] out())

Usage:

  my $single_draw = ran_bernoulli($rng, $p);
  my $multi_draws = ran_bernoulli($rng, $p, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_bernoulli($rng, $p, $outpdl);

=head1 Beta Distribution (:beta)

=head2 ran_beta_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_beta_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_beta_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_beta_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_beta_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_beta

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_beta($rng, $a, $b);
  my $multi_draws = ran_beta($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_beta($rng, $a, $b, $outpdl);

=head1 Binomial Distribution (:binomial)

=head2 ran_binomial_pdf

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 cdf_binomial_P

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 cdf_binomial_Q

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 ran_binomial

  Signature: (PDL::GSL::RNG rng(); double p() ; int n() ; int [o] out())

Usage:

  my $single_draw = ran_binomial($rng, $p, $n);
  my $multi_draws = ran_binomial($rng, $p, $n, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_binomial($rng, $p, $n, $outpdl);

=head1 Cauchy Distribution (:cauchy)

=head2 ran_cauchy_pdf

  Signature: (double val() ; double scale() ; double [o] out())

=head2 cdf_cauchy_P

  Signature: (double val() ; double scale() ; double [o] out())

=head2 cdf_cauchy_Q

  Signature: (double val() ; double scale() ; double [o] out())

=head2 cdf_cauchy_Pinv

  Signature: (double val() ; double scale() ; double [o] out())

=head2 cdf_cauchy_Qinv

  Signature: (double val() ; double scale() ; double [o] out())

=head2 ran_cauchy

  Signature: (PDL::GSL::RNG rng(); double scale() ; double [o] out())

Usage:

  my $single_draw = ran_cauchy($rng, $scale);
  my $multi_draws = ran_cauchy($rng, $scale, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_cauchy($rng, $scale, $outpdl);

=head1 Chi-squared Distribution (:chisq)

=head2 ran_chisq_pdf

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_chisq_P

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_chisq_Q

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_chisq_Pinv

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_chisq_Qinv

  Signature: (double val() ; double nu() ; double [o] out())

=head2 ran_chisq

  Signature: (PDL::GSL::RNG rng(); double nu() ; double [o] out())

Usage:

  my $single_draw = ran_chisq($rng, $nu);
  my $multi_draws = ran_chisq($rng, $nu, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_chisq($rng, $nu, $outpdl);

=head1 Exponential Distribution (:exponential)

=head2 ran_exponential_pdf

  Signature: (double val() ; double mu() ; double [o] out())

=head2 cdf_exponential_P

  Signature: (double val() ; double mu() ; double [o] out())

=head2 cdf_exponential_Q

  Signature: (double val() ; double mu() ; double [o] out())

=head2 cdf_exponential_Pinv

  Signature: (double val() ; double mu() ; double [o] out())

=head2 cdf_exponential_Qinv

  Signature: (double val() ; double mu() ; double [o] out())

=head2 ran_exponential

  Signature: (PDL::GSL::RNG rng(); double mu() ; double [o] out())

Usage:

  my $single_draw = ran_exponential($rng, $mu);
  my $multi_draws = ran_exponential($rng, $mu, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_exponential($rng, $mu, $outpdl);

=head1 The Exponential Power Distribution (:exppow)

=head2 ran_exppow_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_exppow_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_exppow_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_exppow

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_exppow($rng, $a, $b);
  my $multi_draws = ran_exppow($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_exppow($rng, $a, $b, $outpdl);

=head1 F-distribution (:fdist)

=head2 ran_fdist_pdf

  Signature: (double val() ; double nu1() ; double nu2() ; double [o] out())

=head2 cdf_fdist_P

  Signature: (double val() ; double nu1() ; double nu2() ; double [o] out())

=head2 cdf_fdist_Q

  Signature: (double val() ; double nu1() ; double nu2() ; double [o] out())

=head2 cdf_fdist_Pinv

  Signature: (double val() ; double nu1() ; double nu2() ; double [o] out())

=head2 cdf_fdist_Qinv

  Signature: (double val() ; double nu1() ; double nu2() ; double [o] out())

=head2 ran_fdist

  Signature: (PDL::GSL::RNG rng(); double nu1() ; double nu2() ; double [o] out())

Usage:

  my $single_draw = ran_fdist($rng, $nu1, $nu2);
  my $multi_draws = ran_fdist($rng, $nu1, $nu2, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_fdist($rng, $nu1, $nu2, $outpdl);

=head1 Flat (Uniform) Distribution (:flat)

=head2 ran_flat_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_flat_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_flat_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_flat_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_flat_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_flat

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_flat($rng, $a, $b);
  my $multi_draws = ran_flat($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_flat($rng, $a, $b, $outpdl);

=head1 Gamma Distribution (:gamma)

=head2 ran_gamma_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gamma_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gamma_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gamma_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gamma_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_gamma

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_gamma($rng, $a, $b);
  my $multi_draws = ran_gamma($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gamma($rng, $a, $b, $outpdl);

=head1 Gaussian Distribution (:gaussian)

=head2 ran_gaussian_pdf

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_gaussian_P

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_gaussian_Q

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_gaussian_Pinv

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_gaussian_Qinv

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 ran_gaussian

  Signature: (PDL::GSL::RNG rng(); double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_gaussian($rng, $sigma);
  my $multi_draws = ran_gaussian($rng, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gaussian($rng, $sigma, $outpdl);

=head1 Gaussian Tail Distribution (:gaussian_tail)

=head2 ran_gaussian_tail_pdf

  Signature: (double val() ; double a() ; double sigma() ; double [o] out())

=head2 ran_gaussian_tail

  Signature: (PDL::GSL::RNG rng(); double a() ; double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_gaussian_tail($rng, $a, $sigma);
  my $multi_draws = ran_gaussian_tail($rng, $a, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gaussian_tail($rng, $a, $sigma, $outpdl);

=head1 Geometric Distribution (:geometric)

=head2 ran_geometric_pdf

  Signature: (int val() ; double p() ; double [o] out())

=head2 cdf_geometric_P

  Signature: (int val() ; double p() ; double [o] out())

=head2 cdf_geometric_Q

  Signature: (int val() ; double p() ; double [o] out())

=head2 ran_geometric

  Signature: (PDL::GSL::RNG rng(); double p() ; int [o] out())

Usage:

  my $single_draw = ran_geometric($rng, $p);
  my $multi_draws = ran_geometric($rng, $p, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_geometric($rng, $p, $outpdl);

=head1 Type-1 Gumbel Distribution (:gumbel1)

=head2 ran_gumbel1_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel1_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel1_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel1_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel1_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_gumbel1

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_gumbel1($rng, $a, $b);
  my $multi_draws = ran_gumbel1($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gumbel1($rng, $a, $b, $outpdl);

=head1 The Type-2 Gumbel Distribution (:gumbel2)

=head2 ran_gumbel2_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel2_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel2_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel2_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_gumbel2_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_gumbel2

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_gumbel2($rng, $a, $b);
  my $multi_draws = ran_gumbel2($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gumbel2($rng, $a, $b, $outpdl);

=head1 Hypergeometric Distribution (:hypergeometric)

=head2 ran_hypergeometric_pdf

  Signature: (int val() ; int n1() ; int n2() ; int t() ; double [o] out())

=head2 cdf_hypergeometric_P

  Signature: (int val() ; int n1() ; int n2() ; int t() ; double [o] out())

=head2 cdf_hypergeometric_Q

  Signature: (int val() ; int n1() ; int n2() ; int t() ; double [o] out())

=head2 ran_hypergeometric

  Signature: (PDL::GSL::RNG rng(); int n1() ; int n2() ; int t() ; int [o] out())

Usage:

  my $single_draw = ran_hypergeometric($rng, $n1, $n2, $t);
  my $multi_draws = ran_hypergeometric($rng, $n1, $n2, $t, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_hypergeometric($rng, $n1, $n2, $t, $outpdl);

=head1 Landau Distribution (:landau)

=head2 ran_landau_pdf

  Signature: (double val() ; double [o] out())

=head2 ran_landau

  Signature: (PDL::GSL::RNG rng(); double [o] out())

Usage:

  my $single_draw = ran_landau($rng, );
  my $multi_draws = ran_landau($rng, , [ ... output pdl dims ...] );
  my $outpdl_draw = ran_landau($rng, , $outpdl);

=head1 The Laplace Distribution (:laplace)

=head2 ran_laplace_pdf

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_laplace_P

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_laplace_Q

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_laplace_Pinv

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_laplace_Qinv

  Signature: (double val() ; double a() ; double [o] out())

=head2 ran_laplace

  Signature: (PDL::GSL::RNG rng(); double a() ; double [o] out())

Usage:

  my $single_draw = ran_laplace($rng, $a);
  my $multi_draws = ran_laplace($rng, $a, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_laplace($rng, $a, $outpdl);

=head1 Levy alpha-Stable Distributions (:levy)

=head2 ran_levy

  Signature: (PDL::GSL::RNG rng(); double scale() ; double stability() ; double [o] out())

Usage:

  my $single_draw = ran_levy($rng, $scale, $stability);
  my $multi_draws = ran_levy($rng, $scale, $stability, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_levy($rng, $scale, $stability, $outpdl);

=head1 Levy skew alpha-Stable Distribution (:levy_skew)

=head2 ran_levy_skew

  Signature: (PDL::GSL::RNG rng(); double scale() ; double stability() ; double skewness() ; double [o] out())

Usage:

  my $single_draw = ran_levy_skew($rng, $scale, $stability, $skewness);
  my $multi_draws = ran_levy_skew($rng, $scale, $stability, $skewness, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_levy_skew($rng, $scale, $stability, $skewness, $outpdl);

=head1 Logarithmic Distribution (:logarithmic)

=head2 ran_logarithmic_pdf

  Signature: (int val() ; double p() ; double [o] out())

=head2 ran_logarithmic

  Signature: (PDL::GSL::RNG rng(); double p() ; int [o] out())

Usage:

  my $single_draw = ran_logarithmic($rng, $p);
  my $multi_draws = ran_logarithmic($rng, $p, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_logarithmic($rng, $p, $outpdl);

=head1 Logistic Distribution (:logistic)

=head2 ran_logistic_pdf

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_logistic_P

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_logistic_Q

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_logistic_Pinv

  Signature: (double val() ; double a() ; double [o] out())

=head2 cdf_logistic_Qinv

  Signature: (double val() ; double a() ; double [o] out())

=head2 ran_logistic

  Signature: (PDL::GSL::RNG rng(); double a() ; double [o] out())

Usage:

  my $single_draw = ran_logistic($rng, $a);
  my $multi_draws = ran_logistic($rng, $a, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_logistic($rng, $a, $outpdl);

=head1 Lognormal Distribution (:lognormal)

=head2 ran_lognormal_pdf

  Signature: (double val() ; double zeta() ; double sigma() ; double [o] out())

=head2 cdf_lognormal_P

  Signature: (double val() ; double zeta() ; double sigma() ; double [o] out())

=head2 cdf_lognormal_Q

  Signature: (double val() ; double zeta() ; double sigma() ; double [o] out())

=head2 cdf_lognormal_Pinv

  Signature: (double val() ; double zeta() ; double sigma() ; double [o] out())

=head2 cdf_lognormal_Qinv

  Signature: (double val() ; double zeta() ; double sigma() ; double [o] out())

=head2 ran_lognormal

  Signature: (PDL::GSL::RNG rng(); double zeta() ; double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_lognormal($rng, $zeta, $sigma);
  my $multi_draws = ran_lognormal($rng, $zeta, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_lognormal($rng, $zeta, $sigma, $outpdl);

=head1 Negative Binomial Distribution (:negative_binomial)

=head2 ran_negative_binomial_pdf

  Signature: (int val() ; double p() ; double n() ; double [o] out())

=head2 cdf_negative_binomial_P

  Signature: (int val() ; double p() ; double n() ; double [o] out())

=head2 cdf_negative_binomial_Q

  Signature: (int val() ; double p() ; double n() ; double [o] out())

=head2 ran_negative_binomial

  Signature: (PDL::GSL::RNG rng(); double p() ; double n() ; int [o] out())

Usage:

  my $single_draw = ran_negative_binomial($rng, $p, $n);
  my $multi_draws = ran_negative_binomial($rng, $p, $n, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_negative_binomial($rng, $p, $n, $outpdl);

=head1 Pareto Distribution (:pareto)

=head2 ran_pareto_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_pareto_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_pareto_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_pareto_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_pareto_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_pareto

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_pareto($rng, $a, $b);
  my $multi_draws = ran_pareto($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_pareto($rng, $a, $b, $outpdl);

=head1 Pascal Distribution (:pascal)

=head2 ran_pascal_pdf

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 cdf_pascal_P

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 cdf_pascal_Q

  Signature: (int val() ; double p() ; int n() ; double [o] out())

=head2 ran_pascal

  Signature: (PDL::GSL::RNG rng(); double p() ; int n() ; int [o] out())

Usage:

  my $single_draw = ran_pascal($rng, $p, $n);
  my $multi_draws = ran_pascal($rng, $p, $n, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_pascal($rng, $p, $n, $outpdl);

=head1 Poisson Distribution (:poisson)

=head2 ran_poisson_pdf

  Signature: (int val() ; double mu() ; double [o] out())

=head2 cdf_poisson_P

  Signature: (int val() ; double mu() ; double [o] out())

=head2 cdf_poisson_Q

  Signature: (int val() ; double mu() ; double [o] out())

=head2 ran_poisson

  Signature: (PDL::GSL::RNG rng(); double mu() ; int [o] out())

Usage:

  my $single_draw = ran_poisson($rng, $mu);
  my $multi_draws = ran_poisson($rng, $mu, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_poisson($rng, $mu, $outpdl);

=head1 Rayleigh Distribution (:rayleigh)

=head2 ran_rayleigh_pdf

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_rayleigh_P

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_rayleigh_Q

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_rayleigh_Pinv

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 cdf_rayleigh_Qinv

  Signature: (double val() ; double sigma() ; double [o] out())

=head2 ran_rayleigh

  Signature: (PDL::GSL::RNG rng(); double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_rayleigh($rng, $sigma);
  my $multi_draws = ran_rayleigh($rng, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_rayleigh($rng, $sigma, $outpdl);

=head1 Rayleigh Tail Distribution (:rayleigh_tail)

=head2 ran_rayleigh_tail_pdf

  Signature: (double val() ; double a() ; double sigma() ; double [o] out())

=head2 ran_rayleigh_tail

  Signature: (PDL::GSL::RNG rng(); double a() ; double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_rayleigh_tail($rng, $a, $sigma);
  my $multi_draws = ran_rayleigh_tail($rng, $a, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_rayleigh_tail($rng, $a, $sigma, $outpdl);

=head1 t-distribution (:tdist)

=head2 ran_tdist_pdf

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_tdist_P

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_tdist_Q

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_tdist_Pinv

  Signature: (double val() ; double nu() ; double [o] out())

=head2 cdf_tdist_Qinv

  Signature: (double val() ; double nu() ; double [o] out())

=head2 ran_tdist

  Signature: (PDL::GSL::RNG rng(); double nu() ; double [o] out())

Usage:

  my $single_draw = ran_tdist($rng, $nu);
  my $multi_draws = ran_tdist($rng, $nu, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_tdist($rng, $nu, $outpdl);

=head1 Weibull Distribution (:weibull)

=head2 ran_weibull_pdf

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_weibull_P

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_weibull_Q

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_weibull_Pinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 cdf_weibull_Qinv

  Signature: (double val() ; double a() ; double b() ; double [o] out())

=head2 ran_weibull

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_weibull($rng, $a, $b);
  my $multi_draws = ran_weibull($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_weibull($rng, $a, $b, $outpdl);

=head1 Alternate Gaussian Samplers (:gaussian)

=head2 ran_gaussian_ratio_method

  Signature: (PDL::GSL::RNG rng(); double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_gaussian_ratio_method($rng, $sigma);
  my $multi_draws = ran_gaussian_ratio_method($rng, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gaussian_ratio_method($rng, $sigma, $outpdl);

=head2 ran_gaussian_ziggurat

  Signature: (PDL::GSL::RNG rng(); double sigma() ; double [o] out())

Usage:

  my $single_draw = ran_gaussian_ziggurat($rng, $sigma);
  my $multi_draws = ran_gaussian_ziggurat($rng, $sigma, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gaussian_ziggurat($rng, $sigma, $outpdl);

=head1 Alternate Gamma Samplers (:gamma)

=head2 ran_gamma_knuth

  Signature: (PDL::GSL::RNG rng(); double a() ; double b() ; double [o] out())

Usage:

  my $single_draw = ran_gamma_knuth($rng, $a, $b);
  my $multi_draws = ran_gamma_knuth($rng, $a, $b, [ ... output pdl dims ...] );
  my $outpdl_draw = ran_gamma_knuth($rng, $a, $b, $outpdl);

=head1 Multinomial Distribution (:multinomial)

=head2 ran_multinomial

Draws $numdraws samples from a multinomial distribution with probabilities $p,
returns counts in a pdl with the same (first) dimensions as $p.

  Signature: (PDL::GSL::RNG rng(); int numdraws(); double p(n); int [o] counts(n))

Usage:

  ran_multinomial($rng, $numdraws, $p, $outpdl); # $outpdl's first dimensions must be ($p->dims())

  my $single_draw = ran_multinomial($rng, $numdraws, $p); 
  my $multi_draws = ran_multinomial($rng, $numdraws, $p, @dims); # returns pdl with dimensions ($p->dims(), @dims)

=head2 ran_multinomial_pdf

  Signature: (double p(n); int counts(n); double [o] probability())

Note the slightly strange order of arguments.

=head2 ran_multinomial_lnpdf

  Signature: (double p(n); int counts(n); double [o] probability())

Note the slightly strange order of arguments.

=head1 Dirichlet Distribution (:dirichlet)

=head2 ran_dirichlet

  Signature: (PDL::GSL::RNG rng(); double alpha(n); double [o] theta(n))

Usage:

  ran_dirichlet($rng, $alpha, $outpdl); # $outpdl's first dimensions must be ($alpha->dims())

  my $single_draw = ran_dirichlet($rng, $alpha); 
  my $multi_draws = ran_dirichlet($rng, $alpha, @dims); # returns pdl with dimensions ($alpha->dims(), @dims)

=head2 ran_dirichlet_pdf

  Signature: (double theta(n); double alpha(n); double [o] probability())

Note: the argument order is swapped compared to C so that theta comes first.

ran_dirichlet_pdf processes bad values.
It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

=head2 ran_dirichlet_lnpdf

  Signature: (double theta(n); double alpha(n); double [o] probability())

Note: the argument order is swapped compared to C so that theta comes first.

ran_dirichlet_lnpdf processes bad values.
It will set the bad-value flag of all output piddles if the flag is set for any of the input piddles.

=head1 Bivariate Gaussian Distribution (:bivariate_gaussian)

=head2 ran_bivariate_gaussian

  Signature: (PDL::GSL::RNG rng(); double sigma(n=2); double rho(); double [o] out(n=2))

Usage:

  ran_bivariate_gaussian($rng, pdl($sigma_x, $sigma_y), $rho, $dim); # returns pdl dim(2, $dim);
  
  my $xy     = ran_bivariate_gaussian($rng, pdl($sigma_x, $sigma_y), $rho); # returns pdl dim(2)
  my $xy_vec = ran_bivariate_gaussian($rng, pdl($sigma_x, $sigma_y), $rho, $dim); # returns pdl dim(2, $dim);

=head2 ran_bivariate_gaussian_pdf

  Signature: (double xy(n=2); double sigma(n=2); double rho(); double [o] prob())

=head1 Spherical Vector Distribution (:spherical)

=head2 ran_dir_2d

  Signature: (PDL::GSL::RNG rng(); double [o] vector(n=2))

=head2 ran_dir_2d_trig_method

  Signature: (PDL::GSL::RNG rng(); double [o] vector(n=2))

=head2 ran_dir_3d

  Signature: (PDL::GSL::RNG rng(); double [o] vector(n=3))

  Signature: (PDL::GSL::RNG rng(); int size(); double [o] vector(n))

=head1 Sampling (:sample)

=head2 ran_choose

Sample count items from src without replacement, put them (in order) into
out(). ran_choose is not threadable (src must be one dimensional). count must
be <= n.

  Signature: (PDL::GSL::RNG rng(); src(n); count(); out())

=head2 ran_sample

Sample count items from src with replacement, put them (in order) into
out(). ran_sample is not threadable (src must be one dimensional).

  Signature: (PDL::GSL::RNG rng(); src(n); count(); out())

=head1 Shuffling (:shuffle)

=head2 ran_shuffle

Return a new piddle with shuffled elements from src. src must be
one-dimensional.

  Signature: (PDL::GSL::RNG rng(); src(n))

=head1 BUGS

The discrete distribution has no binding yet. Probably a whole lot more.

