1use std::cell::Cell;
13use std::cell::RefCell;
14use std::os::raw::c_void;
15
16use crate::c_api::IntermediateCb;
17
18thread_local! {
19 static INTERMEDIATE_CALLBACK: Cell<Option<(IntermediateCb, *mut c_void)>> = Cell::new(None);
20 static CURRENT_ITERATE: RefCell<Option<IterateSnapshot>> = RefCell::new(None);
21}
22
23pub struct IterateSnapshot {
26 pub x: Vec<f64>,
27 pub z_l: Vec<f64>,
28 pub z_u: Vec<f64>,
29 pub g: Vec<f64>,
30 pub lambda: Vec<f64>,
31 pub x_l_violation: Vec<f64>,
33 pub x_u_violation: Vec<f64>,
34 pub compl_x_l: Vec<f64>,
35 pub compl_x_u: Vec<f64>,
36 pub grad_lag_x: Vec<f64>,
37 pub constraint_violation: Vec<f64>,
38 pub compl_g: Vec<f64>,
39}
40
41pub fn set_intermediate_callback(cb: Option<(IntermediateCb, *mut c_void)>) {
44 INTERMEDIATE_CALLBACK.with(|cell| cell.set(cb));
45}
46
47pub fn set_current_iterate(snapshot: Option<IterateSnapshot>) {
49 CURRENT_ITERATE.with(|cell| {
50 *cell.borrow_mut() = snapshot;
51 });
52}
53
54pub fn with_current_iterate<F, R>(f: F) -> Option<R>
56where
57 F: FnOnce(&IterateSnapshot) -> R,
58{
59 CURRENT_ITERATE.with(|cell| {
60 cell.borrow().as_ref().map(f)
61 })
62}
63
64pub fn invoke_intermediate(
68 alg_mod: i32,
69 iter: usize,
70 obj_value: f64,
71 inf_pr: f64,
72 inf_du: f64,
73 mu: f64,
74 d_norm: f64,
75 regularization_size: f64,
76 alpha_du: f64,
77 alpha_pr: f64,
78 ls_trials: usize,
79) -> bool {
80 INTERMEDIATE_CALLBACK.with(|cell| {
81 if let Some((cb, user_data)) = cell.get() {
82 let result = unsafe {
83 cb(
84 alg_mod,
85 iter as i32,
86 obj_value,
87 inf_pr,
88 inf_du,
89 mu,
90 d_norm,
91 regularization_size,
92 alpha_du,
93 alpha_pr,
94 ls_trials as i32,
95 user_data,
96 )
97 };
98 result != 0
99 } else {
100 true }
102 })
103}