use itertools::{izip, Itertools};
use ndarray::{Array4, CowArray};
use pineappl::boc::{Bin, BinsWithFillLimits, Channel, Kinematics, Order, ScaleFuncForm, Scales};
use pineappl::convolutions::{Conv, ConvType, ConvolutionCache};
use pineappl::evolution::{AlphasTable, OperatorSliceInfo};
use pineappl::fk_table::{FkAssumptions, FkTable};
use pineappl::grid::{Grid, GridOptFlags};
use pineappl::interpolation::{Interp as InterpMain, InterpMeth, Map, ReweightMeth};
use pineappl::packed_array::PackedArray;
use pineappl::packed_array::{ravel_multi_index, unravel_index};
use pineappl::pids::PidBasis;
use pineappl::subgrid::{ImportSubgridV1, Subgrid};
use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::fs::File;
use std::mem;
use std::os::raw::{c_char, c_void};
use std::path::Path;
use std::slice;
pub const PINEAPPL_GOF_OPTIMIZE_SUBGRID_TYPE: GridOptFlags = GridOptFlags::OPTIMIZE_SUBGRID_TYPE;
pub const PINEAPPL_GOF_OPTIMIZE_NODES: GridOptFlags = GridOptFlags::OPTIMIZE_NODES;
pub const PINEAPPL_GOF_SYMMETRIZE_CHANNELS: GridOptFlags = GridOptFlags::SYMMETRIZE_CHANNELS;
pub const PINEAPPL_GOF_STRIP_EMPTY_ORDERS: GridOptFlags = GridOptFlags::STRIP_EMPTY_ORDERS;
pub const PINEAPPL_GOF_MERGE_SAME_CHANNELS: GridOptFlags = GridOptFlags::MERGE_SAME_CHANNELS;
pub const PINEAPPL_GOF_STRIP_EMPTY_CHANNELS: GridOptFlags = GridOptFlags::STRIP_EMPTY_CHANNELS;
fn grid_interpolation_params(key_vals: Option<&KeyVal>) -> Vec<InterpMain> {
let mut q2_min = 1e2;
let mut q2_max = 1e8;
let mut q2_nodes = 40;
let mut q2_order = 3;
let mut x1_min = 2e-7;
let mut x1_max = 1.0;
let mut x1_nodes = 50;
let mut x1_order = 3;
let mut x2_min = 2e-7;
let mut x2_max = 1.0;
let mut x2_nodes = 50;
let mut x2_order = 3;
let mut reweight = ReweightMeth::ApplGridX;
if let Some(keyval) = key_vals {
if let Some(value) = keyval
.ints
.get("q2_bins")
.or_else(|| keyval.ints.get("nq2"))
{
q2_nodes = usize::try_from(*value).unwrap();
}
if let Some(value) = keyval
.doubles
.get("q2_max")
.or_else(|| keyval.doubles.get("q2max"))
{
q2_max = *value;
}
if let Some(value) = keyval
.doubles
.get("q2_min")
.or_else(|| keyval.doubles.get("q2min"))
{
q2_min = *value;
}
if let Some(value) = keyval
.ints
.get("q2_order")
.or_else(|| keyval.ints.get("q2order"))
{
q2_order = usize::try_from(*value).unwrap();
}
if let Some(value) = keyval.bools.get("reweight") {
if !value {
reweight = ReweightMeth::NoReweight;
}
}
if let Some(value) = keyval.ints.get("x_bins").or_else(|| keyval.ints.get("nx")) {
let value = usize::try_from(*value).unwrap();
x1_nodes = value;
x2_nodes = value;
}
if let Some(value) = keyval
.doubles
.get("x_max")
.or_else(|| keyval.doubles.get("xmax"))
{
x1_max = *value;
x2_max = *value;
}
if let Some(value) = keyval
.doubles
.get("x_min")
.or_else(|| keyval.doubles.get("xmin"))
{
x1_min = *value;
x2_min = *value;
}
if let Some(value) = keyval
.ints
.get("x_order")
.or_else(|| keyval.ints.get("xorder"))
{
let value = usize::try_from(*value).unwrap();
x1_order = value;
x2_order = value;
}
if let Some(value) = keyval.ints.get("x1_bins") {
x1_nodes = usize::try_from(*value).unwrap();
}
if let Some(value) = keyval.doubles.get("x1_max") {
x1_max = *value;
}
if let Some(value) = keyval.doubles.get("x1_min") {
x1_min = *value;
}
if let Some(value) = keyval.ints.get("x1_order") {
x1_order = usize::try_from(*value).unwrap();
}
if let Some(value) = keyval.ints.get("x2_bins") {
x2_nodes = usize::try_from(*value).unwrap();
}
if let Some(value) = keyval.doubles.get("x2_max") {
x2_max = *value;
}
if let Some(value) = keyval.doubles.get("x2_min") {
x2_min = *value;
}
if let Some(value) = keyval.ints.get("x2_order") {
x2_order = usize::try_from(*value).unwrap();
}
}
vec![
InterpMain::new(
q2_min,
q2_max,
q2_nodes,
q2_order,
ReweightMeth::NoReweight,
Map::ApplGridH0,
InterpMeth::Lagrange,
),
InterpMain::new(
x1_min,
x1_max,
x1_nodes,
x1_order,
reweight,
Map::ApplGridF2,
InterpMeth::Lagrange,
),
InterpMain::new(
x2_min,
x2_max,
x2_nodes,
x2_order,
reweight,
Map::ApplGridF2,
InterpMeth::Lagrange,
),
]
}
#[derive(Default)]
pub struct Lumi(Vec<Channel>);
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_grid_bin_count(grid: *const Grid) -> usize {
let grid = unsafe { &*grid };
grid.bwfl().len()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_bin_dimensions(grid: *const Grid) -> usize {
let grid = unsafe { &*grid };
grid.bwfl().dimensions()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_bin_normalizations(grid: *const Grid, bin_sizes: *mut f64) {
let grid = unsafe { &*grid };
let bins = grid.bwfl().len();
let bin_sizes = unsafe { slice::from_raw_parts_mut(bin_sizes, bins) };
for (i, size) in grid.bwfl().normalizations().into_iter().enumerate() {
bin_sizes[i] = size;
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_bin_limits_left(
grid: *const Grid,
dimension: usize,
left: *mut f64,
) {
let grid = unsafe { &*grid };
let bins = grid.bwfl().len();
let result = unsafe { slice::from_raw_parts_mut(left, bins) };
for (lhs, rhs) in result.iter_mut().zip(
grid.bwfl()
.bins()
.iter()
.map(|bin| bin.limits()[dimension].0),
) {
*lhs = rhs;
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_bin_limits_right(
grid: *const Grid,
dimension: usize,
right: *mut f64,
) {
let grid = unsafe { &*grid };
let bins = grid.bwfl().len();
let result = unsafe { slice::from_raw_parts_mut(right, bins) };
for (lhs, rhs) in result.iter_mut().zip(
grid.bwfl()
.bins()
.iter()
.map(|bin| bin.limits()[dimension].1),
) {
*lhs = rhs;
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_clone(grid: *const Grid) -> Box<Grid> {
let grid = unsafe { &*grid };
Box::new(grid.clone())
}
#[deprecated(
since = "0.8.0",
note = "use `pineappl_grid_convolve_with_one` instead"
)]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolute_with_one(
grid: *const Grid,
pdg_id: i32,
xfx: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
alphas: extern "C" fn(q2: f64, state: *mut c_void) -> f64,
state: *mut c_void,
order_mask: *const bool,
channel_mask: *const bool,
xi_ren: f64,
xi_fac: f64,
results: *mut f64,
) {
unsafe {
pineappl_grid_convolve_with_one(
grid,
pdg_id,
xfx,
alphas,
state,
order_mask,
channel_mask,
xi_ren,
xi_fac,
results,
);
}
}
#[deprecated(
since = "0.8.0",
note = "use `pineappl_grid_convolve_with_two` instead"
)]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolute_with_two(
grid: *const Grid,
pdg_id1: i32,
xfx1: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
pdg_id2: i32,
xfx2: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
alphas: extern "C" fn(q2: f64, state: *mut c_void) -> f64,
state: *mut c_void,
order_mask: *const bool,
channel_mask: *const bool,
xi_ren: f64,
xi_fac: f64,
results: *mut f64,
) {
unsafe {
pineappl_grid_convolve_with_two(
grid,
pdg_id1,
xfx1,
pdg_id2,
xfx2,
alphas,
state,
order_mask,
channel_mask,
xi_ren,
xi_fac,
results,
);
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolve_with_one(
grid: *const Grid,
pdg_id: i32,
xfx: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
alphas: extern "C" fn(q2: f64, state: *mut c_void) -> f64,
state: *mut c_void,
order_mask: *const bool,
channel_mask: *const bool,
xi_ren: f64,
xi_fac: f64,
results: *mut f64,
) {
let grid = unsafe { &*grid };
let mut xfx = |id, x, q2| xfx(id, x, q2, state);
let mut als = |q2| alphas(q2, state);
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let channel_mask = if channel_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(channel_mask, grid.channels().len()) }
};
let bins = grid.bwfl().len();
let results = unsafe { slice::from_raw_parts_mut(results, bins) };
let mut convolution_cache = ConvolutionCache::new(
vec![Conv::new(ConvType::UnpolPDF, pdg_id)],
vec![&mut xfx],
&mut als,
);
results.copy_from_slice(&grid.convolve(
&mut convolution_cache,
order_mask,
&[],
channel_mask,
&[(xi_ren, xi_fac, 1.0)],
));
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolve_with_two(
grid: *const Grid,
pdg_id1: i32,
xfx1: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
pdg_id2: i32,
xfx2: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
alphas: extern "C" fn(q2: f64, state: *mut c_void) -> f64,
state: *mut c_void,
order_mask: *const bool,
channel_mask: *const bool,
xi_ren: f64,
xi_fac: f64,
results: *mut f64,
) {
let grid = unsafe { &*grid };
let mut xfx1 = |id, x, q2| xfx1(id, x, q2, state);
let mut xfx2 = |id, x, q2| xfx2(id, x, q2, state);
let mut als = |q2| alphas(q2, state);
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let channel_mask = if channel_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(channel_mask, grid.channels().len()) }
};
let bins = grid.bwfl().len();
let results = unsafe { slice::from_raw_parts_mut(results, bins) };
let mut convolution_cache = ConvolutionCache::new(
vec![
Conv::new(ConvType::UnpolPDF, pdg_id1),
Conv::new(ConvType::UnpolPDF, pdg_id2),
],
vec![&mut xfx1, &mut xfx2],
&mut als,
);
results.copy_from_slice(&grid.convolve(
&mut convolution_cache,
order_mask,
&[],
channel_mask,
&[(xi_ren, xi_fac, 1.0)],
));
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_dedup_channels(grid: *mut Grid, ulps: i64) {
let grid = unsafe { &mut *grid };
grid.dedup_channels(ulps);
}
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn pineappl_grid_delete(grid: Option<Box<Grid>>) {}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_fill2` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill(
grid: *mut Grid,
x1: f64,
x2: f64,
q2: f64,
order: usize,
observable: f64,
lumi: usize,
weight: f64,
) {
let grid = unsafe { &mut *grid };
grid.fill(order, observable, lumi, &[q2, x1, x2], weight);
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_fill_all2` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill_all(
grid: *mut Grid,
x1: f64,
x2: f64,
q2: f64,
order: usize,
observable: f64,
weights: *const f64,
) {
let grid = unsafe { &mut *grid };
let weights = unsafe { slice::from_raw_parts(weights, grid.channels().len()) };
for (channel, &weight) in weights.iter().enumerate() {
grid.fill(order, observable, channel, &[q2, x1, x2], weight);
}
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_fill_array2` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill_array(
grid: *mut Grid,
x1: *const f64,
x2: *const f64,
q2: *const f64,
orders: *const usize,
observables: *const f64,
lumis: *const usize,
weights: *const f64,
size: usize,
) {
let grid = unsafe { &mut *grid };
let x1 = unsafe { slice::from_raw_parts(x1, size) };
let x2 = unsafe { slice::from_raw_parts(x2, size) };
let q2 = unsafe { slice::from_raw_parts(q2, size) };
let orders = unsafe { slice::from_raw_parts(orders, size) };
let observables = unsafe { slice::from_raw_parts(observables, size) };
let lumis = unsafe { slice::from_raw_parts(lumis, size) };
let weights = unsafe { slice::from_raw_parts(weights, size) };
for (&x1, &x2, &q2, &order, &observable, &lumi, &weight) in
izip!(x1, x2, q2, orders, observables, lumis, weights)
{
grid.fill(order, observable, lumi, &[q2, x1, x2], weight);
}
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_channels` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_lumi(grid: *const Grid) -> Box<Lumi> {
let grid = unsafe { &*grid };
Box::new(Lumi(grid.channels().to_vec()))
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_order_params2` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_order_params(grid: *const Grid, order_params: *mut u32) {
let grid = unsafe { &*grid };
let orders = grid.orders();
let order_params = unsafe { slice::from_raw_parts_mut(order_params, 4 * orders.len()) };
for (i, order) in orders.iter().enumerate() {
order_params[4 * i] = order.alphas.into();
order_params[4 * i + 1] = order.alpha.into();
order_params[4 * i + 2] = order.logxir.into();
order_params[4 * i + 3] = order.logxif.into();
}
}
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_grid_order_count(grid: *const Grid) -> usize {
let grid = unsafe { &*grid };
grid.orders().len()
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_new2` instead")]
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_grid_new(
lumi: *const Lumi,
orders: usize,
order_params: *const u32,
bins: usize,
bin_limits: *const f64,
key_vals: *const KeyVal,
) -> Box<Grid> {
let order_params = unsafe { slice::from_raw_parts(order_params, 4 * orders) };
let orders: Vec<_> = order_params
.chunks(4)
.map(|s| Order {
alphas: s[0].try_into().unwrap(),
alpha: s[1].try_into().unwrap(),
logxir: s[2].try_into().unwrap(),
logxif: s[3].try_into().unwrap(),
logxia: 0,
})
.collect();
let key_vals = unsafe { key_vals.as_ref() };
let interps = grid_interpolation_params(key_vals);
let lumi = unsafe { &*lumi };
let mut convolutions = vec![Conv::new(ConvType::UnpolPDF, 2212); 2];
if let Some(keyval) = key_vals {
if let Some(value) = keyval.strings.get("initial_state_1") {
convolutions[0] =
Conv::new(ConvType::UnpolPDF, value.to_string_lossy().parse().unwrap());
}
if let Some(value) = keyval.strings.get("initial_state_2") {
convolutions[1] =
Conv::new(ConvType::UnpolPDF, value.to_string_lossy().parse().unwrap());
}
}
let bins = BinsWithFillLimits::from_fill_limits(
unsafe { slice::from_raw_parts(bin_limits, bins + 1) }.to_vec(),
)
.unwrap();
Box::new(Grid::new(
bins,
orders,
lumi.0.clone(),
PidBasis::Pdg,
convolutions,
interps,
vec![Kinematics::Scale(0), Kinematics::X(0), Kinematics::X(1)],
Scales {
ren: ScaleFuncForm::Scale(0),
fac: ScaleFuncForm::Scale(0),
frg: ScaleFuncForm::NoScale,
},
))
}
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_grid_read(filename: *const c_char) -> Box<Grid> {
let filename = unsafe { CStr::from_ptr(filename) };
let filename = filename.to_string_lossy();
let reader = File::open(filename.as_ref()).unwrap();
Box::new(Grid::read(reader).unwrap())
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_merge_bins(grid: *mut Grid, from: usize, to: usize) {
let grid = unsafe { &mut *grid };
grid.merge_bins(from..to).unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_delete_bins(
grid: *mut Grid,
bin_indices_ptr: *const usize,
bin_indices_len: usize,
) {
let grid = unsafe { &mut *grid };
let bin_indices = unsafe { std::slice::from_raw_parts(bin_indices_ptr, bin_indices_len) };
grid.delete_bins(bin_indices);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_merge_and_delete(grid: *mut Grid, other: Option<Box<Grid>>) {
if let Some(other) = other {
let grid = unsafe { &mut *grid };
grid.merge(*other).unwrap();
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_scale(grid: *mut Grid, factor: f64) {
let grid = unsafe { &mut *grid };
grid.scale(factor);
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_split_channels` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_split_lumi(grid: *mut Grid) {
let grid = unsafe { &mut *grid };
grid.split_channels();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_rotate_pid_basis(grid: *mut Grid, pid_basis: PidBasis) {
let grid = unsafe { &mut *grid };
grid.rotate_pid_basis(pid_basis);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_pid_basis(grid: *mut Grid) -> PidBasis {
let grid = unsafe { &mut *grid };
*grid.pid_basis()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_optimize(grid: *mut Grid) {
let grid = unsafe { &mut *grid };
grid.optimize();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_optimize_using(grid: *mut Grid, flags: GridOptFlags) {
let grid = unsafe { &mut *grid };
grid.optimize_using(flags);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_scale_by_bin(
grid: *mut Grid,
count: usize,
factors: *const f64,
) {
let grid = unsafe { &mut *grid };
let factors = unsafe { slice::from_raw_parts(factors, count) };
grid.scale_by_bin(factors);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_scale_by_order(
grid: *mut Grid,
alphas: f64,
alpha: f64,
logxir: f64,
logxif: f64,
global: f64,
) {
let grid = unsafe { &mut *grid };
grid.scale_by_order(alphas, alpha, logxir, logxif, 1.0, global);
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_metadata` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_key_value(
grid: *const Grid,
key: *const c_char,
) -> *mut c_char {
let grid = unsafe { &*grid };
let key = unsafe { CStr::from_ptr(key) };
let key = key.to_string_lossy();
let index = match key.as_ref() {
"initial_state_1" => Some(0),
"initial_state_2" => Some(1),
_ => None,
};
if let Some(index) = index {
return CString::new(grid.convolutions()[index].pid().to_string())
.unwrap()
.into_raw();
}
CString::new(grid.metadata().get(key.as_ref()).map_or("", String::as_str))
.unwrap()
.into_raw()
}
#[deprecated(since = "1.0.0", note = "use `pineappl_grid_set_metadata` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_set_key_value(
grid: *mut Grid,
key: *const c_char,
value: *const c_char,
) {
let grid = unsafe { &mut *grid };
let key = unsafe { CStr::from_ptr(key) }
.to_string_lossy()
.into_owned();
let value = unsafe { CStr::from_ptr(value) }
.to_string_lossy()
.into_owned();
let index = match key.as_str() {
"initial_state_1" => Some(0),
"initial_state_2" => Some(1),
_ => None,
};
if let Some(index) = index {
grid.convolutions_mut()[index] = Conv::new(ConvType::UnpolPDF, value.parse().unwrap());
}
grid.metadata_mut().insert(key, value);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_set_remapper(
grid: *mut Grid,
dimensions: usize,
normalizations: *const f64,
limits: *const f64,
) {
let grid = unsafe { &mut *grid };
let bins = grid.bwfl().len();
let normalizations = unsafe { slice::from_raw_parts(normalizations, bins) };
let limits = unsafe { slice::from_raw_parts(limits, 2 * dimensions * bins) };
let new_bins: Vec<_> = limits
.chunks_exact(2 * dimensions)
.zip(normalizations)
.map(|(limits, &normalization)| {
Bin::new(
limits
.chunks_exact(2)
.map(|limits| (limits[0], limits[1]))
.collect(),
normalization,
)
})
.collect();
grid.set_bwfl(
BinsWithFillLimits::new(new_bins, grid.bwfl().fill_limits().to_vec())
.unwrap(),
)
.unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_write(grid: *const Grid, filename: *const c_char) {
let grid = unsafe { &*grid };
let filename = unsafe { CStr::from_ptr(filename) };
let filename = filename.to_string_lossy();
let path = Path::new(filename.as_ref());
let writer = File::create(path).unwrap();
if path.extension().is_some_and(|ext| ext == "lz4") {
grid.write_lz4(writer).unwrap();
} else {
grid.write(writer).unwrap();
}
}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_add` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_lumi_add(
lumi: *mut Lumi,
combinations: usize,
pdg_id_pairs: *const i32,
factors: *const f64,
) {
let lumi = unsafe { &mut *lumi };
let pdg_id_pairs = unsafe { slice::from_raw_parts(pdg_id_pairs, 2 * combinations) };
let factors = if factors.is_null() {
vec![1.0; combinations]
} else {
unsafe { slice::from_raw_parts(factors, combinations) }.to_vec()
};
lumi.0.push(Channel::new(
pdg_id_pairs
.chunks(2)
.zip(factors)
.map(|x| (vec![x.0[0], x.0[1]], x.1))
.collect(),
));
}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_combinations` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_lumi_combinations(lumi: *const Lumi, entry: usize) -> usize {
let lumi = unsafe { &*lumi };
lumi.0[entry].entry().len()
}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_count` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_lumi_count(lumi: *const Lumi) -> usize {
let lumi = unsafe { &*lumi };
lumi.0.len()
}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_delete` instead")]
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn pineappl_lumi_delete(lumi: Option<Box<Lumi>>) {}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_entry` instead")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_lumi_entry(
lumi: *const Lumi,
entry: usize,
pdg_ids: *mut i32,
factors: *mut f64,
) {
let lumi = unsafe { &*lumi };
let entry = lumi.0[entry].entry();
let pdg_ids = unsafe { slice::from_raw_parts_mut(pdg_ids, 2 * entry.len()) };
let factors = unsafe { slice::from_raw_parts_mut(factors, entry.len()) };
entry
.iter()
.flat_map(|(pids, _)| pids)
.zip(pdg_ids.iter_mut())
.for_each(|(from, to)| *to = *from);
entry
.iter()
.map(|(_, factor)| factor)
.zip(factors.iter_mut())
.for_each(|(from, to)| *to = *from);
}
#[deprecated(since = "1.0.0", note = "use `pineappl_channels_new` instead")]
#[no_mangle]
#[must_use]
pub extern "C" fn pineappl_lumi_new() -> Box<Lumi> {
Box::default()
}
#[derive(Default)]
pub struct KeyVal {
bools: HashMap<String, bool>,
doubles: HashMap<String, f64>,
ints: HashMap<String, i32>,
strings: HashMap<String, CString>,
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn pineappl_keyval_delete(key_vals: Option<Box<KeyVal>>) {}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_keyval_bool(key_vals: *const KeyVal, key: *const c_char) -> bool {
let key_vals = unsafe { &*key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals.bools[key.to_string_lossy().as_ref()]
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_keyval_double(
key_vals: *const KeyVal,
key: *const c_char,
) -> f64 {
let key_vals = unsafe { &*key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals.doubles[key.to_string_lossy().as_ref()]
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_keyval_int(key_vals: *const KeyVal, key: *const c_char) -> i32 {
let key_vals = unsafe { &*key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals.ints[key.to_string_lossy().as_ref()]
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_keyval_string(
key_vals: *const KeyVal,
key: *const c_char,
) -> *const c_char {
let key_vals = unsafe { &*key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals.strings[key.to_string_lossy().as_ref()].as_ptr()
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
#[must_use]
pub extern "C" fn pineappl_keyval_new() -> Box<KeyVal> {
Box::default()
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_keyval_set_bool(
key_vals: *mut KeyVal,
key: *const c_char,
value: bool,
) {
let key_vals = unsafe { &mut *key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals
.bools
.insert(key.to_string_lossy().into_owned(), value);
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_keyval_set_double(
key_vals: *mut KeyVal,
key: *const c_char,
value: f64,
) {
let key_vals = unsafe { &mut *key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals
.doubles
.insert(key.to_string_lossy().into_owned(), value);
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_keyval_set_int(
key_vals: *mut KeyVal,
key: *const c_char,
value: i32,
) {
let key_vals = unsafe { &mut *key_vals };
let key = unsafe { CStr::from_ptr(key) };
key_vals
.ints
.insert(key.to_string_lossy().into_owned(), value);
}
#[deprecated(since = "1.0.0", note = "")]
#[no_mangle]
pub unsafe extern "C" fn pineappl_keyval_set_string(
key_vals: *mut KeyVal,
key: *const c_char,
value: *const c_char,
) {
let key_vals = unsafe { &mut *key_vals };
let key = unsafe { CStr::from_ptr(key) };
let value = unsafe { CStr::from_ptr(value) };
key_vals
.strings
.insert(key.to_string_lossy().into_owned(), CString::from(value));
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_string_delete(string: *mut c_char) {
if !string.is_null() {
mem::drop(unsafe { CString::from_raw(string) });
}
}
#[derive(Clone)]
pub struct Channels {
channels: Vec<Channel>,
convolutions: usize,
}
#[repr(C)]
pub struct Interp {
pub min: f64,
pub max: f64,
pub nodes: usize,
pub order: usize,
pub reweight: ReweightMeth,
pub map: Map,
pub interp_meth: InterpMeth,
}
#[repr(C)]
#[derive(Debug)]
pub struct OperatorInfo {
fac0: f64,
fac1: f64,
pid_basis: PidBasis,
conv_type: ConvType,
}
#[no_mangle]
#[must_use]
pub extern "C" fn pineappl_channels_new(convolutions: usize) -> Box<Channels> {
Box::new(Channels {
channels: Vec::new(),
convolutions,
})
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_channels_add(
channels: *mut Channels,
combinations: usize,
pdg_id_combinations: *const i32,
factors: *const f64,
) {
let &mut Channels {
ref mut channels,
convolutions,
} = unsafe { &mut *channels };
let pdg_id_pairs =
unsafe { slice::from_raw_parts(pdg_id_combinations, convolutions * combinations) };
let factors = if factors.is_null() {
vec![1.0; combinations]
} else {
unsafe { slice::from_raw_parts(factors, combinations) }.to_vec()
};
channels.push(Channel::new(
pdg_id_pairs
.chunks(convolutions)
.zip(factors)
.map(|x| ((0..convolutions).map(|i| x.0[i]).collect(), x.1))
.collect(),
));
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_channels(grid: *const Grid) -> Box<Channels> {
let grid = unsafe { &*grid };
Box::new(Channels {
channels: grid.channels().to_vec(),
convolutions: grid.convolutions().len(),
})
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_channels_count(channels: *const Channels) -> usize {
let Channels { channels, .. } = unsafe { &*channels };
channels.len()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_channels_combinations(
channels: *const Channels,
entry: usize,
) -> usize {
let Channels { channels, .. } = unsafe { &*channels };
channels[entry].entry().len()
}
#[no_mangle]
#[allow(unused_variables)]
pub extern "C" fn pineappl_channels_delete(channels: Option<Box<Channels>>) {}
#[no_mangle]
#[must_use]
pub unsafe extern "C" fn pineappl_grid_new2(
bins: usize,
bin_limits: *const f64,
orders: usize,
order_params: *const u8,
channels: *const Channels,
pid_basis: PidBasis,
convolutions: *const Conv,
interpolations: usize,
interps: *const Interp,
kinematics: *const Kinematics,
scales: *const ScaleFuncForm,
) -> Box<Grid> {
let bins = BinsWithFillLimits::from_fill_limits(
unsafe { slice::from_raw_parts(bin_limits, bins + 1) }.to_vec(),
)
.unwrap();
let order_params = unsafe { slice::from_raw_parts(order_params, 5 * orders) };
let orders: Vec<_> = order_params
.chunks(5)
.map(|s| Order {
alphas: s[0],
alpha: s[1],
logxir: s[2],
logxif: s[3],
logxia: s[4],
})
.collect();
let Channels {
channels,
convolutions: nb_convolutions,
} = unsafe { &*channels }.clone();
let convolutions = unsafe { slice::from_raw_parts(convolutions, nb_convolutions) }.to_vec();
let interp_slices = unsafe { std::slice::from_raw_parts(interps, interpolations) };
let interp_vecs: Vec<_> = interp_slices
.iter()
.map(|interp| {
InterpMain::new(
interp.min,
interp.max,
interp.nodes,
interp.order,
interp.reweight,
interp.map,
interp.interp_meth,
)
})
.collect();
let kinematics = unsafe { slice::from_raw_parts(kinematics, interp_vecs.len()) }.to_vec();
let mu_scales = unsafe { std::slice::from_raw_parts(scales, 3) };
Box::new(Grid::new(
bins,
orders,
channels,
pid_basis,
convolutions,
interp_vecs,
kinematics,
Scales {
ren: mu_scales[0].clone(),
fac: mu_scales[1].clone(),
frg: mu_scales[2].clone(),
},
))
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill2(
grid: *mut Grid,
order: usize,
observable: f64,
channel: usize,
ntuple: *const f64,
weight: f64,
) {
let grid = unsafe { &mut *grid };
let ntuple = unsafe { slice::from_raw_parts(ntuple, grid.kinematics().len()) };
grid.fill(order, observable, channel, ntuple, weight);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill_all2(
grid: *mut Grid,
order: usize,
observable: f64,
ntuple: *const f64,
weights: *const f64,
) {
let grid = unsafe { &mut *grid };
let ntuple = unsafe { slice::from_raw_parts(ntuple, grid.kinematics().len()) };
let weights = unsafe { slice::from_raw_parts(weights, grid.channels().len()) };
for (channel, &weight) in weights.iter().enumerate() {
grid.fill(order, observable, channel, ntuple, weight);
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fill_array2(
grid: *mut Grid,
orders: *const usize,
observables: *const f64,
ntuples: *const f64,
channels: *const usize,
weights: *const f64,
size: usize,
) {
let grid = unsafe { &mut *grid };
let orders = unsafe { slice::from_raw_parts(orders, size) };
let observables = unsafe { slice::from_raw_parts(observables, size) };
let channels = unsafe { slice::from_raw_parts(channels, size) };
let weights = unsafe { slice::from_raw_parts(weights, size) };
let ntuples = unsafe { slice::from_raw_parts(ntuples, size * grid.kinematics().len()) };
let ntuples_2d: Vec<&[f64]> = ntuples.chunks(grid.kinematics().len()).collect();
for (ntuple, &order, &observable, &channel, &weight) in
izip!(ntuples_2d, orders, observables, channels, weights)
{
grid.fill(order, observable, channel, ntuple, weight);
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_split_channels(grid: *mut Grid) {
let grid = unsafe { &mut *grid };
grid.split_channels();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_channels_entry(
channels: *const Channels,
entry: usize,
pdg_ids: *mut i32,
factors: *mut f64,
) {
let Channels {
channels,
convolutions,
} = unsafe { &*channels };
let entry = channels[entry].entry();
let pdg_ids = unsafe { slice::from_raw_parts_mut(pdg_ids, convolutions * entry.len()) };
let factors = unsafe { slice::from_raw_parts_mut(factors, entry.len()) };
entry
.iter()
.flat_map(|(pids, _)| pids)
.zip(pdg_ids.iter_mut())
.for_each(|(from, to)| *to = *from);
entry
.iter()
.map(|(_, factor)| factor)
.zip(factors.iter_mut())
.for_each(|(from, to)| *to = *from);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_order_params2(grid: *const Grid, order_params: *mut u32) {
let grid = unsafe { &*grid };
let orders = grid.orders();
let order_params = unsafe { slice::from_raw_parts_mut(order_params, 5 * orders.len()) };
for (i, order) in orders.iter().enumerate() {
order_params[5 * i] = order.alphas.into();
order_params[5 * i + 1] = order.alpha.into();
order_params[5 * i + 2] = order.logxir.into();
order_params[5 * i + 3] = order.logxif.into();
order_params[5 * i + 4] = order.logxia.into();
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolve(
grid: *const Grid,
xfx: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
alphas: extern "C" fn(q2: f64, state: *mut c_void) -> f64,
pdfs_state: *mut *mut c_void,
alphas_state: *mut c_void,
order_mask: *const bool,
channel_mask: *const bool,
bin_indices: *const usize,
nb_scales: usize,
mu_scales: *const f64,
results: *mut f64,
) {
let grid = unsafe { &*grid };
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let channel_mask = if channel_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(channel_mask, grid.channels().len()) }
};
let bin_indices = if bin_indices.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(bin_indices, grid.bwfl().len()) }
};
let mut als = |q2| alphas(q2, alphas_state);
let pdfs_slices = unsafe { slice::from_raw_parts(pdfs_state, grid.convolutions().len()) };
let mut xfx_funcs: Vec<_> = pdfs_slices
.iter()
.map(|&state| move |id, x, q2| xfx(id, x, q2, state))
.collect();
let mut convolution_cache = ConvolutionCache::new(
grid.convolutions().to_vec(),
xfx_funcs
.iter_mut()
.map(|fx| fx as &mut dyn FnMut(i32, f64, f64) -> f64)
.collect(),
&mut als,
);
let mu_scales = if mu_scales.is_null() {
&[(1.0, 1.0, 1.0)]
} else {
unsafe { slice::from_raw_parts(mu_scales.cast::<(f64, f64, f64)>(), nb_scales) }
};
let results = unsafe { slice::from_raw_parts_mut(results, grid.bwfl().len()) };
results.copy_from_slice(&grid.convolve(
&mut convolution_cache,
order_mask,
bin_indices,
channel_mask,
mu_scales,
));
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_fix_convolution(
grid: *const Grid,
conv_idx: usize,
xfx: extern "C" fn(pdg_id: i32, x: f64, q2: f64, state: *mut c_void) -> f64,
state: *mut c_void,
xi: f64,
) -> Box<Grid> {
let grid = unsafe { &*grid };
let mut xfx_closure = |id, x, q2| xfx(id, x, q2, state);
Box::new(
grid.fix_convolution(conv_idx, &mut xfx_closure, xi)
.unwrap(),
)
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_conv_types(grid: *const Grid, conv_types: *mut ConvType) {
let grid = unsafe { &*grid };
let conv_types = unsafe { slice::from_raw_parts_mut(conv_types, grid.convolutions().len()) };
let convs_array = grid
.convolutions()
.iter()
.map(Conv::conv_type)
.collect_vec();
conv_types.copy_from_slice(&convs_array);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_convolutions_len(grid: *mut Grid) -> usize {
let grid = unsafe { &mut *grid };
grid.convolutions().len()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_kinematics_len(grid: *mut Grid) -> usize {
let grid = unsafe { &mut *grid };
grid.kinematics().len()
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_subgrid_shape(
grid: *const Grid,
bin: usize,
order: usize,
channel: usize,
shape: *mut usize,
) {
let grid = unsafe { &*grid };
let subgrid = &grid.subgrids()[[order, bin, channel]];
let subgrid_shape = if subgrid.is_empty() {
let subgrid_dim = grid.kinematics().len();
&vec![0; subgrid_dim]
} else {
subgrid.shape()
};
let shape = unsafe { slice::from_raw_parts_mut(shape, grid.kinematics().len()) };
shape.copy_from_slice(subgrid_shape);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_subgrid_node_values(
grid: *const Grid,
bin: usize,
order: usize,
channel: usize,
node_values: *mut f64,
) {
let grid = unsafe { &*grid };
let subgrid = &grid.subgrids()[[order, bin, channel]];
let flatten_subgrid: Vec<f64> = subgrid.node_values().into_iter().flatten().collect();
let node_values = unsafe { slice::from_raw_parts_mut(node_values, flatten_subgrid.len()) };
node_values.copy_from_slice(flatten_subgrid.as_slice());
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_subgrid_array(
grid: *const Grid,
bin: usize,
order: usize,
channel: usize,
subgrid_array: *mut f64,
) {
let grid = unsafe { &*grid };
let subgrid = &grid.subgrids()[[order, bin, channel]];
if !subgrid.is_empty() {
let shape = subgrid.shape();
let subgrid_array =
unsafe { slice::from_raw_parts_mut(subgrid_array, shape.iter().product()) };
for (index, value) in subgrid.indexed_iter() {
let ravel_index = ravel_multi_index(index.as_slice(), shape);
subgrid_array[ravel_index] = value;
}
}
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_set_subgrid(
grid: *mut Grid,
bin: usize,
order: usize,
channel: usize,
node_values: *mut f64,
subgrid_array: *mut f64,
subgrid_shape: *mut usize,
) {
let grid = unsafe { &mut *grid };
let num_kins = grid.kinematics().len();
let subgrid_shape = unsafe { slice::from_raw_parts(subgrid_shape, num_kins) };
let subgrid_array =
unsafe { slice::from_raw_parts(subgrid_array, subgrid_shape.iter().product()) };
let node_values: Vec<Vec<f64>> = {
let mut offset = 0;
subgrid_shape
.iter()
.map(|&dim_size| {
let dim_nodes =
unsafe { slice::from_raw_parts(node_values.add(offset), dim_size) }.to_vec();
offset += dim_size;
dim_nodes
})
.collect()
};
let mut sparse_array: PackedArray<f64> =
PackedArray::new(node_values.iter().map(Vec::len).collect());
for (index, value) in subgrid_array
.iter()
.enumerate()
.filter(|(_, value)| **value != 0.0)
{
let index_unravel = unravel_index(index, subgrid_shape);
sparse_array[index_unravel.as_slice()] = *value;
}
let subgrid = ImportSubgridV1::new(sparse_array, node_values);
grid.subgrids_mut()[[order, bin, channel]] = subgrid.into();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_set_bwfl(
grid: *mut Grid,
bins_lower: *mut f64,
bins_upper: *mut f64,
n_bins: usize,
bin_dim: usize,
normalizations: *mut f64,
) {
let grid = unsafe { &mut *grid };
let bins_lower = unsafe { slice::from_raw_parts(bins_lower, bin_dim * n_bins) };
let bins_upper = unsafe { slice::from_raw_parts(bins_upper, bin_dim * n_bins) };
let normalizations = unsafe { slice::from_raw_parts(normalizations, n_bins) };
let limits: Vec<Vec<(f64, f64)>> = bins_lower
.chunks(bin_dim)
.zip(bins_upper.chunks(bin_dim))
.map(|(bl_chunk, bu_chunk)| {
bl_chunk
.iter()
.zip(bu_chunk.iter())
.map(|(&a, &b)| (a, b))
.collect()
})
.collect();
grid.set_bwfl(
BinsWithFillLimits::from_limits_and_normalizations(limits, normalizations.to_vec())
.unwrap(),
)
.unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_evolve_info_shape(
grid: *const Grid,
order_mask: *const bool,
shape_info: *mut usize,
) {
let grid = unsafe { &*grid };
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let shape_info = unsafe { slice::from_raw_parts_mut(shape_info, 5) };
let evolve_info = grid.evolve_info(order_mask);
let evinfo_shapes = [
evolve_info.fac1.len(),
evolve_info.frg1.len(),
evolve_info.pids1.len(),
evolve_info.x1.len(),
evolve_info.ren1.len(),
];
shape_info.copy_from_slice(&evinfo_shapes);
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_evolve_info(
grid: *const Grid,
order_mask: *const bool,
fac1: *mut f64,
frg1: *mut f64,
pids1: *mut i32,
x1: *mut f64,
ren1: *mut f64,
) {
let grid = unsafe { &*grid };
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let evolve_info = grid.evolve_info(order_mask);
let fac1 = unsafe { slice::from_raw_parts_mut(fac1, evolve_info.fac1.len()) };
let frg1 = unsafe { slice::from_raw_parts_mut(frg1, evolve_info.frg1.len()) };
let pids1 = unsafe { slice::from_raw_parts_mut(pids1, evolve_info.pids1.len()) };
let x1 = unsafe { slice::from_raw_parts_mut(x1, evolve_info.x1.len()) };
let ren1 = unsafe { slice::from_raw_parts_mut(ren1, evolve_info.ren1.len()) };
fac1.copy_from_slice(&grid.evolve_info(order_mask).fac1);
frg1.copy_from_slice(&grid.evolve_info(order_mask).frg1);
pids1.copy_from_slice(&grid.evolve_info(order_mask).pids1);
x1.copy_from_slice(&grid.evolve_info(order_mask).x1);
ren1.copy_from_slice(&grid.evolve_info(order_mask).ren1);
}
pub type OperatorCallback = unsafe extern "C" fn(
usize, f64, *const i32, *const f64, *const i32, *const f64, *const usize, *mut f64, *mut c_void, );
#[no_mangle]
pub unsafe extern "C" fn pineappl_grid_evolve(
grid: *const Grid,
nb_slices: usize,
slices: OperatorCallback,
operator_info: *const OperatorInfo,
pids_in: *const i32,
x_in: *const f64,
pids_out: *const i32,
x_out: *const f64,
eko_shape: *const usize,
state: *mut c_void,
order_mask: *const bool,
xi: *const f64,
ren1: *const f64,
alphas: *const f64,
) -> Box<Grid> {
let grid = unsafe { &*grid };
let order_mask = if order_mask.is_null() {
&[]
} else {
unsafe { slice::from_raw_parts(order_mask, grid.orders().len()) }
};
let eko_shape = unsafe { slice::from_raw_parts(eko_shape, 4) };
let pids_in = unsafe { slice::from_raw_parts(pids_in, eko_shape[0]) };
let x_in = unsafe { slice::from_raw_parts(x_in, eko_shape[1]) };
let pids_out = unsafe { slice::from_raw_parts(pids_out, eko_shape[2]) };
let x_out = unsafe { slice::from_raw_parts(x_out, eko_shape[3]) };
let evolve_info = grid.evolve_info(order_mask);
let ren1_len = evolve_info.ren1.len();
let ren1 = unsafe { slice::from_raw_parts(ren1, ren1_len) };
let alphas = unsafe { slice::from_raw_parts(alphas, ren1_len) };
let xi = unsafe { slice::from_raw_parts(xi, 3) };
let operator_info = unsafe {
slice::from_raw_parts(operator_info, nb_slices * evolve_info.fac1.len())
.chunks_exact(evolve_info.fac1.len())
};
let shape: (usize, usize, usize, usize) = <[usize; 4]>::try_from(eko_shape)
.unwrap()
.into();
let op_slices = operator_info
.enumerate()
.map(|(op_index, op_infos)| {
op_infos.iter().map(move |op_info| {
let operator_slice_info = OperatorSliceInfo {
pid_basis: op_info.pid_basis,
fac0: op_info.fac0,
pids0: pids_out.to_vec(),
x0: x_out.to_vec(),
fac1: op_info.fac1,
pids1: pids_in.to_vec(),
x1: x_in.to_vec(),
conv_type: op_info.conv_type,
};
let mut array = CowArray::from(Array4::zeros(shape));
unsafe {
slices(
op_index,
op_info.fac1,
pids_in.as_ptr(),
x_in.as_ptr(),
pids_out.as_ptr(),
x_out.as_ptr(),
eko_shape.as_ptr(),
array
.as_slice_mut()
.unwrap()
.as_mut_ptr(),
state,
);
}
Ok::<_, std::io::Error>((operator_slice_info, array))
})
})
.collect();
let fk_table = grid
.evolve(
op_slices,
order_mask,
(xi[0], xi[1], xi[2]),
&AlphasTable {
ren1: ren1.to_vec(),
alphas: alphas.to_vec(),
},
)
.unwrap();
Box::new(fk_table.into_grid())
}
#[no_mangle]
pub unsafe extern "C" fn pineappl_fktable_optimize(grid: *mut Grid, assumptions: FkAssumptions) {
let grid = unsafe { &mut *grid };
let read_grid = unsafe { std::ptr::read(grid) };
let mut fktable = FkTable::try_from(read_grid)
.unwrap();
fktable.optimize(assumptions);
unsafe { std::ptr::write(grid, fktable.into_grid()) };
}