Skip to main content

derivative_batch

Function derivative_batch 

Source
pub fn derivative_batch<F>(
    points: &[f64],
    settings: DiffSettings,
    backend: ComputeBackend,
    f: F,
) -> DerivativeBatch
where F: Fn(usize, f64) -> f64 + Sync,
Expand description

Differentiate N independent scalar functions at N points, on the chosen backend.

This is the batched, GPU-shaped form: lane i differentiates f(i, .) at points[i], and no arithmetic crosses lanes.

§Arguments

  • points — one abscissa per lane, in the caller’s own units.
  • settings — scheme and step-size policy, shared by every lane.
  • backend — requested execution backend. What actually runs is derivative_backend_for applied to it. None of the degradations changes the answer.
  • f — f(i, x) is lane i’s function evaluated at x. It must be a pure deterministic function of its arguments — see the module-level “Determinism” section. The Sync bound is present in both feature builds so enabling parallel never changes a public signature.

§Returns

A DerivativeBatch with one solution per point, in point order. An empty points slice returns an empty batch and calls f zero times.

§Cost

DiffScheme::evaluations_per_derivative calls to f per lane — 2 for the three second-order-or-lower schemes, 4 for DiffScheme::Central4th.

§Example

use outram_foam_basic_lib::compute::ComputeBackend;
use outram_foam_basic_lib::math::differentiate::{
    derivative_batch, DiffSettings,
};

// Lane i differentiates x^(i+1) at x = 2; the answer is (i+1) * 2^i.
let points = vec![2.0_f64; 4];
let batch = derivative_batch(
    &points,
    DiffSettings::central(),
    ComputeBackend::CpuMulti,
    |i, x: f64| x.powi(i as i32 + 1),
);

let d = batch.values().expect("all lanes finite");
for (i, got) in d.iter().enumerate() {
    let want = (i as f64 + 1.0) * 2.0_f64.powi(i as i32);
    assert!((got - want).abs() < 1e-6 * want.abs().max(1.0), "lane {i}: {got} vs {want}");
}