### ----------------------------------------------------
### -- Math::Libgsl::RandomDistribution
### -- Licenses: Artistic-2.0
### -- Authors: Fernando Santagata
### -- File: lib/Math/Libgsl/RandomDistribution.rakumod
### ----------------------------------------------------
### -- Chunk 1 of 3
use v6.c;

unit module Math::Libgsl::RandomDistribution:ver<0.0.4>:auth<zef:FRITH>;

use NativeCall;
use NativeHelpers::Blob;
use Math::Libgsl::Vector;
use Math::Libgsl::Matrix;
use Math::Libgsl::Random;
use Math::Libgsl::Exception;
use Math::Libgsl::Constants;
use Math::Libgsl::Raw::RandomDistribution :ALL;

# Gaussian Distribution
sub gaussian(Math::Libgsl::Random $r, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian($r.r, $sigma)
}
sub gaussian-pdf(Num() $x, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian_pdf($x, $sigma)
}
sub gaussian-ziggurat(Math::Libgsl::Random $r, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian_ziggurat($r.r, $sigma)
}
sub gaussian-ratio-method(Math::Libgsl::Random $r, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian_ratio_method($r.r, $sigma)
}
sub ugaussian(Math::Libgsl::Random $r --> Num) is export
{
  gsl_ran_ugaussian($r.r)
}
sub ugaussian-pdf(Num() $x --> Num) is export
{
  gsl_ran_ugaussian_pdf($x)
}
sub ugaussian-ratio-method(Math::Libgsl::Random $r --> Num) is export
{
  gsl_ran_ugaussian_ratio_method($r.r)
}
sub gaussian-P(Num() $x, Num() $sigma --> Num) is export
{
  gsl_cdf_gaussian_P($x, $sigma)
}
sub gaussian-Q(Num() $x, Num() $sigma --> Num) is export
{
  gsl_cdf_gaussian_Q($x, $sigma)
}
sub gaussian-Pinv(Num() $P, Num() $sigma --> Num) is export
{
  gsl_cdf_gaussian_Pinv($P, $sigma)
}
sub gaussian-Qinv(Num() $Q, Num() $sigma --> Num) is export
{
  gsl_cdf_gaussian_Qinv($Q, $sigma)
}
sub ugaussian-P(Num() $x --> Num) is export
{
  gsl_cdf_ugaussian_P($x)
}
sub ugaussian-Q(Num() $x --> Num) is export
{
  gsl_cdf_ugaussian_Q($x)
}
sub ugaussian-Pinv(Num() $P --> Num) is export
{
  gsl_cdf_ugaussian_Pinv($P)
}
sub ugaussian-Qinv(Num() $Q --> Num) is export
{
  gsl_cdf_ugaussian_Qinv($Q)
}
# Gaussian Tail Distribution
sub gaussian-tail(Math::Libgsl::Random $r, Num() $a where * > 0, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian_tail($r.r, $a, $sigma)
}
sub gaussian-tail-pdf(Num() $x, Num() $a where * > 0, Num() $sigma --> Num) is export
{
  gsl_ran_gaussian_tail_pdf($x, $a, $sigma)
}
sub ugaussian-tail(Math::Libgsl::Random $r, Num() $a where * > 0 --> Num) is export
{
  gsl_ran_ugaussian_tail($r.r, $a)
}
sub ugaussian-tail-pdf(Num() $x, Num() $a where * > 0 --> Num) is export
{
  gsl_ran_ugaussian_tail_pdf($x, $a)
}
# Bivariate Gaussian Distribution
sub bivariate-gaussian(Math::Libgsl::Random $r, Num() $sigma-x, Num() $sigma-y, Num() $rho where -1 < * < 1
                       --> List) is export
{
  my num64 ($x, $y);
  gsl_ran_bivariate_gaussian($r.r, $sigma-x, $sigma-y, $rho, $x, $y);
  return $x, $y;
}
sub bivariate-gaussian-pdf(Num() $x, Num() $y, Num() $sigma-x, Num() $sigma-y, Num() $rho where -1 < * < 1
                           --> Num) is export
{
  gsl_ran_bivariate_gaussian_pdf($x, $y, $sigma-x, $sigma-y, $rho);
}
# Multivariate Gaussian Distribution
sub multivariate-gaussian(Math::Libgsl::Random $r, Math::Libgsl::Vector $mu,
                          Math::Libgsl::Matrix $L where { $L.matrix.size1 == $L.matrix.size2 &&
                                                          $L.matrix.size1 == $mu.vector.size }
                          --> Math::Libgsl::Vector) is export
{
  my Math::Libgsl::Vector $result .= new: $mu.vector.size;
  my $ret = gsl_ran_multivariate_gaussian($r.r, $mu.vector, $L.matrix, $result.vector);
  fail X::Libgsl.new: errno => $ret, error => "Error in multivariate-gaussian" if $ret ≠ GSL_SUCCESS;
  return $result;
}
sub multivariate-gaussian-pdf(Math::Libgsl::Vector $x,
                              Math::Libgsl::Vector $mu where *.vector.size == $x.vector.size,
                              Math::Libgsl::Matrix $L where { $L.matrix.size1 == $L.matrix.size2 &&
                                                              $L.matrix.size1 == $mu.vector.size } --> Num) is export
{
  my num64 $result;
  my Math::Libgsl::Vector $work .= new: $mu.vector.size;
  my $ret = gsl_ran_multivariate_gaussian_pdf($x.vector, $mu.vector, $L.matrix, $result, $work.vector);
  fail X::Libgsl.new: errno => $ret, error => "Error in multivariate-gaussian-pdf" if $ret ≠ GSL_SUCCESS;
  return $result;
}
sub multivariate-gaussian-log-pdf(Math::Libgsl::Vector $x,
                                  Math::Libgsl::Vector $mu where *.vector.size == $x.vector.size,
                                  Math::Libgsl::Matrix $L where { $L.matrix.size1 == $L.matrix.size2 &&
                                                                  $L.matrix.size1 == $mu.vector.size } --> Num) is export
{
  my num64 $result;
  my Math::Libgsl::Vector $work .= new: $mu.vector.size;
  my $ret = gsl_ran_multivariate_gaussian_log_pdf($x.vector, $mu.vector, $L.matrix, $result, $work.vector);
  fail X::Libgsl.new: errno => $ret, error => "Error in multivariate-gaussian-log-pdf" if $ret ≠ GSL_SUCCESS;
  return $result;
}
sub multivariate-gaussian-mean(Math::Libgsl::Matrix $X --> Math::Libgsl::Vector) is export
{
  my Math::Libgsl::Vector $mu-hat .= new: $X.matrix.size2;
  my $ret = gsl_ran_multivariate_gaussian_mean($X.matrix, $mu-hat.vector);
  fail X::Libgsl.new: errno => $ret, error => "Error in multivariate-gaussian-mean" if $ret ≠ GSL_SUCCESS;
  return $mu-hat;
}
sub multivariate-gaussian-vcov(Math::Libgsl::Matrix $X --> Math::Libgsl::Matrix) is export
{
  my Math::Libgsl::Matrix $mu-hat .= new: $X.matrix.size2, $X.matrix.size2;
  my $ret = gsl_ran_multivariate_gaussian_vcov($X.matrix, $mu-hat.matrix);
  fail X::Libgsl.new: errno => $ret, error => "Error in multivariate-gaussian-vcov" if $ret ≠ GSL_SUCCESS;
  return $mu-hat;
}
# Exponential Distribution
sub exponential(Math::Libgsl::Random $r, Num() $mu --> Num) is export
{
  gsl_ran_exponential($r.r, $mu);
}
sub exponential-pdf(Num() $x, Num() $mu --> Num) is export
{
  gsl_ran_exponential_pdf($x, $mu);
}
sub exponential-P(Num() $x, Num() $mu --> Num) is export
{
  gsl_cdf_exponential_P($x, $mu);
}
sub exponential-Q(Num() $x, Num() $mu --> Num) is export
{
  gsl_cdf_exponential_Q($x, $mu);
}
sub exponential-Pinv(Num() $P, Num() $mu --> Num) is export
{
  gsl_cdf_exponential_Pinv($P, $mu);
}
sub exponential-Qinv(Num() $Q, Num() $mu --> Num) is export
{
  gsl_cdf_exponential_Qinv($Q, $mu);
}
# Laplace Distribution
sub laplace(Math::Libgsl::Random $r, Num() $a --> Num) is export
{
  gsl_ran_laplace($r.r, $a);
}
sub laplace-pdf(Num() $x, Num() $a --> Num) is export
{
  gsl_ran_laplace_pdf($x, $a);
}
sub laplace-P(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_laplace_P($x, $a);
}
sub laplace-Q(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_laplace_Q($x, $a);
}
sub laplace-Pinv(Num() $P, Num() $a --> Num) is export
{
  gsl_cdf_laplace_Pinv($P, $a);
}
sub laplace-Qinv(Num() $Q, Num() $a --> Num) is export
{
  gsl_cdf_laplace_Qinv($Q, $a);
}
# Exponential Power Distribution
sub exppow(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_exppow($r.r, $a, $b);
}
sub exppow-pdf(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_exppow_pdf($x, $a, $b);
}
sub exppow-P(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_exppow_P($x, $a, $b);
}
sub exppow-Q(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_exppow_Q($x, $a, $b);
}
# Cauchy Distribution
sub cauchy(Math::Libgsl::Random $r, Num() $a --> Num) is export
{
  gsl_ran_cauchy($r.r, $a);
}
sub cauchy-pdf(Num() $x, Num() $a --> Num) is export
{
  gsl_ran_cauchy_pdf($x, $a);
}
sub cauchy-P(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_cauchy_P($x, $a);
}
sub cauchy-Q(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_cauchy_Q($x, $a);
}
sub cauchy-Pinv(Num() $P, Num() $a --> Num) is export
{
  gsl_cdf_cauchy_Pinv($P, $a);
}
sub cauchy-Qinv(Num() $Q, Num() $a --> Num) is export
{
  gsl_cdf_cauchy_Qinv($Q, $a);
}
# Rayleigh Distribution
sub rayleigh(Math::Libgsl::Random $r, Num() $sigma --> Num) is export
{
  gsl_ran_rayleigh($r.r, $sigma);
}
sub rayleigh-pdf(Num() $x, Num() $sigma --> Num) is export
{
  gsl_ran_rayleigh_pdf($x, $sigma);
}
sub rayleigh-P(Num() $x, Num() $sigma --> Num) is export
{
  gsl_cdf_rayleigh_P($x, $sigma);
}
sub rayleigh-Q(Num() $x, Num() $sigma --> Num) is export
{
  gsl_cdf_rayleigh_Q($x, $sigma);
}
sub rayleigh-Pinv(Num() $P, Num() $sigma --> Num) is export
{
  gsl_cdf_rayleigh_Pinv($P, $sigma);
}
sub rayleigh-Qinv(Num() $Q, Num() $sigma --> Num) is export
{
  gsl_cdf_rayleigh_Qinv($Q, $sigma);
}
# Rayleigh Tail Distribution
sub rayleigh-tail(Math::Libgsl::Random $r, Num() $a, Num() $sigma --> Num) is export
{
  gsl_ran_rayleigh_tail($r.r, $a, $sigma);
}
sub rayleigh-tail-pdf(Num() $x, Num() $a, Num() $sigma --> Num) is export
{
  gsl_ran_rayleigh_tail_pdf($x, $a, $sigma);
}
# Landau Distribution
sub landau(Math::Libgsl::Random $r --> Num) is export
{
  gsl_ran_landau($r.r);
}
sub landau-pdf(Num() $x --> Num) is export
{
  gsl_ran_landau_pdf($x);
}
# Levy alpha-Stable Distribution
sub levy(Math::Libgsl::Random $r, Num() $c, Num() $alpha where 0 < * ≤ 2 --> Num) is export
{
  gsl_ran_levy($r.r, $c, $alpha);
}
# Levy skew alpha-Stable Distribution
sub levy-skew(Math::Libgsl::Random $r, Num() $c, Num() $alpha where 0 < * ≤ 2, Num() $beta --> Num) is export
{
  gsl_ran_levy_skew($r.r, $c, $alpha, $beta);
}
# Gamma Distribution
sub gamma(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gamma($r.r, $a, $b);
}
sub gamma-knuth(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gamma_knuth($r.r, $a, $b);
}
sub gamma-pdf(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gamma_pdf($x, $a, $b);
}
sub gamma-P(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gamma_P($x, $a, $b);
}
sub gamma-Q(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gamma_Q($x, $a, $b);
}
sub gamma-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gamma_Pinv($P, $a, $b);
}
sub gamma-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gamma_Qinv($Q, $a, $b);
}
# Flat (Uniform) Distribution
sub flat(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_flat($r.r, $a, $b);
}
sub flat-pdf(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_flat_pdf($x, $a, $b);
}
sub flat-P(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_flat_P($x, $a, $b);
}
sub flat-Q(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_flat_Q($x, $a, $b);
}
sub flat-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_flat_Pinv($P, $a, $b);
}
sub flat-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_flat_Qinv($Q, $a, $b);
}
# Lognormal Distribution
sub lognormal(Math::Libgsl::Random $r, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_ran_lognormal($r.r, $zeta, $sigma);
}
sub lognormal-pdf(Num() $x, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_ran_lognormal_pdf($x, $zeta, $sigma);
}
sub lognormal-P(Num() $x, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_cdf_lognormal_P($x, $zeta, $sigma);
}
sub lognormal-Q(Num() $x, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_cdf_lognormal_Q($x, $zeta, $sigma);
}
sub lognormal-Pinv(Num() $P, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_cdf_lognormal_Pinv($P, $zeta, $sigma);
}
sub lognormal-Qinv(Num() $Q, Num() $zeta, Num() $sigma --> Num) is export
{
  gsl_cdf_lognormal_Qinv($Q, $zeta, $sigma);
}
# Chi-squared Distribution
sub chisq(Math::Libgsl::Random $r, Num() $nu --> Num) is export
{
  gsl_ran_chisq($r.r, $nu);
}
sub chisq-pdf(Num() $x where * ≥ 0, Num() $nu --> Num) is export
{
  gsl_ran_chisq_pdf($x, $nu);
}
sub chisq-P(Num() $x where * ≥ 0, Num() $nu --> Num) is export
{
  gsl_cdf_chisq_P($x, $nu);
}
sub chisq-Q(Num() $x where * ≥ 0, Num() $nu --> Num) is export
{
  gsl_cdf_chisq_Q($x, $nu);
}
sub chisq-Pinv(Num() $P, Num() $nu --> Num) is export
{
  gsl_cdf_chisq_Pinv($P, $nu);
}
sub chisq-Qinv(Num() $Q, Num() $nu --> Num) is export
{
  gsl_cdf_chisq_Qinv($Q, $nu);
}
# F-distribution
sub fdist(Math::Libgsl::Random $r, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_ran_fdist($r.r, $nu1, $nu2);
}
sub fdist-pdf(Num() $x where * ≥ 0, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_ran_fdist_pdf($x, $nu1, $nu2);
}
sub fdist-P(Num() $x where * ≥ 0, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_cdf_fdist_P($x, $nu1, $nu2);
}
sub fdist-Q(Num() $x where * ≥ 0, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_cdf_fdist_Q($x, $nu1, $nu2);
}
sub fdist-Pinv(Num() $P, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_cdf_fdist_Pinv($P, $nu1, $nu2);
}
sub fdist-Qinv(Num() $Q, Num() $nu1, Num() $nu2 --> Num) is export
{
  gsl_cdf_fdist_Qinv($Q, $nu1, $nu2);
}
# t-distribution
sub tdist(Math::Libgsl::Random $r, Num() $nu --> Num) is export
{
  gsl_ran_tdist($r.r, $nu);
}
sub tdist-pdf(Num() $x, Num() $nu --> Num) is export
{
  gsl_ran_tdist_pdf($x, $nu);
}
sub tdist-P(Num() $x, Num() $nu --> Num) is export
{
  gsl_cdf_tdist_P($x, $nu);
}
sub tdist-Q(Num() $x, Num() $nu --> Num) is export
{
  gsl_cdf_tdist_Q($x, $nu);
}
sub tdist-Pinv(Num() $P, Num() $nu --> Num) is export
{
  gsl_cdf_tdist_Pinv($P, $nu);
}
sub tdist-Qinv(Num() $Q, Num() $nu --> Num) is export
{
  gsl_cdf_tdist_Qinv($Q, $nu);
}
# Beta Distribution
sub beta(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_beta($r.r, $a, $b);
}
sub beta-pdf(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_beta_pdf($x, $a, $b);
}
sub beta-P(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_beta_P($x, $a, $b);
}
sub beta-Q(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_beta_Q($x, $a, $b);
}
sub beta-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_beta_Pinv($P, $a, $b);
}
sub beta-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_beta_Qinv($Q, $a, $b);
}
# Logistic Distribution
sub logistic(Math::Libgsl::Random $r, Num() $a --> Num) is export
{
  gsl_ran_logistic($r.r, $a);
}
sub logistic-pdf(Num() $x, Num() $a --> Num) is export
{
  gsl_ran_logistic_pdf($x, $a);
}
sub logistic-P(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_logistic_P($x, $a);
}
sub logistic-Q(Num() $x, Num() $a --> Num) is export
{
  gsl_cdf_logistic_Q($x, $a);
}
sub logistic-Pinv(Num() $P, Num() $a --> Num) is export
{
  gsl_cdf_logistic_Pinv($P, $a);
}
sub logistic-Qinv(Num() $Q, Num() $a --> Num) is export
{
  gsl_cdf_logistic_Qinv($Q, $a);
}
# Pareto Distribution
sub pareto(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_pareto($r.r, $a, $b);
}
sub pareto-pdf(Num() $x, Num() $a, Num() $b where { $x ≥ $b } --> Num) is export
{
  gsl_ran_pareto_pdf($x, $a, $b);
}
sub pareto-P(Num() $x, Num() $a, Num() $b where { $x ≥ $b } --> Num) is export
{
  gsl_cdf_pareto_P($x, $a, $b);
}
sub pareto-Q(Num() $x, Num() $a, Num() $b where { $x ≥ $b } --> Num) is export
{
  gsl_cdf_pareto_Q($x, $a, $b);
}
sub pareto-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_pareto_Pinv($P, $a, $b);
}
sub pareto-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_pareto_Qinv($Q, $a, $b);
}
# Spherical Vector Distributions
sub d2dir(Math::Libgsl::Random $r --> List) is export
{
  my num64 $x = 0e0;
  my num64 $y = 0e0;
  gsl_ran_dir_2d($r.r, $x, $y);
  return $x, $y;
}
sub d2dir-trig-method(Math::Libgsl::Random $r --> List) is export
{
  my num64 $x = 0e0;
  my num64 $y = 0e0;
  gsl_ran_dir_2d_trig_method($r.r, $x, $y);
  return $x, $y;
}
sub d3dir(Math::Libgsl::Random $r --> List) is export
{
  my num64 $x = 0e0;
  my num64 $y = 0e0;
  my num64 $z = 0e0;
  gsl_ran_dir_3d($r.r, $x, $y, $z);
  return $x, $y, $z;
}
sub dndir(Math::Libgsl::Random $r, Int $n --> List) is export
{
  my $xarr = CArray[num64].new: 0e0 xx $n;
  gsl_ran_dir_nd($r.r, $n, $xarr);
  return $xarr.list;
}
# Weibull Distribution
sub weibull(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_weibull($r.r, $a, $b);
}
sub weibull-pdf(Num() $x where $x ≥ 0, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_weibull_pdf($x, $a, $b);
}
sub weibull-P(Num() $x where $x ≥ 0, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_weibull_P($x, $a, $b);
}
sub weibull-Q(Num() $x where $x ≥ 0, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_weibull_Q($x, $a, $b);
}
sub weibull-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_weibull_Pinv($P, $a, $b);
}
sub weibull-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_weibull_Qinv($Q, $a, $b);
}
# Type-1 Gumbel Distribution
sub gumbel1(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gumbel1($r.r, $a, $b);
}
sub gumbel1-pdf(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gumbel1_pdf($x, $a, $b);
}
sub gumbel1-P(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel1_P($x, $a, $b);
}
sub gumbel1-Q(Num() $x, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel1_Q($x, $a, $b);
}
sub gumbel1-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel1_Pinv($P, $a, $b);
}
sub gumbel1-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel1_Qinv($Q, $a, $b);
}
# Type-2 Gumbel Distribution
sub gumbel2(Math::Libgsl::Random $r, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gumbel2($r.r, $a, $b);
}
sub gumbel2-pdf(Num() $x where * > 0, Num() $a, Num() $b --> Num) is export
{
  gsl_ran_gumbel2_pdf($x, $a, $b);
}
sub gumbel2-P(Num() $x where * > 0, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel2_P($x, $a, $b);
}
sub gumbel2-Q(Num() $x where * > 0, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel2_Q($x, $a, $b);
}
sub gumbel2-Pinv(Num() $P, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel2_Pinv($P, $a, $b);
}
sub gumbel2-Qinv(Num() $Q, Num() $a, Num() $b --> Num) is export
{
  gsl_cdf_gumbel2_Qinv($Q, $a, $b);
}
# Dirichlet Distribution
sub dirichlet(Math::Libgsl::Random $r, Int $K, @alpha where *.all > 0 --> List) is export
{
  my $alpha = CArray[num64].new: @alpha».Num;
  my $theta = CArray[num64].new: 0e0 xx @alpha.elems;
  gsl_ran_dirichlet($r.r, $K, $alpha, $theta);
  return $theta.list;
}
sub dirichlet-pdf(Int $K, @alpha where *.all > 0, @theta where *.all ≥ 0 --> Num) is export
{
  my $alpha = CArray[num64].new: @alpha».Num;
  my $theta = CArray[num64].new: @theta».Num;
  gsl_ran_dirichlet_pdf($K, $alpha, $theta);
}
sub dirichlet-lnpdf(Int $K, @alpha where *.all > 0, @theta where *.all ≥ 0 --> Num) is export
{
  my $alpha = CArray[num64].new: @alpha».Num;
  my $theta = CArray[num64].new: @theta».Num;
  gsl_ran_dirichlet_lnpdf($K, $alpha, $theta);
}
# General Discrete Distributions
class Discrete
{
  has gsl_ran_discrete_t $!discrete;
  has Int                $.size;
  has                    @.probability;

