1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! Pure-Rust [relaxed vector fitting](https://en.wikipedia.org/wiki/Vector_fitting)
//! for rational approximation of frequency-domain data.
//! Fits scalar, vector, and matrix-valued responses.
//!
//! # API overview
//!
//! - [`Model`] — fitted rational approximation (poles, residues, evaluation)
//! - [`Options`] — solver configuration (pole count, convergence, weighting)
//! - [`Csv`] and [`Touchstone`] — parse sampled data from common file formats
//! - [`hz`], [`rad`], [`real`], [`complex`] — axis wrappers for unit conversion
//! - [`Shape`] and [`Layout`] — describe the structure of flattened response data
//!
//! # Examples
//!
//! Fit sampled data from CSV:
//!
//! ```rust
//! use vecfit::{Csv, Options};
//!
//! let csv = "freq_Hz,re_f1,im_f1\n1,0.95,-0.31\n5,0.35,-0.72\n10,0.10,-0.98\n50,0.02,-1.0\n100,0.01,-1.0\n";
//! let model = Csv::from_csv(csv)?.fit(Options::new().poles(2))?;
//!
//! assert!(model.shape().is_scalar());
//! # Ok::<(), vecfit::VecfitError>(())
//! ```
//!
//! Fit an analytic transfer function via closure:
//!
//! ```rust
//! use num_complex::Complex64;
//! use vecfit::{Options, Model, complex};
//!
//! let s: Vec<Complex64> = (0..80)
//! .map(|k| Complex64::new(0.0, 1.0 + k as f64))
//! .collect();
//!
//! let model = Model::fit(
//! complex(&s),
//! |s| 0.05 + 1.2 / (s + 3.0) + 0.4 / (s + 15.0),
//! Options::new().poles(4),
//! )?;
//!
//! let fitted = model.eval_scalar(&s)?;
//! assert_eq!(fitted.len(), s.len());
//! # Ok::<(), vecfit::VecfitError>(())
//! ```
//!
//! Multi-channel vector fit using the `hz` axis wrapper:
//!
//! ```rust
//! use vecfit::{Options, Model, hz};
//!
//! let freq: Vec<f64> = (1..60).map(|k| k as f64).collect();
//! let model = Model::fit(
//! hz(&freq),
//! |f| {
//! let w = 2.0 * std::f64::consts::PI * f;
//! [1.0 / (1.0 + w), 0.6 / (3.0 + w), 0.3 / (9.0 + w)]
//! },
//! Options::new().poles(4),
//! )?;
//!
//! assert_eq!(model.channels(), 3);
//! # Ok::<(), vecfit::VecfitError>(())
//! ```
//!
//! JSON round-trip:
//!
//! ```rust
//! use num_complex::Complex64;
//! use vecfit::{Options, Model, complex};
//!
//! let s: Vec<Complex64> = (0..48)
//! .map(|k| Complex64::new(0.0, 2.0 + k as f64))
//! .collect();
//! let model = Model::fit(
//! complex(&s),
//! |s| vec![1.0 / (s + 2.0), 0.5 / (s + 8.0)],
//! Options::new().poles(3),
//! )?;
//!
//! let json = model.to_json()?;
//! let loaded = Model::from_json(&json)?;
//! assert_eq!(loaded.channels(), model.channels());
//! # Ok::<(), vecfit::VecfitError>(())
//! ```
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;
pub use crate;