Skip to main content

qualia_core_db/solvers/calculus/
capabilities.rs

1//! Machine-readable capability truth for the native calculus surface.
2//!
3//! Descriptors are static POD-like metadata: discovery allocates nothing and
4//! never infers mathematical guarantees from a function name.
5
6use crate::q_hash;
7
8#[repr(u8)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum ScalarType {
11    F32 = 1,
12    F64 = 2,
13    Complex64 = 3,
14}
15
16#[repr(u8)]
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub enum AccuracyModel {
19    ExactAlgebraic = 1,
20    FixedOrder = 2,
21    EmbeddedEstimate = 3,
22    ResidualControlled = 4,
23    DiagnosticOnly = 5,
24}
25
26#[repr(u8)]
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum StepControl {
29    NotApplicable = 0,
30    Fixed = 1,
31    Adaptive = 2,
32}
33
34#[repr(u8)]
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
36pub enum AllocationClass {
37    ZeroHeap = 0,
38    CallerWorkspace = 1,
39    ColdHeap = 2,
40}
41
42#[repr(u8)]
43#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
44pub enum Maturity {
45    Foundation = 0,
46    Verified = 1,
47    Certified = 2,
48}
49
50#[repr(transparent)]
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub struct BackendSet(pub u8);
53
54impl BackendSet {
55    pub const SCALAR_CPU: u8 = 1 << 0;
56    pub const SIMD_CPU: u8 = 1 << 1;
57    pub const GPU: u8 = 1 << 2;
58    pub const WASM: u8 = 1 << 3;
59
60    pub const fn new(bits: u8) -> Self {
61        Self(bits)
62    }
63
64    pub const fn contains(self, backend: u8) -> bool {
65        self.0 & backend == backend
66    }
67}
68
69#[repr(C)]
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct CalculusCapability {
72    pub operation_id: u64,
73    pub name: &'static str,
74    pub minimum_dimension: u16,
75    /// Zero denotes runtime/caller-bounded dimension.
76    pub maximum_dimension: u16,
77    pub scalar: ScalarType,
78    pub accuracy: AccuracyModel,
79    pub formal_order: u8,
80    pub step_control: StepControl,
81    pub allocation: AllocationClass,
82    pub backends: BackendSet,
83    pub maturity: Maturity,
84}
85
86const CPU: BackendSet = BackendSet::new(BackendSet::SCALAR_CPU | BackendSet::WASM);
87const SIMD_CPU: BackendSet =
88    BackendSet::new(BackendSet::SCALAR_CPU | BackendSet::SIMD_CPU | BackendSet::WASM);
89const PORTABLE_GPU: BackendSet =
90    BackendSet::new(BackendSet::SCALAR_CPU | BackendSet::GPU | BackendSet::WASM);
91
92pub const CALCULUS_CAPABILITIES: &[CalculusCapability] = &[
93    CalculusCapability {
94        operation_id: q_hash("q42:calculus:simpson-1-3"),
95        name: "composite Simpson 1/3 quadrature",
96        minimum_dimension: 1,
97        maximum_dimension: 1,
98        scalar: ScalarType::F64,
99        accuracy: AccuracyModel::FixedOrder,
100        formal_order: 4,
101        step_control: StepControl::Fixed,
102        allocation: AllocationClass::ZeroHeap,
103        backends: SIMD_CPU,
104        maturity: Maturity::Verified,
105    },
106    CalculusCapability {
107        operation_id: q_hash("q42:calculus:trapezoid"),
108        name: "composite trapezoidal quadrature",
109        minimum_dimension: 1,
110        maximum_dimension: 1,
111        scalar: ScalarType::F64,
112        accuracy: AccuracyModel::FixedOrder,
113        formal_order: 2,
114        step_control: StepControl::Fixed,
115        allocation: AllocationClass::ZeroHeap,
116        backends: CPU,
117        maturity: Maturity::Verified,
118    },
119    CalculusCapability {
120        operation_id: q_hash("q42:calculus:gpu-simpson-1-3-f32"),
121        name: "portable GPU Simpson 1/3 quadrature",
122        minimum_dimension: 1,
123        maximum_dimension: 1,
124        scalar: ScalarType::F32,
125        accuracy: AccuracyModel::FixedOrder,
126        formal_order: 4,
127        step_control: StepControl::Fixed,
128        allocation: AllocationClass::ColdHeap,
129        backends: PORTABLE_GPU,
130        maturity: Maturity::Foundation,
131    },
132    CalculusCapability {
133        operation_id: q_hash("q42:calculus:rk4-static"),
134        name: "fixed-state classical Runge-Kutta",
135        minimum_dimension: 4,
136        maximum_dimension: 4,
137        scalar: ScalarType::F64,
138        accuracy: AccuracyModel::FixedOrder,
139        formal_order: 4,
140        step_control: StepControl::Fixed,
141        allocation: AllocationClass::ZeroHeap,
142        backends: CPU,
143        maturity: Maturity::Verified,
144    },
145    CalculusCapability {
146        operation_id: q_hash("q42:calculus:rk4-dense"),
147        name: "dynamic classical Runge-Kutta",
148        minimum_dimension: 1,
149        maximum_dimension: 0,
150        scalar: ScalarType::F64,
151        accuracy: AccuracyModel::FixedOrder,
152        formal_order: 4,
153        step_control: StepControl::Fixed,
154        allocation: AllocationClass::ColdHeap,
155        backends: CPU,
156        maturity: Maturity::Verified,
157    },
158    CalculusCapability {
159        operation_id: q_hash("q42:calculus:shooting-newton-static"),
160        name: "fixed-state Newton shooting BVP",
161        minimum_dimension: 4,
162        maximum_dimension: 4,
163        scalar: ScalarType::F64,
164        accuracy: AccuracyModel::ResidualControlled,
165        formal_order: 4,
166        step_control: StepControl::Fixed,
167        allocation: AllocationClass::ZeroHeap,
168        backends: CPU,
169        maturity: Maturity::Verified,
170    },
171    CalculusCapability {
172        operation_id: q_hash("q42:calculus:bdf1"),
173        name: "scalar backward Euler",
174        minimum_dimension: 1,
175        maximum_dimension: 1,
176        scalar: ScalarType::F64,
177        accuracy: AccuracyModel::ResidualControlled,
178        formal_order: 1,
179        step_control: StepControl::Fixed,
180        allocation: AllocationClass::ZeroHeap,
181        backends: CPU,
182        maturity: Maturity::Foundation,
183    },
184    CalculusCapability {
185        operation_id: q_hash("q42:calculus:bdf2"),
186        name: "scalar BDF2",
187        minimum_dimension: 1,
188        maximum_dimension: 1,
189        scalar: ScalarType::F64,
190        accuracy: AccuracyModel::ResidualControlled,
191        formal_order: 2,
192        step_control: StepControl::Fixed,
193        allocation: AllocationClass::ZeroHeap,
194        backends: CPU,
195        maturity: Maturity::Foundation,
196    },
197    CalculusCapability {
198        operation_id: q_hash("q42:calculus:symplectic-separable"),
199        name: "scalar separable symplectic integration",
200        minimum_dimension: 2,
201        maximum_dimension: 2,
202        scalar: ScalarType::F64,
203        accuracy: AccuracyModel::FixedOrder,
204        formal_order: 4,
205        step_control: StepControl::Fixed,
206        allocation: AllocationClass::ColdHeap,
207        backends: CPU,
208        maturity: Maturity::Verified,
209    },
210    CalculusCapability {
211        operation_id: q_hash("q42:calculus:forward-sensitivity-scalar"),
212        name: "scalar forward sensitivity",
213        minimum_dimension: 1,
214        maximum_dimension: 1,
215        scalar: ScalarType::F64,
216        accuracy: AccuracyModel::FixedOrder,
217        formal_order: 4,
218        step_control: StepControl::Fixed,
219        allocation: AllocationClass::ColdHeap,
220        backends: CPU,
221        maturity: Maturity::Verified,
222    },
223    CalculusCapability {
224        operation_id: q_hash("q42:calculus:symbolic-multivariable"),
225        name: "symbolic gradient Jacobian and Hessian",
226        minimum_dimension: 1,
227        maximum_dimension: 0,
228        scalar: ScalarType::F64,
229        accuracy: AccuracyModel::ExactAlgebraic,
230        formal_order: 0,
231        step_control: StepControl::NotApplicable,
232        allocation: AllocationClass::ColdHeap,
233        backends: CPU,
234        maturity: Maturity::Verified,
235    },
236];
237
238pub fn capability(operation_id: u64) -> Option<&'static CalculusCapability> {
239    CALCULUS_CAPABILITIES
240        .iter()
241        .find(|entry| entry.operation_id == operation_id)
242}
243
244#[cfg(test)]
245mod tests {
246    use super::*;
247
248    #[test]
249    fn capability_ids_are_unique_and_backend_claims_are_nonempty() {
250        for (index, capability) in CALCULUS_CAPABILITIES.iter().enumerate() {
251            assert_ne!(capability.operation_id, 0);
252            assert_ne!(capability.backends.0, 0);
253            for other in &CALCULUS_CAPABILITIES[index + 1..] {
254                assert_ne!(capability.operation_id, other.operation_id);
255            }
256        }
257    }
258
259    #[test]
260    fn capability_lookup_is_allocation_free_static_discovery() {
261        let id = q_hash("q42:calculus:simpson-1-3");
262        let descriptor = capability(id).unwrap();
263        assert_eq!(descriptor.formal_order, 4);
264        assert_eq!(descriptor.maturity, Maturity::Verified);
265        assert!(descriptor.backends.contains(BackendSet::SIMD_CPU));
266    }
267}