  submethod BUILD(Int() :$!size, :@!probability where *.all > 0) {
    my $probability = CArray[num64].new: @!probability».Num;
    $!discrete = gsl_ran_discrete_preproc($!size, $probability);
  }
  submethod DESTROY() {
    gsl_ran_discrete_free($!discrete);
  }
  method discrete(Math::Libgsl::Random $r --> Int) {
    gsl_ran_discrete($r.r, $!discrete);
  }
  method discrete-pdf(Int $k --> Num) {
    gsl_ran_discrete_pdf($k, $!discrete);
  }
}
# Poisson Distribution
sub poisson(Math::Libgsl::Random $r, Num() $mu --> UInt) is export
{
  gsl_ran_poisson($r.r, $mu);
}
sub poisson-pdf(UInt $k, Num() $mu --> Num) is export
{
  gsl_ran_poisson_pdf($k, $mu);
}
sub poisson-P(UInt $k, Num() $mu --> Num) is export
{
  gsl_cdf_poisson_P($k, $mu);
}
sub poisson-Q(UInt $k, Num() $mu --> Num) is export
{
  gsl_cdf_poisson_Q($k, $mu);
}
# Bernoulli Distribution
sub bernoulli(Math::Libgsl::Random $r, Num() $p --> Int) is export
{
  gsl_ran_bernoulli($r.r, $p);
}
sub bernoulli-pdf(UInt $k, Num() $p --> Num) is export
{
  gsl_ran_bernoulli_pdf($k, $p);
}
# Binomial Distribution
sub binomial(Math::Libgsl::Random $r, Num() $p, UInt $n --> Int) is export
{
  gsl_ran_binomial($r.r, $p, $n);
}
sub binomial-pdf(UInt $k, Num() $p, UInt $n where * ≥ $k --> Num) is export
{
  gsl_ran_binomial_pdf($k, $p, $n);
}
sub binomial-P(UInt $k, Num() $p, UInt $n where * ≥ $k --> Num) is export
{
  gsl_cdf_binomial_P($k, $p, $n);
}
sub binomial-Q(UInt $k, Num() $p, UInt $n where * ≥ $k --> Num) is export
{
  gsl_cdf_binomial_Q($k, $p, $n);
}
# Multinomial Distribution
sub multinomial(Math::Libgsl::Random $r, Int $K, UInt $N, *@p where { @p.all ~~ Numeric } --> List) is export
{
  my $p = CArray[num64].new: @p».Num;
  my $n = CArray[uint32].new: 0 xx $K;
  gsl_ran_multinomial($r.r, $K, $N, $p, $n);
  return $n.list;
}
sub multinomial-pdf(Int $K, @p where { @p.all ~~ Numeric }, *@n where { @n.all ~~ UInt } --> Num) is export
{
  my $p = CArray[num64].new: @p».Num;
  my $n = CArray[uint32].new: @n;
  gsl_ran_multinomial_pdf($K, $p, $n);
}
sub multinomial-lnpdf(Int $K, @p where { @p.all ~~ Numeric }, *@n where { @n.all ~~ UInt } --> Num) is export
{
  my $p = CArray[num64].new: @p».Num;
  my $n = CArray[uint32].new: @n;
  gsl_ran_multinomial_lnpdf($K, $p, $n);
}
# Negative Binomial Distribution
sub negative-binomial(Math::Libgsl::Random $r, Num() $p, Num() $n --> UInt) is export
{
  gsl_ran_negative_binomial($r.r, $p, $n);
}
sub negative-binomial-pdf(UInt $k, Num() $p, Num() $n --> Num) is export
{
  gsl_ran_negative_binomial_pdf($k, $p, $n);
}
sub negative-binomial-P(UInt $k, Num() $p, Num() $n --> Num) is export
{
  gsl_cdf_negative_binomial_P($k, $p, $n);
}
sub negative-binomial-Q(UInt $k, Num() $p, Num() $n --> Num) is export
{
  gsl_cdf_negative_bin