qualia_core_db/domains/financial/economics/
input_output.rs1pub const MAX_SECTORS: usize = 32;
5
6pub fn propagate_supply_shock(
9 coupling: &[f64],
10 shock: &[f64],
11 n: usize,
12 max_rounds: u32,
13 tolerance: f64,
14 impact_out: &mut [f64],
15) -> usize {
16 if n == 0
17 || n > MAX_SECTORS
18 || coupling.len() < n * n
19 || shock.len() < n
20 || impact_out.len() < n
21 {
22 return 0;
23 }
24 let mut term = [0.0f64; MAX_SECTORS];
25 let mut next = [0.0f64; MAX_SECTORS];
26 for i in 0..n {
27 term[i] = shock[i];
28 impact_out[i] = shock[i];
29 }
30 let mut rounds = 0usize;
31 for _ in 0..max_rounds {
32 rounds += 1;
33 let mut l1 = 0.0f64;
34 for i in 0..n {
35 let mut acc = 0.0;
36 for j in 0..n {
37 acc += coupling[i * n + j] * term[j];
38 }
39 next[i] = acc;
40 l1 += acc.abs();
41 }
42 for i in 0..n {
43 impact_out[i] += next[i];
44 term[i] = next[i];
45 }
46 if l1 < tolerance {
47 break;
48 }
49 }
50 rounds
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn supply_shock_propagates_to_dependent_sectors() {
59 let a = [0.0, 0.5, 0.5, 0.0];
60 let shock = [1.0, 0.0];
61 let mut impact = [0.0f64; 2];
62 let rounds = propagate_supply_shock(&a, &shock, 2, 100, 1e-9, &mut impact);
63 assert!(rounds > 1);
64 assert!((impact[0] - 4.0 / 3.0).abs() < 1e-6);
65 assert!(impact[1] > 0.6 && impact[1] < 0.7);
66 }
67
68 #[test]
69 fn supply_shock_rejects_bad_dimensions() {
70 let mut out = [0.0f64; 2];
71 assert_eq!(
72 propagate_supply_shock(&[0.0], &[1.0], 0, 10, 1e-9, &mut out),
73 0
74 );
75 assert_eq!(
76 propagate_supply_shock(&[0.0; 4], &[1.0, 0.0], 3, 10, 1e-9, &mut out),
77 0
78 );
79 }
80}