Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion docs/user/native-apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,35 @@ SDK and library, not an older installed release. Declare the operators with
`Generator.generate(..., correlators=CorrelatorConfig(...))` or
`generate ... --correlators FILE.json` as in [Born Correlations](../correlators.md).

Native correlated evaluation is **binary64 only**, like the ordinary native
Native correlated evaluation uses **binary64 buffers by default**, like the ordinary native
SDK. It runs in RustiCol without Python or Symbolica. The separate Python
correlated executor retains Symbolica-backed double-double and arbitrary
precision; its `precision=16` path also uses that executor.

For cancellation-prone correlated requests, the development SDK can load an
explicit native binary128 companion. Preparation requires retained evaluators,
Symbolica and Linux GCC with quadmath:

```python
runtime = Runtime.load("PROCESS_ARTIFACT")
runtime.compile_correlated_rescue("PROCESS.rescue.so")
```

Attach that trusted executable library with
`rusticol_runtime_load_correlated_rescue(handle, path)`, then use
`rusticol_runtime_evaluate_correlated_many_rescued_f64` with the same request
and binary64 buffer layout as `_many_f64`. The loader checks the artifact ID
and dimensions. Ordinary calls remain unchanged; no automatic rescue or
precision switching is implied. Convenience-language wrappers do not yet
expose these two C functions.

The companion recomputes internal momenta, currents and amplitudes in binary128,
returns high/low binary64 amplitude components, and reuses the SDK's twofold
full-colour contraction. External sources and mutable model inputs remain
binary64. Numerical execution needs quadmath, not Python or Symbolica. Missing
kernels, incompatible artifacts and unsupported instruction programs fail
explicitly; small imaginary parts are not clamped.

LC, NLC and full colour are selected at generation for each inserted colour
matrix, independently of connection order. The underlying amplitudes remain
complete and full-colour: ordinary `evaluate`/`evaluate_resolved` still return
Expand Down
14 changes: 14 additions & 0 deletions rust/crates/rusticol-capi/include/rusticol.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,20 @@ int rusticol_runtime_evaluate_correlated_many_f64(
double *output, size_t output_capacity
);

/* Explicit native higher-precision current/amplitude mode. The companion
* is trusted executable input prepared for this exact artifact; no Symbolica
* or Python is loaded at numerical runtime. Sources/model inputs and returned
* buffers retain binary64 layout. No automatic fallback or component clamping.
*/
int rusticol_runtime_load_correlated_rescue(RusticolRuntimeHandle *handle, const char *path);
int rusticol_runtime_evaluate_correlated_many_rescued_f64(
RusticolRuntimeHandle *handle,
const double *momenta, size_t momentum_count, size_t point_count,
const RusticolCorrelatedRequest *requests, size_t request_count,
const char *const *helicity_ids, size_t helicity_count,
double *output, size_t output_capacity
);

/* Ordinary momenta use [point][external particle][E, px, py, pz]. */
int rusticol_runtime_evaluate_f64(
RusticolRuntimeHandle *handle,
Expand Down
103 changes: 97 additions & 6 deletions rust/crates/rusticol-capi/src/correlated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,88 @@ pub unsafe extern "C" fn rusticol_runtime_evaluate_correlated_many_f64(
helicity_count: size_t,
output: *mut c_double,
output_capacity: size_t,
) -> c_int {
unsafe {
evaluate(
handle,
momenta,
momentum_count,
point_count,
requests,
request_count,
helicity_ids,
helicity_count,
output,
output_capacity,
false,
)
}
}

/// Attach a trusted native companion library to this exact process artifact.
///
/// # Safety
/// handle must be live/exclusive; path must name trusted executable code implementing the rescue ABI.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rusticol_runtime_load_correlated_rescue(
handle: *mut RusticolRuntimeHandle,
path: *const c_char,
) -> c_int {
guard(|| {
let handle = unsafe { required_handle_mut(handle) }?;
let path = unsafe { required_c_string(path, "rescue library path") }?;
unsafe { handle.runtime.load_correlated_rescue(Path::new(path)) }?;
Ok(())
})
}

/// Evaluate using a previously attached binary128 current/amplitude kernel.
///
/// # Safety
/// Pointer/storage requirements are identical to the binary64 correlated entry point.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rusticol_runtime_evaluate_correlated_many_rescued_f64(
handle: *mut RusticolRuntimeHandle,
momenta: *const c_double,
momentum_count: size_t,
point_count: size_t,
requests: *const RusticolCorrelatedRequest,
request_count: size_t,
helicity_ids: *const *const c_char,
helicity_count: size_t,
output: *mut c_double,
output_capacity: size_t,
) -> c_int {
unsafe {
evaluate(
handle,
momenta,
momentum_count,
point_count,
requests,
request_count,
helicity_ids,
helicity_count,
output,
output_capacity,
true,
)
}
}

#[allow(clippy::too_many_arguments)]
unsafe fn evaluate(
handle: *mut RusticolRuntimeHandle,
momenta: *const c_double,
momentum_count: size_t,
point_count: size_t,
requests: *const RusticolCorrelatedRequest,
request_count: size_t,
helicity_ids: *const *const c_char,
helicity_count: size_t,
output: *mut c_double,
output_capacity: size_t,
rescue: bool,
) -> c_int {
guard(|| {
let required = request_count
Expand All @@ -193,12 +275,21 @@ pub unsafe extern "C" fn rusticol_runtime_evaluate_correlated_many_f64(
let requests = unsafe { read_requests(requests, request_count) }?;
let helicities =
unsafe { read_selector_ids(helicity_ids, helicity_count, "helicity IDs") }?;
let values = handle.runtime.evaluate_correlated_many_f64(
momenta,
point_count,
&requests,
helicities.as_deref(),
)?;
let values = if rescue {
handle.runtime.evaluate_correlated_many_rescued_f64(
momenta,
point_count,
&requests,
helicities.as_deref(),
)?
} else {
handle.runtime.evaluate_correlated_many_f64(
momenta,
point_count,
&requests,
helicities.as_deref(),
)?
};
if values.point_count != point_count
|| values.request_count != request_count
|| values.values.len().checked_mul(2) != Some(required)
Expand Down
Loading