use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
BlackScholesPricer, CompoundPoissonProcess, CtMarkovChain, EulerMaruyama,
GeometricBrownianMotionProcess, Lcg, OrnsteinUhlenbeckProcess, PoissonProcessSimulator,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn app2(f: Expr, a: Expr, b: Expr) -> Expr {
app(app(f, a), b)
}
pub fn app3(f: Expr, a: Expr, b: Expr, c: Expr) -> Expr {
app(app2(f, a, b), c)
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn bvar(n: u32) -> Expr {
Expr::BVar(n)
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn list_ty(elem: Expr) -> Expr {
app(cst("List"), elem)
}
pub fn stochastic_process_ty() -> Expr {
arrow(cst("FilteredProbabilitySpace"), real_ty())
}
pub fn martingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn brownian_motion_ty() -> Expr {
stochastic_process_ty()
}
pub fn ito_integral_ty() -> Expr {
arrow(
arrow(stochastic_process_ty(), arrow(real_ty(), real_ty())),
stochastic_process_ty(),
)
}
pub fn sde_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), real_ty()),
arrow(stochastic_process_ty(), prop()),
),
)
}
pub fn optional_stopping_ty() -> Expr {
pi(
BinderInfo::Default,
"X",
stochastic_process_ty(),
arrow(nat_ty(), arrow(app(cst("Martingale"), bvar(1)), prop())),
)
}
pub fn doob_maximal_ty() -> Expr {
pi(
BinderInfo::Default,
"X",
stochastic_process_ty(),
pi(
BinderInfo::Default,
"n",
nat_ty(),
arrow(real_ty(), arrow(app(cst("Martingale"), bvar(2)), prop())),
),
)
}
pub fn ito_lemma_ty() -> Expr {
pi(
BinderInfo::Default,
"X",
stochastic_process_ty(),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn girsanov_theorem_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(brownian_motion_ty(), prop()),
)
}
pub fn reflection_principle_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), arrow(prop(), prop())))
}
pub fn brownian_motion_existence_ty() -> Expr {
cst("BrownianMotionProcess")
}
pub fn brownian_motion_is_martingale_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn brownian_motion_continuous_paths_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn brownian_motion_quadratic_variation_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), arrow(real_ty(), prop()))
}
pub fn brownian_motion_zero_at_origin_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn ito_isometry_ty() -> Expr {
arrow(cst("AdaptedProcess"), arrow(real_ty(), prop()))
}
pub fn ito_formula_multidim_ty() -> Expr {
arrow(
nat_ty(),
arrow(
stochastic_process_ty(),
arrow(arrow(real_ty(), real_ty()), prop()),
),
)
}
pub fn stratonovich_integral_ty() -> Expr {
arrow(cst("AdaptedProcess"), stochastic_process_ty())
}
pub fn ito_stratonovich_relation_ty() -> Expr {
arrow(cst("AdaptedProcess"), prop())
}
pub fn sde_strong_solution_existence_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), prop())),
)
}
pub fn sde_strong_solution_uniqueness_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn sde_weak_solution_existence_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn martingale_representation_ty() -> Expr {
arrow(
arrow(stochastic_process_ty(), prop()),
arrow(cst("AdaptedProcess"), prop()),
)
}
pub fn doob_meyer_decomposition_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn local_martingale_to_martingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn feynman_kac_formula_ty() -> Expr {
arrow(
arrow(real_ty(), arrow(real_ty(), real_ty())),
arrow(stochastic_process_ty(), prop()),
)
}
pub fn black_scholes_pde_ty() -> Expr {
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop())
}
pub fn risk_neutral_pricing_ty() -> Expr {
arrow(stochastic_process_ty(), arrow(real_ty(), prop()))
}
pub fn levy_process_ty() -> Expr {
stochastic_process_ty()
}
pub fn levy_khintchine_formula_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn levy_ito_decomposition_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn levy_process_is_semimartingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn poisson_process_ty() -> Expr {
arrow(real_ty(), stochastic_process_ty())
}
pub fn poisson_process_mean_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), prop()))
}
pub fn poisson_superposition_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), prop()))
}
pub fn compound_poisson_process_ty() -> Expr {
arrow(
real_ty(),
arrow(arrow(real_ty(), real_ty()), stochastic_process_ty()),
)
}
pub fn compound_poisson_mean_ty() -> Expr {
arrow(
real_ty(),
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), prop())),
)
}
pub fn jump_sde_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), arrow(real_ty(), real_ty())),
arrow(stochastic_process_ty(), prop()),
),
),
)
}
pub fn jump_sde_existence_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn markov_property_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn strong_markov_property_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn markov_semigroup_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop()),
)
}
pub fn brownian_motion_harmonic_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), prop())
}
pub fn potential_theory_green_function_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn brownian_motion_recurrence_ty() -> Expr {
arrow(nat_ty(), prop())
}
pub fn stopping_time_ty() -> Expr {
arrow(stochastic_process_ty(), nat_ty())
}
pub fn optional_sampling_theorem_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(nat_ty(), arrow(nat_ty(), prop())),
)
}
pub fn wald_identity_ty() -> Expr {
arrow(stochastic_process_ty(), arrow(nat_ty(), prop()))
}
pub fn semimartingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn semimartingale_integration_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(stochastic_process_ty(), stochastic_process_ty()),
)
}
pub fn quadratic_covariation_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(stochastic_process_ty(), stochastic_process_ty()),
)
}
pub fn invariant_measure_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
),
)
}
pub fn ergodic_theorem_sde_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn fokker_planck_equation_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
)
}
pub fn build_stochastic_processes_env(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("FilteredProbabilitySpace", type0()),
("BrownianMotionProcess", type0()),
("AdaptedProcess", type0()),
("LevyMeasure", type0()),
("StochasticProcess", stochastic_process_ty()),
("Martingale", martingale_ty()),
("BrownianMotion", brownian_motion_ty()),
("ItoIntegral", ito_integral_ty()),
("SDE", sde_ty()),
("GBM", stochastic_process_ty()),
("OUProcess", stochastic_process_ty()),
("StoppingTime", arrow(stochastic_process_ty(), nat_ty())),
("optional_stopping", optional_stopping_ty()),
("doob_maximal", doob_maximal_ty()),
("ito_lemma", ito_lemma_ty()),
("girsanov_theorem", girsanov_theorem_ty()),
("reflection_principle", reflection_principle_ty()),
("brownian_motion_existence", brownian_motion_existence_ty()),
(
"brownian_motion_is_martingale",
brownian_motion_is_martingale_ty(),
),
(
"brownian_motion_continuous_paths",
brownian_motion_continuous_paths_ty(),
),
(
"brownian_motion_quadratic_variation",
brownian_motion_quadratic_variation_ty(),
),
(
"brownian_motion_zero_at_origin",
brownian_motion_zero_at_origin_ty(),
),
("ito_isometry", ito_isometry_ty()),
("ito_formula_multidim", ito_formula_multidim_ty()),
("stratonovich_integral", stratonovich_integral_ty()),
("ito_stratonovich_relation", ito_stratonovich_relation_ty()),
(
"sde_strong_solution_existence",
sde_strong_solution_existence_ty(),
),
(
"sde_strong_solution_uniqueness",
sde_strong_solution_uniqueness_ty(),
),
(
"sde_weak_solution_existence",
sde_weak_solution_existence_ty(),
),
(
"martingale_representation_theorem",
martingale_representation_ty(),
),
("doob_meyer_decomposition", doob_meyer_decomposition_ty()),
(
"local_martingale_to_martingale",
local_martingale_to_martingale_ty(),
),
("feynman_kac_formula", feynman_kac_formula_ty()),
("black_scholes_pde", black_scholes_pde_ty()),
("risk_neutral_pricing", risk_neutral_pricing_ty()),
("LevyProcess", levy_process_ty()),
("levy_khintchine_formula", levy_khintchine_formula_ty()),
("levy_ito_decomposition", levy_ito_decomposition_ty()),
(
"levy_process_is_semimartingale",
levy_process_is_semimartingale_ty(),
),
("PoissonProcess", poisson_process_ty()),
("poisson_process_mean", poisson_process_mean_ty()),
("poisson_superposition", poisson_superposition_ty()),
("compound_poisson_process", compound_poisson_process_ty()),
("compound_poisson_mean", compound_poisson_mean_ty()),
("jump_sde", jump_sde_ty()),
("jump_sde_existence", jump_sde_existence_ty()),
("markov_property", markov_property_ty()),
("strong_markov_property", strong_markov_property_ty()),
("markov_semigroup", markov_semigroup_ty()),
("brownian_motion_harmonic", brownian_motion_harmonic_ty()),
(
"potential_theory_green_function",
potential_theory_green_function_ty(),
),
(
"brownian_motion_recurrence",
brownian_motion_recurrence_ty(),
),
("stopping_time_measurable", stopping_time_ty()),
("optional_sampling_theorem", optional_sampling_theorem_ty()),
("wald_identity", wald_identity_ty()),
("Semimartingale", semimartingale_ty()),
(
"semimartingale_integration",
semimartingale_integration_ty(),
),
("quadratic_covariation", quadratic_covariation_ty()),
("invariant_measure", invariant_measure_ty()),
("ergodic_theorem_sde", ergodic_theorem_sde_ty()),
("fokker_planck_equation", fokker_planck_equation_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
pub fn random_walk(n_steps: u32, seed: u64) -> Vec<f64> {
let mut lcg = Lcg::new(seed);
let mut path = Vec::with_capacity(n_steps as usize + 1);
let mut x = 0.0f64;
path.push(x);
for _ in 0..n_steps {
x += lcg.next_step();
path.push(x);
}
path
}
pub fn brownian_motion(t_end: f64, n_steps: u32, seed: u64) -> Vec<(f64, f64)> {
let mut lcg = Lcg::new(seed);
let dt = t_end / n_steps as f64;
let scale = dt.sqrt();
let mut path = Vec::with_capacity(n_steps as usize + 1);
let mut t = 0.0f64;
let mut x = 0.0f64;
path.push((t, x));
for _ in 0..n_steps {
x += lcg.next_normal() * scale;
t += dt;
path.push((t, x));
}
path
}
pub fn geometric_brownian_motion(
s0: f64,
mu: f64,
sigma: f64,
t_end: f64,
n_steps: u32,
seed: u64,
) -> Vec<(f64, f64)> {
let mut lcg = Lcg::new(seed);
let dt = t_end / n_steps as f64;
let drift = (mu - 0.5 * sigma * sigma) * dt;
let vol = sigma * dt.sqrt();
let mut path = Vec::with_capacity(n_steps as usize + 1);
let mut t = 0.0f64;
let mut s = s0;
path.push((t, s));
for _ in 0..n_steps {
s *= (drift + vol * lcg.next_normal()).exp();
t += dt;
path.push((t, s));
}
path
}
pub fn ornstein_uhlenbeck(
x0: f64,
theta: f64,
mu: f64,
sigma: f64,
t_end: f64,
n_steps: u32,
seed: u64,
) -> Vec<(f64, f64)> {
let mut lcg = Lcg::new(seed);
let dt = t_end / n_steps as f64;
let vol = sigma * dt.sqrt();
let mut path = Vec::with_capacity(n_steps as usize + 1);
let mut t = 0.0f64;
let mut x = x0;
path.push((t, x));
for _ in 0..n_steps {
x += theta * (mu - x) * dt + vol * lcg.next_normal();
t += dt;
path.push((t, x));
}
path
}
pub fn standard_normal_cdf(x: f64) -> f64 {
if x > 8.0 {
return 1.0;
}
if x < -8.0 {
return 0.0;
}
let t = 1.0 / (1.0 + 0.2316419 * x.abs());
let poly = t
* (0.319381530
+ t * (-0.356563782 + t * (1.781477937 + t * (-1.821255978 + t * 1.330274429))));
let phi = (-0.5 * x * x).exp() / (2.0 * std::f64::consts::PI).sqrt();
let cdf = 1.0 - phi * poly;
if x >= 0.0 {
cdf
} else {
1.0 - cdf
}
}
pub fn black_scholes_call(s: f64, k: f64, t: f64, r: f64, sigma: f64) -> f64 {
if t <= 0.0 {
return (s - k).max(0.0);
}
let sqrt_t = t.sqrt();
let d1 = ((s / k).ln() + (r + 0.5 * sigma * sigma) * t) / (sigma * sqrt_t);
let d2 = d1 - sigma * sqrt_t;
s * standard_normal_cdf(d1) - k * (-r * t).exp() * standard_normal_cdf(d2)
}
pub fn black_scholes_put(s: f64, k: f64, t: f64, r: f64, sigma: f64) -> f64 {
black_scholes_call(s, k, t, r, sigma) - s + k * (-r * t).exp()
}
pub fn monte_carlo_call(
s0: f64,
k: f64,
t: f64,
r: f64,
sigma: f64,
n_paths: u32,
seed: u64,
) -> f64 {
if n_paths == 0 {
return 0.0;
}
let mut lcg = Lcg::new(seed);
let drift = (r - 0.5 * sigma * sigma) * t;
let vol = sigma * t.sqrt();
let discount = (-r * t).exp();
let mut total = 0.0f64;
for _ in 0..n_paths {
let z = lcg.next_normal();
let s_t = s0 * (drift + vol * z).exp();
total += (s_t - k).max(0.0);
}
discount * total / n_paths as f64
}
pub fn martingale_l1_convergence_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn martingale_l2_convergence_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn martingale_as_convergence_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn reverse_martingale_convergence_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn uniformly_integrable_martingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn optional_stopping_ui_ty() -> Expr {
arrow(stochastic_process_ty(), arrow(nat_ty(), prop()))
}
pub fn doob_maximal_l2_ty() -> Expr {
arrow(stochastic_process_ty(), arrow(nat_ty(), prop()))
}
pub fn doob_upcrossing_inequality_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(real_ty(), arrow(real_ty(), prop())),
)
}
pub fn predictable_process_ty() -> Expr {
type0()
}
pub fn predictable_sigma_algebra_ty() -> Expr {
type0()
}
pub fn optional_sigma_algebra_ty() -> Expr {
type0()
}
pub fn predictable_compensator_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(cst("PredictableProcess"), prop()),
)
}
pub fn natural_filtration_ty() -> Expr {
arrow(stochastic_process_ty(), type0())
}
pub fn brownian_filtration_complete_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn brownian_increment_independence_ty() -> Expr {
arrow(
cst("BrownianMotionProcess"),
arrow(real_ty(), arrow(real_ty(), prop())),
)
}
pub fn brownian_scaling_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), arrow(real_ty(), prop()))
}
pub fn brownian_time_inversion_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn brownian_lil_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), prop())
}
pub fn ito_isometry_general_ty() -> Expr {
arrow(cst("AdaptedProcess"), arrow(real_ty(), prop()))
}
pub fn stochastic_exponential_ty() -> Expr {
arrow(stochastic_process_ty(), stochastic_process_ty())
}
pub fn stochastic_exponential_martingale_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn novikov_condition_ty() -> Expr {
arrow(cst("AdaptedProcess"), prop())
}
pub fn cameron_martin_theorem_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(cst("BrownianMotionProcess"), prop()),
)
}
pub fn girsanov_multidim_ty() -> Expr {
arrow(nat_ty(), arrow(cst("AdaptedProcess"), prop()))
}
pub fn equivalent_martingale_measure_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn first_ftam_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn malliavin_derivative_ty() -> Expr {
type0()
}
pub fn skorokhod_integral_ty() -> Expr {
type0()
}
pub fn malliavin_integration_by_parts_ty() -> Expr {
arrow(
cst("MalliavinDerivative"),
arrow(cst("SkorokhodIntegral"), prop()),
)
}
pub fn clark_ocone_formula_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(cst("MalliavinDerivative"), prop()),
)
}
pub fn malliavin_smooth_functional_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn rough_path_ty() -> Expr {
type0()
}
pub fn controlled_rough_path_ty() -> Expr {
type0()
}
pub fn rough_path_integral_ty() -> Expr {
arrow(
cst("ControlledRoughPath"),
arrow(cst("RoughPath"), arrow(stochastic_process_ty(), prop())),
)
}
pub fn rough_path_continuity_ty() -> Expr {
arrow(cst("RoughPath"), arrow(real_ty(), prop()))
}
pub fn brownian_rough_path_ty() -> Expr {
arrow(
cst("BrownianMotionProcess"),
arrow(cst("RoughPath"), prop()),
)
}
pub fn rough_path_rde_solution_ty() -> Expr {
arrow(cst("RoughPath"), arrow(stochastic_process_ty(), prop()))
}
pub fn feller_semigroup_ty() -> Expr {
type0()
}
pub fn feller_process_existence_ty() -> Expr {
arrow(
cst("FellerSemigroup"),
arrow(stochastic_process_ty(), prop()),
)
}
pub fn kolmogorov_forward_equation_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop()),
),
)
}
pub fn kolmogorov_backward_equation_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), prop()),
),
)
}
pub fn generator_feller_ty() -> Expr {
arrow(
cst("FellerSemigroup"),
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop()),
)
}
pub fn reflected_brownian_motion_ty() -> Expr {
type0()
}
pub fn reflected_bm_existence_ty() -> Expr {
arrow(real_ty(), arrow(cst("ReflectedBrownianMotion"), prop()))
}
pub fn skorokhod_reflection_problem_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(cst("ReflectedBrownianMotion"), prop()),
)
}
pub fn tanaka_formula_ty() -> Expr {
arrow(cst("BrownianMotionProcess"), arrow(real_ty(), prop()))
}
pub fn local_time_ty() -> Expr {
arrow(
cst("BrownianMotionProcess"),
arrow(real_ty(), arrow(real_ty(), prop())),
)
}
pub fn infinitely_divisible_distribution_ty() -> Expr {
type0()
}
pub fn levy_process_infinitely_divisible_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(cst("InfinitelyDivisibleDistribution"), prop()),
)
}
pub fn poisson_random_measure_ty() -> Expr {
type0()
}
pub fn poisson_random_measure_levy_ty() -> Expr {
arrow(
levy_process_ty(),
arrow(cst("PoissonRandomMeasure"), prop()),
)
}
pub fn stable_process_ty() -> Expr {
arrow(real_ty(), stochastic_process_ty())
}
pub fn subordinator_ty() -> Expr {
arrow(stochastic_process_ty(), prop())
}
pub fn subordination_ty() -> Expr {
arrow(
stochastic_process_ty(),
arrow(stochastic_process_ty(), stochastic_process_ty()),
)
}
pub(super) fn sp_ext_gamma_sample(a: f64, b: f64, lcg: &mut super::types::Lcg) -> f64 {
if a <= 0.0 || b <= 0.0 {
return 0.0;
}
let n = (a.ceil() as u32).max(1);
let mut sum = 0.0f64;
for _ in 0..n {
let u = lcg.next_f64().max(1e-15);
sum += (-u.ln()) / b;
}
sum * (a / n as f64)
}