use ffi;
use std::f64::INFINITY;
use std::intrinsics::{sqrtf64, powf64, fabsf64, floorf64, logf64};
use std::default::Default;
use libc::c_void;
use c_vec::CSlice;
pub struct PlainMonteCarlo {
s: *mut ffi::gsl_monte_plain_state,
}
impl PlainMonteCarlo {
pub fn new(dim: u64) -> Option<PlainMonteCarlo> {
let tmp = unsafe { ffi::gsl_monte_plain_alloc(dim) };
if tmp.is_null() {
None
} else {
Some(PlainMonteCarlo {
s: tmp
})
}
}
pub fn init(&self) -> ::Value {
unsafe { ffi::gsl_monte_plain_init(self.s) }
}
pub fn integrate<T>(&self, f: ::monte_function<T>, arg: &mut T, xl: &[f64], xu: &[f64], calls: u64, r: &::Rng, result: &mut f64,
abserr: &mut f64) -> ::Value {
unsafe {
let mut m = 0f64;
let mut q = 0f64;
let dim = (*self.s).dim as usize;
let mut t_x = CSlice::new((*self.s).x, dim);
let x = t_x.as_mut();
if xl.len() != dim || xu.len() != dim {
rgsl_error!("number of dimensions must match allocated size", ::Value::Inval);
}
for i in 0usize..dim {
if xu[i] <= xl[i] {
rgsl_error!("xu must be greater than xl", ::Value::Inval);
}
if xu[i] - xl[i] > ::DBL_MAX {
rgsl_error!("Range of integration is too large, please rescale", ::Value::Inval);
}
}
let mut vol = 1f64;
for i in 0usize..dim {
vol *= xu[i] - xl[i];
}
for n in 0usize..(calls as usize) {
for i in 0usize..dim {
x[i] = xl[i] + r.uniform_pos() * (xu[i] - xl[i]);
}
{
let fval = f(x, arg);
let d = fval - m;
m += d / (n as f64 + 1f64);
q += d * d * (n as f64 / (n as f64 + 1f64));
}
}
*result = vol * m;
*abserr = if calls < 2 {
INFINITY
} else {
vol * sqrtf64(q / (calls as f64 * (calls as f64 - 1f64)))
};
::Value::Success
}
}
}
impl Drop for PlainMonteCarlo {
fn drop(&mut self) {
unsafe { ffi::gsl_monte_plain_free(self.s) };
self.s = ::std::ptr::null_mut();
}
}
impl ffi::FFI<ffi::gsl_monte_plain_state> for PlainMonteCarlo {
fn wrap(s: *mut ffi::gsl_monte_plain_state) -> PlainMonteCarlo {
PlainMonteCarlo {
s: s
}
}
fn unwrap(s: &PlainMonteCarlo) -> *mut ffi::gsl_monte_plain_state {
s.s
}
}
pub struct MiserMonteCarlo {
s: *mut ffi::gsl_monte_miser_state
}
impl MiserMonteCarlo {
pub fn new(dim: u64) -> Option<MiserMonteCarlo> {
let tmp_pointer = unsafe { ffi::gsl_monte_miser_alloc(dim) };
if tmp_pointer.is_null() {
None
} else {
Some(MiserMonteCarlo {
s: tmp_pointer
})
}
}
pub fn init(&self) -> ::Value {
unsafe { ffi::gsl_monte_miser_init(self.s) }
}
#[allow(unused_assignments)]
pub fn integrate<T>(&self, f: ::monte_function<T>, arg: &mut T, xl: &[f64], xu: &[f64], t_calls: u64, r: &::Rng, result: &mut f64,
abserr: &mut f64) -> ::Value {
unsafe {
let mut calls = t_calls;
let mut calls_l = 0u64;
let mut calls_r = 0u64;
let min_calls = (*self.s).min_calls;
let mut i_bisect = 0usize;
let dim = (*self.s).dim as usize;
let mut found_best = false;
let mut res_est = 0f64;
let mut err_est = 0f64;
let mut res_r = 0f64;
let mut err_r = 0f64;
let mut res_l = 0f64;
let mut err_l = 0f64;
let mut weight_l = 0f64;
let mut weight_r = 0f64;
let mut t_x = CSlice::new((*self.s).x, dim);
let x = t_x.as_mut();
let mut t_xmid = CSlice::new((*self.s).xmid, dim);
let xmid = t_xmid.as_mut();
let mut t_sigma_l = CSlice::new((*self.s).sigma_l, dim);
let sigma_l = t_sigma_l.as_mut();
let mut t_sigma_r = CSlice::new((*self.s).sigma_r, dim);
let sigma_r = t_sigma_r.as_mut();
if dim != xl.len() || dim != xu.len() {
rgsl_error!("number of dimensions must match allocated size", ::Value::Inval);
}
for i in 0usize..dim {
if xu[i] <= xl[i] {
rgsl_error!("xu must be greater than xl", ::Value::Inval);
}
if xu[i] - xl[i] > ::DBL_MAX {
rgsl_error!("Range of integration is too large, please rescale", ::Value::Inval);
}
}
if (*self.s).alpha < 0f64 {
rgsl_error!("alpha must be non-negative", ::Value::Inval);
}
let mut vol = 1f64;
for i in 0usize..dim {
vol *= xu[i] - xl[i];
}
if calls < (*self.s).min_calls_per_bisection {
let mut m = 0f64;
let mut q = 0f64;
if calls < 2 {
rgsl_error!("insufficient calls for subvolume", ::Value::Failed);
}
for n in 0usize..(calls as usize) {
for i in 0usize..dim {
x[i] = xl[i] + r.uniform_pos() * (xu[i] - xl[i]);
}
{
let fval = f(x, arg);
let d = fval - m;
m += d / (n as f64 + 1f64);
q += d * d * (n as f64 / (n as f64 + 1f64));
}
}
*result = vol * m;
*abserr = vol * sqrtf64(q / (calls as f64 * (calls as f64 - 1f64)));
return ::Value::Success;
}
let tmp = calls as f64 * (*self.s).estimate_frac;
let estimate_calls = if min_calls as f64 > tmp {
min_calls
} else {
tmp as u64
};
if estimate_calls < dim as u64 * 4u64 {
rgsl_error!("insufficient calls to sample all halfspaces", ::Value::Sanity);
}
for i in 0usize..dim {
let s = if (r.uniform() - 0.5f64) >= 0f64 { (*self.s).dither } else { -(*self.s).dither };
xmid[i] = (0.5f64 + s) * xl[i] + (0.5f64 - s) * xu[i];
}
estimate_corrmc(f, arg, xl, xu, estimate_calls, r, self, &mut res_est, &mut err_est, xmid, sigma_l, sigma_r);
calls -= estimate_calls;
{
let mut best_var = ::DBL_MAX;
let beta = 2f64 / (1f64 + (*self.s).alpha);
weight_r = 1f64;
weight_l = weight_r;
for i in 0usize..dim {
if sigma_l[i] >= 0f64 && sigma_r[i] >= 0f64 {
let var = powf64(sigma_l[i], beta) + powf64(sigma_r[i], beta);
if var <= best_var {
found_best = true;
best_var = var;
i_bisect = i;
weight_l = powf64(sigma_l[i], beta);
weight_r = powf64(sigma_r[i], beta);
if weight_l == 0f64 && weight_r == 0f64 {
weight_l = 1f64;
weight_r = 1f64;
}
}
} else {
if sigma_l[i] < 0f64 {
rgsl_error!("no points in left-half space!", ::Value::Sanity);
}
if sigma_r[i] < 0f64 {
rgsl_error!("no points in right-half space!", ::Value::Sanity);
}
}
}
}
if !found_best {
i_bisect = r.uniform_int(dim as u64) as usize;
}
let xbi_l = xl[i_bisect];
let xbi_m = xmid[i_bisect];
let xbi_r = xu[i_bisect];
{
let fraction_l = fabsf64((xbi_m - xbi_l) / (xbi_r - xbi_l));
let fraction_r = 1f64 - fraction_l;
let a = fraction_l * weight_l;
let b = fraction_r * weight_r;
calls_l = (min_calls as f64 + (calls as f64 - 2f64 * min_calls as f64) * (a / (a + b))) as u64;
calls_r = (min_calls as f64 + (calls as f64 - 2f64 * min_calls as f64) * (b / (a + b))) as u64;
}
{
let mut xu_tmp : Vec<f64> = Vec::with_capacity(dim);
for it in xu.iter() {
xu_tmp.push(*it);
}
xu_tmp[i_bisect] = xbi_m;
let status = self.integrate(f, arg, xl.as_ref(), xu_tmp.as_ref(), calls_l, r, &mut res_l, &mut err_l);
if status != ::Value::Success {
return status;
}
}
{
let mut xl_tmp : Vec<f64> = Vec::with_capacity(dim);
for it in xl.iter() {
xl_tmp.push(*it);
}
xl_tmp[i_bisect] = xbi_m;
let status = self.integrate(f, arg, xl_tmp.as_ref(), xu, calls_r, r, &mut res_r, &mut err_r);
if status != ::Value::Success {
return status;
}
}
*result = res_l + res_r;
*abserr = sqrtf64(err_l * err_l + err_r * err_r);
::Value::Success
}
}
}
impl Drop for MiserMonteCarlo {
fn drop(&mut self) {
unsafe { ffi::gsl_monte_miser_free(self.s) };
self.s = ::std::ptr::null_mut();
}
}
impl ffi::FFI<ffi::gsl_monte_miser_state> for MiserMonteCarlo {
fn wrap(s: *mut ffi::gsl_monte_miser_state) -> MiserMonteCarlo {
MiserMonteCarlo {
s: s
}
}
fn unwrap(s: &MiserMonteCarlo) -> *mut ffi::gsl_monte_miser_state {
s.s
}
}
fn estimate_corrmc<T>(f: ::monte_function<T>, arg: &mut T, xl: &[f64], xu: &[f64], calls: u64, r: &::Rng, state: &MiserMonteCarlo,
result: &mut f64, abserr: &mut f64, xmid: &[f64], sigma_l: &mut [f64], sigma_r: &mut [f64]) -> ::Value {
unsafe {
let dim = (*state.s).dim as usize;
let mut t_x = CSlice::new((*state.s).x, dim);
let x = t_x.as_mut();
let mut t_fsum_l = CSlice::new((*state.s).fsum_l, dim);
let fsum_l = t_fsum_l.as_mut();
let mut t_fsum_r = CSlice::new((*state.s).fsum_r, dim);
let fsum_r = t_fsum_r.as_mut();
let mut t_fsum2_l = CSlice::new((*state.s).fsum2_l, dim);
let fsum2_l = t_fsum2_l.as_mut();
let mut t_fsum2_r = CSlice::new((*state.s).fsum2_r, dim);
let fsum2_r = t_fsum2_r.as_mut();
let mut t_hits_l = CSlice::new((*state.s).hits_l, dim);
let hits_l = t_hits_l.as_mut();
let mut t_hits_r = CSlice::new((*state.s).hits_r, dim);
let hits_r = t_hits_r.as_mut();
let mut m = 0f64;
let mut q = 0f64;
let mut vol = 1f64;
for i in 0usize..dim {
vol *= xu[i] - xl[i];
hits_r[i] = 0;
hits_l[i] = hits_r[i];
fsum_r[i] = 0f64;
fsum_l[i] = fsum_r[i];
fsum2_r[i] = 0f64;
fsum2_l[i] = fsum2_r[i];
sigma_r[i] = -1f64;
sigma_l[i] = sigma_r[i];
}
for n in 0usize..(calls as usize) {
let j = (n / 2usize) % dim;
let side = n % 2usize;
for i in 0usize..dim {
let z = r.uniform_pos();
if i != j {
x[i] = xl[i] + z * (xu[i] - xl[i]);
} else {
if side == 0 {
x[i] = xmid[i] + z * (xu[i] - xmid[i]);
} else {
x[i] = xl[i] + z * (xmid[i] - xl[i]);
}
}
}
let fval = f(x, arg);
{
let d = fval - m;
m += d / (n as f64 + 1f64);
q += d * d * (n as f64 / (n as f64 + 1f64));
}
for i in 0usize..dim {
if x[i] <= xmid[i] {
fsum_l[i] += fval;
fsum2_l[i] += fval * fval;
hits_l[i] += 1;
} else {
fsum_r[i] += fval;
fsum2_r[i] += fval * fval;
hits_r[i] += 1;
}
}
}
for i in 0usize..dim {
let fraction_l = (xmid[i] - xl[i]) / (xu[i] - xl[i]);
if hits_l[i] > 0 {
fsum_l[i] /= hits_l[i] as f64;
sigma_l[i] = sqrtf64(fsum2_l[i] - fsum_l[i] * fsum_l[i] / hits_l[i] as f64);
sigma_l[i] *= fraction_l * vol / hits_l[i] as f64;
}
if hits_r[i] > 0 {
fsum_r[i] /= hits_r[i] as f64;
sigma_r[i] = sqrtf64(fsum2_r[i] - fsum_r[i] * fsum_r[i] / hits_r[i] as f64);
sigma_r[i] *= (1f64 - fraction_l) * vol / hits_r[i] as f64;
}
}
*result = vol * m;
if calls < 2 {
*abserr = INFINITY;
} else {
*abserr = vol * sqrtf64(q / (calls as f64 * (calls as f64 - 1f64)));
}
::Value::Success
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct VegasParams {
pub alpha: f64,
pub iterations: u64,
pub stage: i32,
pub mode: ::VegasMode,
pub verbose: i32,
ostream: *mut c_void
}
impl Default for VegasParams {
fn default() -> VegasParams {
VegasParams {
alpha: 1.5f64,
iterations: 5u64,
stage: 0i32,
mode: ::VegasMode::Importance,
verbose: 0i32,
ostream: ::std::ptr::null_mut()
}
}
}
pub struct VegasMonteCarlo {
s: *mut ffi::gsl_monte_vegas_state
}
impl VegasMonteCarlo {
pub fn new(dim: u64) -> Option<VegasMonteCarlo> {
let tmp_pointer = unsafe { ffi::gsl_monte_vegas_alloc(dim) };
if tmp_pointer.is_null() {
None
} else {
Some(VegasMonteCarlo {
s: tmp_pointer
})
}
}
pub fn init(&self) -> ::Value {
unsafe { ffi::gsl_monte_vegas_init(self.s) }
}
pub fn integrate<T>(&self, f: ::monte_function<T>, arg: &mut T, xl: &[f64], xu: &[f64], t_calls: u64, r: &::Rng, result: &mut f64,
abserr: &mut f64) -> ::Value {
unsafe {
let mut calls = t_calls;
let dim = (*self.s).dim as usize;
if xl.len() != dim || xu.len() != dim {
rgsl_error!("number of dimensions must match allocated size", ::Value::Inval);
}
for i in 0usize..dim {
if xu[i] <= xl[i] {
rgsl_error!("xu must be greater than xl", ::Value::Inval);
}
if xu[i] - xl[i] > ::DBL_MAX {
rgsl_error!("Range of integration is too large, please rescale", ::Value::Inval);
}
}
if (*self.s).stage == 0 {
init_grid(self.s, xl, xu);
}
if (*self.s).stage <= 1 {
(*self.s).wtd_int_sum = 0f64;
(*self.s).sum_wgts = 0f64;
(*self.s).chi_sum = 0f64;
(*self.s).it_num = 1;
(*self.s).samples = 0;
(*self.s).chisq = 0f64;
}
if (*self.s).stage <= 2 {
let mut bins = (*self.s).bins_max;
let mut boxes = 1u64;
if (*self.s).mode != ::VegasMode::ImportanceOnly {
boxes = floorf64(powf64(calls as f64 / 2f64, 1f64 / dim as f64)) as u64;
(*self.s).mode = ::VegasMode::Importance;
if 2 * boxes >= (*self.s).bins_max {
let tmp = boxes / (*self.s).bins_max;
let box_per_bin = if tmp > 1 { tmp } else { 1 };
let tmp2 = boxes / box_per_bin;
bins = if tmp2 < (*self.s).bins_max { tmp2 } else { (*self.s).bins_max };
boxes = box_per_bin * bins;
(*self.s).mode = ::VegasMode::Stratified;
}
}
{
let tot_boxes = boxes.pow(dim as u32);
let tmp = calls / tot_boxes;
(*self.s).calls_per_box = if tmp > 2 { tmp as u32 } else { 2 };
calls = ((*self.s).calls_per_box * tot_boxes as u32) as u64;
}
(*self.s).jac = (*self.s).vol * powf64(bins as f64, dim as f64) / (calls as f64);
(*self.s).boxes = boxes as u32;
if bins != (*self.s).bins as u64 {
resize_grid(self.s, bins as usize);
}
}
(*self.s).it_start = (*self.s).it_num;
let mut cum_int = 0f64;
let mut cum_sig = 0f64;
for it in 0usize..((*self.s).iterations as usize) {
let mut intgrl = 0f64;
let mut tss = 0f64;
let calls_per_box = (*self.s).calls_per_box;
let jacbin = (*self.s).jac;
let mut x = CSlice::new((*self.s).x, dim);
let mut bin = CSlice::new((*self.s).bin, dim);
(*self.s).it_num = (*self.s).it_start + it as u32;
reset_grid_values(self.s);
let mut t_box = CSlice::new((*self.s).box_, dim);
init_box_coord(self.s, t_box.as_mut());
loop {
let mut m = 0f64;
let mut q = 0f64;
for k in 0usize..(calls_per_box as usize) {
let mut bin_vol = 0f64;
random_point(x.as_mut(), bin.as_mut(), &mut bin_vol, t_box.as_mut(), xl, xu, self.s, r);
let fval = jacbin * bin_vol * f(x.as_mut(), arg);
{
let d = fval - m;
m += d / (k as f64 + 1f64);
q += d * d * (k as f64 / (k as f64 + 1f64));
}
if (*self.s).mode != ::VegasMode::Stratified {
let f_sq = fval * fval;
accumulate_distribution(self.s, bin.as_mut(), f_sq);
}
}
intgrl += m * calls_per_box as f64;
let f_sq_sum = q * calls_per_box as f64;
tss += f_sq_sum;
if (*self.s).mode == ::VegasMode::Stratified {
accumulate_distribution(self.s, bin.as_mut(), f_sq_sum);
}
if !change_box_coord(self.s, t_box.as_mut()) {
break;
}
}
let var = tss / (calls_per_box as f64 - 1f64);
let wgt = if var > 0f64 {
1f64 / var
} else if (*self.s).sum_wgts > 0f64 {
(*self.s).sum_wgts / (*self.s).samples as f64
} else {
0f64
};
let intgrl_sq = intgrl * intgrl;
let sig = sqrtf64(var);
(*self.s).result = intgrl;
(*self.s).sigma = sig;
if wgt > 0f64 {
let sum_wgts = (*self.s).sum_wgts;
let wtd_int_sum = (*self.s).wtd_int_sum;
let m = if sum_wgts > 0f64 {
wtd_int_sum / sum_wgts
} else {
0f64
};
let q = intgrl - m;
(*self.s).samples += 1;
(*self.s).sum_wgts += wgt;
(*self.s).wtd_int_sum += intgrl * wgt;
(*self.s).chi_sum += intgrl_sq * wgt;
cum_int = (*self.s).wtd_int_sum / (*self.s).sum_wgts;
cum_sig = sqrtf64(1f64 / (*self.s).sum_wgts);
if (*self.s).samples == 1 {
(*self.s).chisq = 0f64;
} else {
(*self.s).chisq *= (*self.s).samples as f64 - 2f64;
(*self.s).chisq += (wgt / (1f64 + (wgt / sum_wgts))) * q * q;
(*self.s).chisq /= (*self.s).samples as f64 - 1f64;
}
} else {
cum_int += (intgrl - cum_int) / (it as f64 + 1f64);
cum_sig = 0f64;
}
refine_grid(self.s);
}
(*self.s).stage = 1;
*result = cum_int;
*abserr = cum_sig;
::Value::Success
}
}
pub fn chisq(&self) -> f64 {
unsafe { ffi::gsl_monte_vegas_chisq(self.s) }
}
pub fn runval(&self, result: &mut f64, sigma: &mut f64) {
unsafe { ffi::gsl_monte_vegas_runval(self.s, result, sigma) }
}
pub fn params_get(&self) -> VegasParams {
let mut tmp : VegasParams = Default::default();
unsafe { ffi::gsl_monte_vegas_params_get(self.s, &mut tmp) };
tmp
}
pub fn params_set(&self, params: &VegasParams) {
unsafe { ffi::gsl_monte_vegas_params_set(self.s, params) }
}
}
impl Drop for VegasMonteCarlo {
fn drop(&mut self) {
unsafe { ffi::gsl_monte_vegas_free(self.s) };
self.s = ::std::ptr::null_mut();
}
}
impl ffi::FFI<ffi::gsl_monte_vegas_state> for VegasMonteCarlo {
fn wrap(s: *mut ffi::gsl_monte_vegas_state) -> VegasMonteCarlo {
VegasMonteCarlo {
s: s
}
}
fn unwrap(s: &VegasMonteCarlo) -> *mut ffi::gsl_monte_vegas_state {
s.s
}
}
unsafe fn init_grid(s: *mut ffi::gsl_monte_vegas_state, xl: &[f64], xu: &[f64]) {
let mut vol = 1f64;
let mut t_delx = CSlice::new((*s).delx, xl.len());
let delx = t_delx.as_mut();
(*s).bins = 1;
for j in 0usize..xl.len() {
let dx = xu[j] - xl[j];
delx[j] = dx;
vol *= dx;
*(*s).xi.offset(j as isize) = 0f64;
*(*s).xi.offset((*s).dim as isize + j as isize) = 1f64;
}
(*s).vol = vol;
}
unsafe fn reset_grid_values(s: *mut ffi::gsl_monte_vegas_state) {
let dim = (*s).dim as isize;
let bins = (*s).bins as isize;
for i in 0isize..bins {
for j in 0isize..dim {
*(*s).d.offset(i * dim + j) = 0f64;
}
}
}
unsafe fn accumulate_distribution(s: *mut ffi::gsl_monte_vegas_state, bin: &[i32], y: f64) {
let dim = (*s).dim as usize;
for j in 0isize..(dim as isize) {
let i = bin[j as usize] as isize;
*(*s).d.offset(i * dim as isize + j) += y;
}
}
#[allow(unused_variables)]
#[allow(unused_assignments)]
unsafe fn random_point(x: &mut [f64], bin: &mut [i32], bin_vol: &mut f64, box_: &[i32], xl: &[f64], xu: &[f64], s: *mut ffi::gsl_monte_vegas_state,
r: &::Rng) {
let mut vol = 1f64;
let dim = (*s).dim as usize;
let bins = (*s).bins as usize;
let boxes = (*s).boxes as usize;
let mut t_delx = CSlice::new((*s).delx, xl.len());
let delx = t_delx.as_mut();
for j in 0usize..dim {
let z = ((box_[j] as f64 + r.uniform_pos()) / boxes as f64) * bins as f64;
let k = z as isize;
let mut y = 0f64;
let mut bin_width = 0f64;
bin[j] = k as i32;
if k == 0 {
bin_width = *(*s).xi.offset(dim as isize + j as isize);
y = z * bin_width;
} else {
bin_width = *(*s).xi.offset((k + 1) * (*s).dim as isize + j as isize) - *(*s).xi.offset(k * (*s).dim as isize + j as isize);
y = *(*s).xi.offset(k * (*s).dim as isize + j as isize) + (z - k as f64) * bin_width;
}
x[j] = xl[j] + y * delx[j];
vol *= bin_width;
}
*bin_vol = vol;
}
unsafe fn resize_grid(s: *mut ffi::gsl_monte_vegas_state, bins: usize) {
let dim = (*s).dim as usize;
let pts_per_bin = (*s).bins as f64 / bins as f64;
for j in 0usize..dim {
let mut xnew = 0f64;
let mut dw = 0f64;
let mut i = 1usize;
for k in 1usize..((*s).bins as usize + 1usize) {
dw += 1f64;
let xold = xnew;
xnew = *(*s).xi.offset(k as isize * dim as isize + j as isize);
while dw > pts_per_bin {
dw -= pts_per_bin;
*(*s).xin.offset(i as isize) = xnew - (xnew - xold) * dw;
i += 1;
}
}
for k in 1usize..bins {
*(*s).xi.offset(k as isize * dim as isize + j as isize) = *(*s).xin.offset(k as isize);
}
*(*s).xi.offset(bins as isize * dim as isize + j as isize) = 1f64;
}
(*s).bins = bins as u32;
}
unsafe fn refine_grid(s: *mut ffi::gsl_monte_vegas_state) {
let dim = (*s).dim as usize;
let bins = (*s).bins as usize;
for j in 0usize..dim {
let mut t_weight = CSlice::new((*s).weight, bins);
let weight = t_weight.as_mut();
let mut oldg = *(*s).d.offset(j as isize);
let mut newg = *(*s).d.offset(dim as isize + j as isize);
*(*s).d.offset(j as isize) = (oldg + newg) / 2f64;
let mut grid_tot_j = *(*s).xi.offset(j as isize);
for i in 1usize..(bins - 1usize) {
let rc = oldg + newg;
oldg = newg;
newg = *(*s).d.offset((i as isize + 1) * dim as isize + j as isize);
*(*s).d.offset(i as isize * dim as isize + j as isize) = (rc + newg) / 3f64;
grid_tot_j += *(*s).d.offset(i as isize * dim as isize + j as isize);
}
*(*s).d.offset((bins as isize - 1isize) * dim as isize + j as isize) = (newg + oldg) / 2f64;
grid_tot_j += *(*s).d.offset((bins as isize - 1isize) * dim as isize + j as isize);
let mut tot_weight = 0f64;
for i in 0usize..bins {
weight[i] = 0f64;
if *(*s).d.offset(i as isize * dim as isize + j as isize) > 0f64 {
oldg = grid_tot_j / *(*s).d.offset(i as isize * dim as isize + j as isize);
weight[i] = powf64(((oldg - 1f64) / oldg / logf64(oldg)), (*s).alpha);
}
tot_weight += weight[i];
}
{
let pts_per_bin = tot_weight / bins as f64;
let mut xnew = 0f64;
let mut dw = 0f64;
let mut i = 1usize;
for k in 0usize..bins {
dw += weight[k];
let xold = xnew;
xnew = *(*s).xi.offset((k as isize + 1isize) * dim as isize + j as isize);
while dw > pts_per_bin {
dw -= pts_per_bin;
*(*s).xin.offset(i as isize) = xnew - (xnew - xold) * dw / weight[k];
i += 1;
}
}
for k in 1usize..bins {
*(*s).xi.offset(k as isize * dim as isize + j as isize) = *(*s).xin.offset(k as isize);
}
*(*s).xi.offset(bins as isize * dim as isize + j as isize) = 1f64;
}
}
}
unsafe fn init_box_coord(s: *mut ffi::gsl_monte_vegas_state, box_: &mut [ffi::coord]) {
let dim = (*s).dim as usize;
for i in 0usize..dim {
box_[i] = 0;
}
}
unsafe fn change_box_coord(s: *mut ffi::gsl_monte_vegas_state, box_: &mut [ffi::coord]) -> bool {
let mut j = (*s).dim as isize - 1;
let ng = (*s).boxes;
while j >= 0 {
box_[j as usize] = (box_[j as usize] + 1) % ng as i32;
if box_[j as usize] != 0 {
return true;
}
j -= 1;
}
false
}