20 double sigma_scale = 3.0;
 
   24     ZigguratBox(
double x_min, 
double x_max, 
double y_max, 
double y_lower)
 
   25         : m_x_min(x_min), m_x_max(x_max), m_y_max(y_max), m_y_lower(y_lower)
 
   37 std::pair<double, double> samplingZiggurat(
double r, 
double x_func_max, 
double (*func_phi)(
double))
 
   42     std::random_device rd;  
 
   43     std::mt19937 gen(rd()); 
 
   44     std::uniform_real_distribution<double> uniformDist(0.0, 1.0);
 
   46     double box_width = (x_func_max + r) / n_boxes; 
 
   47     std::vector<ZigguratBox> boxes;
 
   48     std::vector<double> cum_area_vector;
 
   50     double x_min = 0, x_max = 0, y_max = 0, y_lower = 0, cum_area_box = 0;
 
   54     for (
size_t i = 0; i < n_boxes; ++i) {
 
   60         if (x_func_max >= x_max) {
 
   61             y_max = func_phi(x_max);
 
   62             y_lower = func_phi(x_min);
 
   63         } 
else if (x_func_max > x_min && x_func_max <= x_max) {
 
   64             y_max = func_phi(x_func_max);
 
   65             y_lower = std::min(func_phi(x_min), func_phi(x_max));
 
   67             y_max = func_phi(x_min);
 
   68             y_lower = func_phi(x_max);
 
   71         boxes.emplace_back(ZigguratBox(x_min, x_max, y_max, y_lower));
 
   73         cum_area_box += box_width * y_max;
 
   74         cum_area_vector.emplace_back(cum_area_box);
 
   78     for (
size_t i = 0; i < n_boxes; ++i)
 
   79         cum_area_vector[i] = cum_area_vector[i] / cum_area_vector.back();
 
   83     bool solnFound(
false);
 
   86         double random_cum_area = uniformDist(gen);
 
   87         for (
size_t i = 0; i < n_boxes; ++i) {
 
   88             if (random_cum_area <= cum_area_vector[i]) {
 
   89                 double random_y = uniformDist(gen) * boxes[i].m_y_max;
 
   91                 std::uniform_real_distribution<double> uniformDistAB(boxes[i].m_x_min,
 
   93                 double phi_attempt = uniformDistAB(gen);
 
   95                 if (random_y <= boxes[i].m_y_lower) {
 
   99                     if (random_y <= func_phi(phi_attempt)) {
 
  110     double alpha = 2 * M_PI * uniformDist(gen);
 
  111     return std::make_pair(phi, alpha);
 
  114 double func_phi_Cauchy(
double phi)
 
  117     return phi * std::exp(-phi);
 
  120 double func_phi_Cone(
double phi)
 
  123     return 6 * (1 - phi) * phi;
 
  127 IDistribution2DSampler::~IDistribution2DSampler() = 
default;
 
  129 std::pair<double, double> Distribution2DCauchySampler::randomSample()
 const 
  133     double phi_max_Cauchy = 1.0;
 
  135     double r = sigma_scale * std::sqrt(2); 
 
  136     std::pair<double, double> samples = samplingZiggurat(r, phi_max_Cauchy, func_phi_Cauchy);
 
  137     return std::make_pair(m_omega_x * samples.first * std::cos(samples.second),
 
  138                           m_omega_y * samples.first * std::sin(samples.second));
 
  141 std::pair<double, double> Distribution2DGaussSampler::randomSample()
 const 
  143     std::random_device rd;  
 
  144     std::mt19937 gen(rd()); 
 
  145     std::uniform_real_distribution<double> uniformDist(0.0, 1.0);
 
  147     double cdf_value_phi = uniformDist(gen);
 
  150     double phi = std::sqrt(-2 * std::log(1 - cdf_value_phi));
 
  151     double alpha = 2 * M_PI * uniformDist(gen);
 
  152     return std::make_pair(m_omega_x * phi * std::cos(alpha), m_omega_y * phi * std::sin(alpha));
 
  155 std::pair<double, double> Distribution2DGateSampler::randomSample()
 const 
  157     std::random_device rd;  
 
  158     std::mt19937 gen(rd()); 
 
  159     std::uniform_real_distribution<double> uniformDist(0.0, 1.0);
 
  161     double cdf_value_phi = uniformDist(gen);
 
  164     double phi = std::sqrt(cdf_value_phi);
 
  165     double alpha = 2 * M_PI * uniformDist(gen);
 
  166     return std::make_pair(m_omega_x * phi * std::cos(alpha), m_omega_y * phi * std::sin(alpha));
 
  169 std::pair<double, double> Distribution2DConeSampler::randomSample()
 const 
  173     double phi_max_Cone = 0.5;
 
  176     std::pair<double, double> samples = samplingZiggurat(r, phi_max_Cone, func_phi_Cone);
 
  177     return std::make_pair(m_omega_x * samples.first * std::cos(samples.second),
 
  178                           m_omega_y * samples.first * std::sin(samples.second));
 
Defines interface class IFTDistribution1D, and children thereof.