1use num::complex::Complex64;
2use std::collections::HashMap;
3
4use crate::ascii::ast::{PsfAst, Trace, Values};
5use crate::bin_search_before;
6
7pub struct AcData {
8 pub signals: HashMap<String, Vec<Complex64>>,
9 pub freq: Vec<f64>,
10}
11
12impl AcData {
13 pub fn from_ascii(ast: &PsfAst) -> Self {
14 let mut groups = HashMap::<&str, &str>::new();
17 let mut i = 0;
18 while i < ast.traces.len() {
19 match ast.traces[i] {
20 Trace::Group { name: group, count } => {
21 debug_assert!(count >= 0);
22 let count = count as usize;
23 for j in 1..=count {
24 if let Trace::Signal { name, .. } = ast.traces[i + j] {
25 groups.insert(group, name);
26 } else {
27 panic!("Expected signal; found group");
28 }
29 }
30 i += count + 1;
31 }
32 Trace::Signal { name, .. } => {
33 groups.insert(name, name);
34 i += 1;
35 }
36 }
37 }
38
39 let mut signals = HashMap::<String, Vec<Complex64>>::new();
40 let mut freq = Vec::<f64>::new();
41 for v in ast.values.iter() {
42 if v.signal == "freq" {
43 if let Values::Real(values) = &v.values {
44 debug_assert_eq!(values.len(), 1);
45 freq.push(values[0]);
46 } else {
47 panic!("Expected real signal values; found complex");
48 }
49 } else if let Values::Complex(values) = &v.values {
50 debug_assert_eq!(values.len(), 1);
51 if let Some(lst) = signals.get_mut(groups[v.signal]) {
52 lst.push(values[0]);
53 } else {
54 signals.insert(groups[v.signal].to_string(), vec![values[0]]);
55 }
56 } else {
57 panic!("Expected complex signal values; found real");
58 }
59 }
60
61 Self { signals, freq }
62 }
63
64 pub fn from_binary(mut ast: crate::binary::ast::PsfAst) -> Self {
65 let mut signals = HashMap::<String, Vec<Complex64>>::new();
66 for group in ast.traces.iter() {
67 for sig in group.signals() {
68 let v = ast
69 .values
70 .values
71 .remove(&sig.id)
72 .expect("missing values for trace");
73 signals.insert(sig.name.to_string(), v.unwrap_complex());
74 }
75 }
76
77 assert_eq!(
78 ast.sweeps[0].name, "freq",
79 "ac analysis expects to sweep frequency"
80 );
81 let freq = ast
82 .values
83 .values
84 .remove(&ast.sweeps[0].id)
85 .unwrap()
86 .unwrap_real();
87
88 Self { signals, freq }
89 }
90
91 pub fn idx_before_freq(&self, f: f64) -> Option<usize> {
94 bin_search_before(&self.freq, f)
95 }
96
97 #[inline]
98 pub fn signal(&self, name: &str) -> Option<&Vec<Complex64>> {
99 self.signals.get(name)
100 }
101}