1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum ApiCategory {
10 LinearAlgebra,
12 Decomposition,
14 Statistics,
16 Distribution,
18 HypothesisTest,
20 SignalProcessing,
22 FFT,
24 Optimization,
26 Integration,
28 Interpolation,
30 SpecialFunction,
32 Sparse,
34 ImageProcessing,
36 MachineLearning,
38 TimeSeries,
40}
41
42impl core::fmt::Display for ApiCategory {
43 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
44 match self {
45 ApiCategory::LinearAlgebra => write!(f, "Linear Algebra"),
46 ApiCategory::Decomposition => write!(f, "Decomposition"),
47 ApiCategory::Statistics => write!(f, "Statistics"),
48 ApiCategory::Distribution => write!(f, "Distribution"),
49 ApiCategory::HypothesisTest => write!(f, "Hypothesis Test"),
50 ApiCategory::SignalProcessing => write!(f, "Signal Processing"),
51 ApiCategory::FFT => write!(f, "FFT"),
52 ApiCategory::Optimization => write!(f, "Optimization"),
53 ApiCategory::Integration => write!(f, "Integration"),
54 ApiCategory::Interpolation => write!(f, "Interpolation"),
55 ApiCategory::SpecialFunction => write!(f, "Special Function"),
56 ApiCategory::Sparse => write!(f, "Sparse"),
57 ApiCategory::ImageProcessing => write!(f, "Image Processing"),
58 ApiCategory::MachineLearning => write!(f, "Machine Learning"),
59 ApiCategory::TimeSeries => write!(f, "Time Series"),
60 #[allow(unreachable_patterns)]
62 _ => write!(f, "Other"),
63 }
64 }
65}
66
67#[derive(Debug, Clone)]
69pub struct ApiEntry {
70 pub crate_name: &'static str,
72 pub module_path: &'static str,
74 pub function_name: &'static str,
76 pub signature: &'static str,
78 pub description: &'static str,
80 pub math_reference: &'static str,
82 pub example: &'static str,
84 pub see_also: &'static [&'static str],
86 pub category: ApiCategory,
88}
89
90pub fn api_catalog() -> &'static [ApiEntry] {
92 &API_CATALOG
93}
94
95pub fn search_api(query: &str) -> Vec<&'static ApiEntry> {
98 let q = query.to_ascii_lowercase();
99 API_CATALOG
100 .iter()
101 .filter(|e| {
102 e.function_name.to_ascii_lowercase().contains(&q)
103 || e.description.to_ascii_lowercase().contains(&q)
104 || e.module_path.to_ascii_lowercase().contains(&q)
105 || e.crate_name.to_ascii_lowercase().contains(&q)
106 })
107 .collect()
108}
109
110pub fn by_crate(crate_name: &str) -> Vec<&'static ApiEntry> {
112 let cn = crate_name.to_ascii_lowercase();
113 API_CATALOG
114 .iter()
115 .filter(|e| e.crate_name.to_ascii_lowercase() == cn)
116 .collect()
117}
118
119pub fn by_category(cat: ApiCategory) -> Vec<&'static ApiEntry> {
121 API_CATALOG.iter().filter(|e| e.category == cat).collect()
122}
123
124static API_CATALOG: [ApiEntry; 60] = [
129 ApiEntry {
133 crate_name: "scirs2-linalg",
134 module_path: "basic",
135 function_name: "det",
136 signature: "pub fn det<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<F>",
137 description: "Compute the determinant of a square matrix via LU factorization.",
138 math_reference: "det(A) = product of diagonal entries of U after PA = LU factorization. \
139 For an n x n matrix, det(A) = (-1)^s * prod(U_ii) where s is the number of row swaps.",
140 example: r#"use scirs2_linalg::basic::det;
141use scirs2_core::ndarray::array;
142
143let a = array![[1.0, 2.0], [3.0, 4.0]];
144let d = det(&a.view(), None).expect("det failed");
145// d is approximately -2.0
146assert!((d - (-2.0)).abs() < 1e-10);"#,
147 see_also: &["inv", "lu", "solve"],
148 category: ApiCategory::LinearAlgebra,
149 },
150 ApiEntry {
151 crate_name: "scirs2-linalg",
152 module_path: "basic",
153 function_name: "inv",
154 signature: "pub fn inv<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<Array2<F>>",
155 description: "Compute the inverse of a square matrix using LU decomposition with partial pivoting.",
156 math_reference: "A^{-1} such that A * A^{-1} = I. \
157 Computed via PA = LU, then solving LU * X = P for each column of identity.",
158 example: r#"use scirs2_linalg::basic::inv;
159use scirs2_core::ndarray::array;
160
161let a = array![[1.0, 2.0], [3.0, 4.0]];
162let a_inv = inv(&a.view(), None).expect("inv failed");
163// a_inv is approximately [[-2.0, 1.0], [1.5, -0.5]]"#,
164 see_also: &["det", "solve", "lu"],
165 category: ApiCategory::LinearAlgebra,
166 },
167 ApiEntry {
168 crate_name: "scirs2-linalg",
169 module_path: "matrix_equations",
170 function_name: "solve_sylvester",
171 signature: "pub fn solve_sylvester<A: MatEqFloat>(a: &ArrayView2<A>, b: &ArrayView2<A>, c: &ArrayView2<A>) -> LinalgResult<Array2<A>>",
172 description: "Solve the Sylvester equation AX + XB = C using the Bartels-Stewart algorithm.",
173 math_reference: "Find X such that AX + XB = C. \
174 Uses Schur decomposition of A and B, then solves the triangular Sylvester equation.",
175 example: r#"use scirs2_linalg::matrix_equations::solve_sylvester;
176use scirs2_core::ndarray::array;
177
178let a = array![[1.0, 0.0], [0.0, 2.0]];
179let b = array![[3.0, 0.0], [0.0, 4.0]];
180let c = array![[4.0, 0.0], [0.0, 6.0]];
181let x = solve_sylvester(&a.view(), &b.view(), &c.view())
182 .expect("solve_sylvester failed");
183// x[0][0] should be 1.0 (since 1*1 + 1*3 = 4)"#,
184 see_also: &["solve_continuous_lyapunov", "solve_discrete_lyapunov"],
185 category: ApiCategory::LinearAlgebra,
186 },
187 ApiEntry {
188 crate_name: "scirs2-linalg",
189 module_path: "special",
190 function_name: "expm",
191 signature: "pub fn expm<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<Array2<F>>",
192 description: "Compute the matrix exponential exp(A) using scaling and squaring with Pade approximation.",
193 math_reference: "exp(A) = sum_{k=0}^{inf} A^k / k!. \
194 Implemented via scaling-and-squaring: exp(A) = (exp(A/2^s))^{2^s} \
195 where exp(A/2^s) is approximated by a Pade rational function.",
196 example: r#"use scirs2_linalg::special::expm;
197use scirs2_core::ndarray::array;
198
199let a = array![[0.0, 1.0], [-1.0, 0.0]];
200let e = expm(&a.view(), None).expect("expm failed");
201// exp([[0,1],[-1,0]]) = [[cos(1), sin(1)], [-sin(1), cos(1)]]"#,
202 see_also: &["det", "inv"],
203 category: ApiCategory::LinearAlgebra,
204 },
205 ApiEntry {
206 crate_name: "scirs2-linalg",
207 module_path: "matrix_equations",
208 function_name: "solve_continuous_riccati",
209 signature: "pub fn solve_continuous_riccati<A: MatEqFloat>(a: &ArrayView2<A>, b: &ArrayView2<A>, q: &ArrayView2<A>, r: &ArrayView2<A>) -> LinalgResult<Array2<A>>",
210 description: "Solve the continuous-time algebraic Riccati equation (CARE) for optimal control.",
211 math_reference: "Find X such that A^T X + X A - X B R^{-1} B^T X + Q = 0. \
212 Uses the Schur method on the 2n x 2n Hamiltonian matrix.",
213 example: r#"use scirs2_linalg::matrix_equations::solve_continuous_riccati;
214use scirs2_core::ndarray::array;
215
216let a = array![[0.0, 1.0], [0.0, 0.0]];
217let b = array![[0.0], [1.0]];
218let q = array![[1.0, 0.0], [0.0, 1.0]];
219let r = array![[1.0]];
220let x = solve_continuous_riccati(&a.view(), &b.view(), &q.view(), &r.view())
221 .expect("CARE solver failed");"#,
222 see_also: &["solve_discrete_riccati", "solve_continuous_lyapunov"],
223 category: ApiCategory::LinearAlgebra,
224 },
225 ApiEntry {
229 crate_name: "scirs2-linalg",
230 module_path: "decomposition",
231 function_name: "lu",
232 signature: "pub fn lu<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<(Array2<F>, Array2<F>, Array2<F>)>",
233 description: "Compute the LU decomposition with partial pivoting, returning (P, L, U).",
234 math_reference: "PA = LU where P is a permutation matrix, L is unit lower triangular, \
235 and U is upper triangular. Uses Gaussian elimination with partial pivoting. \
236 Complexity: O(2n^3/3) for an n x n matrix.",
237 example: r#"use scirs2_linalg::decomposition::lu;
238use scirs2_core::ndarray::array;
239
240let a = array![[2.0, 1.0], [4.0, 3.0]];
241let (p, l, u) = lu(&a.view(), None).expect("LU failed");
242// P * A = L * U"#,
243 see_also: &["det", "inv", "qr"],
244 category: ApiCategory::Decomposition,
245 },
246 ApiEntry {
247 crate_name: "scirs2-linalg",
248 module_path: "decomposition",
249 function_name: "qr",
250 signature: "pub fn qr<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<(Array2<F>, Array2<F>)>",
251 description: "Compute the QR decomposition using Householder reflections, returning (Q, R).",
252 math_reference: "A = QR where Q is orthogonal (Q^T Q = I) and R is upper triangular. \
253 Uses Householder reflections: each step zeroes out below-diagonal entries in one column. \
254 Complexity: O(2mn^2 - 2n^3/3) for m x n matrix.",
255 example: r#"use scirs2_linalg::decomposition::qr;
256use scirs2_core::ndarray::array;
257
258let a = array![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
259let (q, r) = qr(&a.view(), None).expect("QR failed");
260// q is 3x3 orthogonal, r is 3x2 upper triangular"#,
261 see_also: &["svd", "lu", "cholesky"],
262 category: ApiCategory::Decomposition,
263 },
264 ApiEntry {
265 crate_name: "scirs2-linalg",
266 module_path: "decomposition",
267 function_name: "svd",
268 signature: "pub fn svd<F>(a: &ArrayView2<F>, workers: Option<usize>, full_matrices: bool) -> LinalgResult<(Array2<F>, Array1<F>, Array2<F>)>",
269 description: "Compute the Singular Value Decomposition, returning (U, S, Vt).",
270 math_reference: "A = U * diag(S) * V^T where U (m x m) and V (n x n) are orthogonal, \
271 S contains non-negative singular values in decreasing order. \
272 Uses bidiagonalization followed by QR iteration (Golub-Kahan). \
273 Complexity: O(min(mn^2, m^2 n)).",
274 example: r#"use scirs2_linalg::decomposition::svd;
275use scirs2_core::ndarray::array;
276
277let a = array![[1.0, 0.0], [0.0, 2.0], [0.0, 0.0]];
278let (u, s, vt) = svd(&a.view(), None, true).expect("SVD failed");
279// s contains singular values [2.0, 1.0]"#,
280 see_also: &["qr", "eig", "eigh"],
281 category: ApiCategory::Decomposition,
282 },
283 ApiEntry {
284 crate_name: "scirs2-linalg",
285 module_path: "decomposition",
286 function_name: "cholesky",
287 signature: "pub fn cholesky<F>(a: &ArrayView2<F>, workers: Option<usize>) -> LinalgResult<Array2<F>>",
288 description: "Compute the Cholesky decomposition of a symmetric positive-definite matrix, returning lower-triangular L.",
289 math_reference: "A = L L^T where L is lower triangular with positive diagonal entries. \
290 Only valid for symmetric positive-definite matrices. \
291 L_jj = sqrt(A_jj - sum_{k<j} L_jk^2), \
292 L_ij = (A_ij - sum_{k<j} L_ik L_jk) / L_jj for i > j. \
293 Complexity: O(n^3/3).",
294 example: r#"use scirs2_linalg::decomposition::cholesky;
295use scirs2_core::ndarray::array;
296
297let a = array![[4.0, 2.0], [2.0, 3.0]];
298let l = cholesky(&a.view(), None).expect("Cholesky failed");
299// L * L^T = A"#,
300 see_also: &["lu", "qr", "eigh"],
301 category: ApiCategory::Decomposition,
302 },
303 ApiEntry {
304 crate_name: "scirs2-linalg",
305 module_path: "decomposition",
306 function_name: "eig_f64_lapack",
307 signature: "pub fn eig_f64_lapack(a: &ArrayView2<f64>) -> EigResult",
308 description: "Compute eigenvalues and eigenvectors of a general square matrix (may be complex).",
309 math_reference: "Find lambda and v such that A v = lambda v. \
310 For a general real matrix, eigenvalues may be complex conjugate pairs. \
311 Uses the QR algorithm with implicit shifts after Hessenberg reduction. \
312 Complexity: O(10n^3) in practice.",
313 example: r#"use scirs2_linalg::decomposition::eig_f64_lapack;
314use scirs2_core::ndarray::array;
315
316let a = array![[0.0, -1.0], [1.0, 0.0]];
317let result = eig_f64_lapack(&a.view());
318// Eigenvalues are +/- i (complex)"#,
319 see_also: &["eigh_f64_lapack", "svd", "qr"],
320 category: ApiCategory::Decomposition,
321 },
322 ApiEntry {
323 crate_name: "scirs2-linalg",
324 module_path: "decomposition",
325 function_name: "eigh_f64_lapack",
326 signature: "pub fn eigh_f64_lapack(a: &ArrayView2<f64>) -> LinalgResult<(Array1<f64>, Array2<f64>)>",
327 description: "Compute eigenvalues and eigenvectors of a real symmetric matrix (all eigenvalues are real).",
328 math_reference: "For symmetric A, all eigenvalues are real and eigenvectors are orthogonal. \
329 A = V diag(lambda) V^T where V is orthogonal. \
330 Uses tridiagonal reduction + divide-and-conquer or QR iteration. \
331 Complexity: O(4n^3/3) for tridiagonal + O(n^2) per eigenvalue.",
332 example: r#"use scirs2_linalg::decomposition::eigh_f64_lapack;
333use scirs2_core::ndarray::array;
334
335let a = array![[2.0, 1.0], [1.0, 3.0]];
336let (eigenvalues, eigenvectors) = eigh_f64_lapack(&a.view())
337 .expect("eigh failed");
338// eigenvalues are real, eigenvectors are orthogonal"#,
339 see_also: &["eig_f64_lapack", "svd"],
340 category: ApiCategory::Decomposition,
341 },
342 ApiEntry {
343 crate_name: "scirs2-linalg",
344 module_path: "decomposition",
345 function_name: "lu_default",
346 signature: "pub fn lu_default<F>(a: &ArrayView2<F>) -> LinalgResult<(Array2<F>, Array2<F>, Array2<F>)>",
347 description: "Convenience wrapper for LU decomposition with default worker count.",
348 math_reference: "Same as lu: PA = LU decomposition with partial pivoting.",
349 example: r#"use scirs2_linalg::decomposition::lu_default;
350use scirs2_core::ndarray::array;
351
352let a = array![[1.0, 2.0], [3.0, 4.0]];
353let (p, l, u) = lu_default(&a.view()).expect("LU failed");"#,
354 see_also: &["lu", "qr_default", "svd_default"],
355 category: ApiCategory::Decomposition,
356 },
357 ApiEntry {
358 crate_name: "scirs2-linalg",
359 module_path: "decomposition",
360 function_name: "qr_default",
361 signature: "pub fn qr_default<F>(a: &ArrayView2<F>) -> LinalgResult<(Array2<F>, Array2<F>)>",
362 description: "Convenience wrapper for QR decomposition with default worker count.",
363 math_reference: "Same as qr: A = QR via Householder reflections.",
364 example: r#"use scirs2_linalg::decomposition::qr_default;
365use scirs2_core::ndarray::array;
366
367let a = array![[1.0, 2.0], [3.0, 4.0]];
368let (q, r) = qr_default(&a.view()).expect("QR failed");"#,
369 see_also: &["qr", "lu_default", "svd_default"],
370 category: ApiCategory::Decomposition,
371 },
372 ApiEntry {
373 crate_name: "scirs2-linalg",
374 module_path: "decomposition",
375 function_name: "svd_default",
376 signature: "pub fn svd_default<F>(a: &ArrayView2<F>, full_matrices: bool) -> LinalgResult<(Array2<F>, Array1<F>, Array2<F>)>",
377 description: "Convenience wrapper for SVD with default worker count.",
378 math_reference: "Same as svd: A = U diag(S) V^T decomposition.",
379 example: r#"use scirs2_linalg::decomposition::svd_default;
380use scirs2_core::ndarray::array;
381
382let a = array![[1.0, 2.0], [3.0, 4.0]];
383let (u, s, vt) = svd_default(&a.view(), false).expect("SVD failed");"#,
384 see_also: &["svd", "qr_default", "lu_default"],
385 category: ApiCategory::Decomposition,
386 },
387 ApiEntry {
388 crate_name: "scirs2-linalg",
389 module_path: "decomposition",
390 function_name: "cholesky_default",
391 signature: "pub fn cholesky_default<F>(a: &ArrayView2<F>) -> LinalgResult<Array2<F>>",
392 description: "Convenience wrapper for Cholesky decomposition with default worker count.",
393 math_reference: "Same as cholesky: A = L L^T for SPD matrices.",
394 example: r#"use scirs2_linalg::decomposition::cholesky_default;
395use scirs2_core::ndarray::array;
396
397let a = array![[4.0, 2.0], [2.0, 3.0]];
398let l = cholesky_default(&a.view()).expect("Cholesky failed");"#,
399 see_also: &["cholesky", "lu_default"],
400 category: ApiCategory::Decomposition,
401 },
402 ApiEntry {
406 crate_name: "scirs2-stats",
407 module_path: "simd_enhanced_core",
408 function_name: "mean_enhanced",
409 signature: "pub fn mean_enhanced<F, D>(x: &ArrayBase<D, Ix1>) -> StatsResult<F>",
410 description: "Compute the arithmetic mean of a 1-D array using SIMD-enhanced accumulation.",
411 math_reference: "mean(x) = (1/n) * sum_{i=1}^{n} x_i. \
412 Uses compensated (Kahan) summation for numerical stability.",
413 example: r#"use scirs2_stats::simd_enhanced_core::mean_enhanced;
414use scirs2_core::ndarray::array;
415
416let data = array![1.0, 2.0, 3.0, 4.0, 5.0];
417let m: f64 = mean_enhanced(&data).expect("mean failed");
418assert!((m - 3.0).abs() < 1e-10);"#,
419 see_also: &["variance_enhanced", "median_abs_deviation_simd"],
420 category: ApiCategory::Statistics,
421 },
422 ApiEntry {
423 crate_name: "scirs2-stats",
424 module_path: "simd_enhanced_core",
425 function_name: "variance_enhanced",
426 signature: "pub fn variance_enhanced<F, D>(x: &ArrayBase<D, Ix1>, ddof: usize) -> StatsResult<F>",
427 description: "Compute the sample variance of a 1-D array with configurable degrees-of-freedom correction.",
428 math_reference: "var(x, ddof) = (1/(n - ddof)) * sum_{i=1}^{n} (x_i - mean(x))^2. \
429 ddof=0 gives population variance; ddof=1 gives unbiased sample variance (Bessel's correction).",
430 example: r#"use scirs2_stats::simd_enhanced_core::variance_enhanced;
431use scirs2_core::ndarray::array;
432
433let data = array![2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
434let v: f64 = variance_enhanced(&data, 1).expect("variance failed");
435// Unbiased sample variance"#,
436 see_also: &["mean_enhanced", "median_abs_deviation_simd"],
437 category: ApiCategory::Statistics,
438 },
439 ApiEntry {
440 crate_name: "scirs2-stats",
441 module_path: "correlation_simd",
442 function_name: "pearson_r_simd",
443 signature: "pub fn pearson_r_simd<F, D>(x: &ArrayBase<D, Ix1>, y: &ArrayBase<D, Ix1>) -> StatsResult<F>",
444 description: "Compute the Pearson product-moment correlation coefficient using SIMD-accelerated dot products.",
445 math_reference: "r = cov(x, y) / (std(x) * std(y)) \
446 = [n sum(xy) - sum(x)sum(y)] / sqrt([n sum(x^2) - (sum x)^2][n sum(y^2) - (sum y)^2]). \
447 Range: [-1, 1]. Measures linear relationship strength.",
448 example: r#"use scirs2_stats::correlation_simd::pearson_r_simd;
449use scirs2_core::ndarray::array;
450
451let x = array![1.0, 2.0, 3.0, 4.0, 5.0];
452let y = array![2.0, 4.0, 6.0, 8.0, 10.0];
453let r: f64 = pearson_r_simd(&x, &y).expect("pearson_r failed");
454assert!((r - 1.0).abs() < 1e-10); // Perfect positive correlation"#,
455 see_also: &["spearman_r_simd", "ttest_ind"],
456 category: ApiCategory::Statistics,
457 },
458 ApiEntry {
459 crate_name: "scirs2-stats",
460 module_path: "correlation_simd_enhanced",
461 function_name: "spearman_r_simd",
462 signature: "pub fn spearman_r_simd<F, D>(x: &ArrayBase<D, Ix1>, y: &ArrayBase<D, Ix1>) -> StatsResult<F>",
463 description: "Compute Spearman's rank correlation coefficient using SIMD-accelerated ranking.",
464 math_reference: "rho = 1 - 6 sum(d_i^2) / (n(n^2 - 1)) where d_i = rank(x_i) - rank(y_i). \
465 Measures monotonic (not necessarily linear) relationship. Range: [-1, 1].",
466 example: r#"use scirs2_stats::correlation_simd_enhanced::spearman_r_simd;
467use scirs2_core::ndarray::array;
468
469let x = array![1.0, 2.0, 3.0, 4.0, 5.0];
470let y = array![5.0, 6.0, 7.0, 8.0, 7.0];
471let rho: f64 = spearman_r_simd(&x, &y).expect("spearman_r failed");"#,
472 see_also: &["pearson_r_simd", "ttest_ind"],
473 category: ApiCategory::Statistics,
474 },
475 ApiEntry {
476 crate_name: "scirs2-stats",
477 module_path: "dispersion_simd",
478 function_name: "median_abs_deviation_simd",
479 signature: "pub fn median_abs_deviation_simd<F, D>(data: &ArrayBase<D, Ix1>, scale: F) -> StatsResult<F>",
480 description: "Compute the Median Absolute Deviation (MAD), a robust measure of spread.",
481 math_reference: "MAD = median(|x_i - median(x)|). \
482 Scaled MAD = scale * MAD; with scale = 1.4826, it estimates std for normal data. \
483 Breakdown point: 50% (robust to up to half the data being outliers).",
484 example: r#"use scirs2_stats::dispersion_simd::median_abs_deviation_simd;
485use scirs2_core::ndarray::array;
486
487let data = array![1.0, 2.0, 3.0, 4.0, 100.0]; // outlier at 100
488let mad: f64 = median_abs_deviation_simd(&data, 1.0)
489 .expect("MAD failed");
490// MAD is robust to the outlier at 100"#,
491 see_also: &["variance_enhanced", "mean_enhanced"],
492 category: ApiCategory::Statistics,
493 },
494 ApiEntry {
498 crate_name: "scirs2-stats",
499 module_path: "distributions::normal",
500 function_name: "Normal::new",
501 signature: "pub fn new(loc: F, scale: F) -> StatsResult<Normal<F>>",
502 description: "Create a Normal (Gaussian) distribution with given mean and standard deviation.",
503 math_reference: "PDF: f(x) = (1 / (sigma * sqrt(2 pi))) * exp(-(x - mu)^2 / (2 sigma^2)). \
504 CDF: Phi(x) = 0.5 * (1 + erf((x - mu) / (sigma * sqrt(2)))). \
505 Mean = mu, Variance = sigma^2.",
506 example: r#"use scirs2_stats::distributions::normal::Normal;
507use scirs2_stats::traits::Distribution;
508
509let n = Normal::new(0.0_f64, 1.0).expect("Normal::new failed");
510let p = n.pdf(0.0); // ~0.3989 (peak of standard normal)
511let c = n.cdf(0.0); // 0.5 (symmetric about mean)"#,
512 see_also: &["Beta::new", "Gamma::new", "Uniform::new"],
513 category: ApiCategory::Distribution,
514 },
515 ApiEntry {
516 crate_name: "scirs2-stats",
517 module_path: "distributions::beta",
518 function_name: "Beta::new",
519 signature: "pub fn new(alpha: F, beta: F) -> StatsResult<Beta<F>>",
520 description: "Create a Beta distribution with shape parameters alpha and beta on [0, 1].",
521 math_reference: "PDF: f(x; a, b) = x^{a-1} (1-x)^{b-1} / B(a, b) for x in [0, 1]. \
522 B(a, b) = Gamma(a) Gamma(b) / Gamma(a+b) is the beta function. \
523 Mean = a/(a+b), Variance = ab / ((a+b)^2 (a+b+1)).",
524 example: r#"use scirs2_stats::distributions::beta::Beta;
525use scirs2_stats::traits::Distribution;
526
527let b = Beta::new(2.0_f64, 5.0).expect("Beta::new failed");
528let p = b.pdf(0.3);
529let c = b.cdf(0.5);"#,
530 see_also: &["Normal::new", "Gamma::new", "Uniform::new"],
531 category: ApiCategory::Distribution,
532 },
533 ApiEntry {
534 crate_name: "scirs2-stats",
535 module_path: "distributions::gamma",
536 function_name: "Gamma::new",
537 signature: "pub fn new(shape: F, scale: F) -> StatsResult<Gamma<F>>",
538 description: "Create a Gamma distribution with given shape (a) and scale (theta) parameters.",
539 math_reference: "PDF: f(x; a, theta) = x^{a-1} exp(-x/theta) / (theta^a Gamma(a)) for x > 0. \
540 Mean = a * theta, Variance = a * theta^2. \
541 Special cases: a=1 gives Exponential; a=n/2, theta=2 gives Chi-squared(n).",
542 example: r#"use scirs2_stats::distributions::gamma::Gamma;
543use scirs2_stats::traits::Distribution;
544
545let g = Gamma::new(2.0_f64, 1.0).expect("Gamma::new failed");
546let p = g.pdf(1.0);
547let c = g.cdf(2.0);"#,
548 see_also: &["Beta::new", "Normal::new", "Poisson::new"],
549 category: ApiCategory::Distribution,
550 },
551 ApiEntry {
552 crate_name: "scirs2-stats",
553 module_path: "distributions::poisson",
554 function_name: "Poisson::new",
555 signature: "pub fn new(mu: F) -> StatsResult<Poisson<F>>",
556 description: "Create a Poisson distribution with rate parameter mu.",
557 math_reference: "PMF: P(X = k) = mu^k exp(-mu) / k! for k = 0, 1, 2, ... \
558 Mean = mu, Variance = mu. \
559 Models the number of events in a fixed interval given constant average rate.",
560 example: r#"use scirs2_stats::distributions::poisson::Poisson;
561use scirs2_stats::traits::Distribution;
562
563let p = Poisson::new(3.0_f64).expect("Poisson::new failed");
564let prob = p.pmf(2.0); // P(X = 2) for Poisson(3)"#,
565 see_also: &["Binomial::new", "Normal::new", "Gamma::new"],
566 category: ApiCategory::Distribution,
567 },
568 ApiEntry {
569 crate_name: "scirs2-stats",
570 module_path: "distributions::uniform",
571 function_name: "Uniform::new",
572 signature: "pub fn new(low: F, high: F) -> StatsResult<Uniform<F>>",
573 description: "Create a continuous Uniform distribution on the interval [low, high].",
574 math_reference: "PDF: f(x) = 1 / (high - low) for x in [low, high], 0 otherwise. \
575 CDF: F(x) = (x - low) / (high - low). \
576 Mean = (low + high) / 2, Variance = (high - low)^2 / 12.",
577 example: r#"use scirs2_stats::distributions::uniform::Uniform;
578use scirs2_stats::traits::Distribution;
579
580let u = Uniform::new(0.0_f64, 1.0).expect("Uniform::new failed");
581let p = u.pdf(0.5); // 1.0
582let c = u.cdf(0.75); // 0.75"#,
583 see_also: &["Normal::new", "Beta::new"],
584 category: ApiCategory::Distribution,
585 },
586 ApiEntry {
590 crate_name: "scirs2-stats",
591 module_path: "tests::ttest",
592 function_name: "ttest_1samp",
593 signature: "pub fn ttest_1samp<F>(x: &ArrayView1<F>, popmean: F) -> StatsResult<(F, F)>",
594 description: "One-sample t-test: test whether the mean of a sample differs from a hypothesized population mean.",
595 math_reference: "t = (mean(x) - mu_0) / (s / sqrt(n)) where s is sample std dev. \
596 Under H0: mean = mu_0, t follows Student's t-distribution with n-1 degrees of freedom. \
597 Returns (t_statistic, two-sided p-value).",
598 example: r#"use scirs2_stats::tests::ttest::ttest_1samp;
599use scirs2_core::ndarray::array;
600
601let x = array![5.1, 4.9, 5.2, 5.0, 4.8, 5.1];
602let (t_stat, p_value) = ttest_1samp(&x.view(), 5.0_f64)
603 .expect("ttest_1samp failed");
604// Test whether sample mean differs from 5.0"#,
605 see_also: &["ttest_ind", "ttest_rel"],
606 category: ApiCategory::HypothesisTest,
607 },
608 ApiEntry {
609 crate_name: "scirs2-stats",
610 module_path: "tests::ttest",
611 function_name: "ttest_ind",
612 signature: "pub fn ttest_ind<F>(x: &ArrayView1<F>, y: &ArrayView1<F>, equal_var: bool) -> StatsResult<(F, F)>",
613 description: "Independent two-sample t-test: test whether the means of two independent samples differ.",
614 math_reference: "If equal_var=true (Student): t = (mean_x - mean_y) / (s_p * sqrt(1/n_x + 1/n_y)) \
615 where s_p^2 = ((n_x-1)s_x^2 + (n_y-1)s_y^2) / (n_x + n_y - 2). \
616 If equal_var=false (Welch): uses Welch-Satterthwaite df approximation. \
617 Returns (t_statistic, two-sided p-value).",
618 example: r#"use scirs2_stats::tests::ttest::ttest_ind;
619use scirs2_core::ndarray::array;
620
621let group_a = array![5.1, 4.9, 5.2, 5.0, 4.8];
622let group_b = array![5.5, 5.3, 5.6, 5.4, 5.7];
623let (t_stat, p_value) = ttest_ind(&group_a.view(), &group_b.view(), false)
624 .expect("ttest_ind failed");
625// Welch's t-test for unequal variances"#,
626 see_also: &["ttest_1samp", "ttest_rel", "pearson_r_simd"],
627 category: ApiCategory::HypothesisTest,
628 },
629 ApiEntry {
630 crate_name: "scirs2-stats",
631 module_path: "tests::ttest",
632 function_name: "ttest_rel",
633 signature: "pub fn ttest_rel<F>(x: &ArrayView1<F>, y: &ArrayView1<F>) -> StatsResult<(F, F)>",
634 description: "Paired t-test: test whether the mean difference of paired observations is zero.",
635 math_reference: "t = mean(d) / (s_d / sqrt(n)) where d_i = x_i - y_i, \
636 s_d is the std dev of differences. df = n - 1. \
637 More powerful than independent test when observations are naturally paired.",
638 example: r#"use scirs2_stats::tests::ttest::ttest_rel;
639use scirs2_core::ndarray::array;
640
641let before = array![200.0, 210.0, 190.0, 220.0, 205.0];
642let after = array![195.0, 205.0, 185.0, 212.0, 198.0];
643let (t_stat, p_value) = ttest_rel(&before.view(), &after.view())
644 .expect("ttest_rel failed");"#,
645 see_also: &["ttest_1samp", "ttest_ind"],
646 category: ApiCategory::HypothesisTest,
647 },
648 ApiEntry {
649 crate_name: "scirs2-stats",
650 module_path: "tests::ttest",
651 function_name: "ttest_ind_from_stats",
652 signature: "pub fn ttest_ind_from_stats<F>(mean1: F, std1: F, nobs1: F, mean2: F, std2: F, nobs2: F, equal_var: bool) -> StatsResult<(F, F)>",
653 description: "Two-sample t-test from summary statistics (means, standard deviations, sample sizes).",
654 math_reference: "Same formulas as ttest_ind, but accepts pre-computed statistics. \
655 Useful when raw data is not available (e.g., from published papers).",
656 example: r#"use scirs2_stats::tests::ttest::ttest_ind_from_stats;
657
658let (t_stat, p_value) = ttest_ind_from_stats(
659 5.0_f64, 1.0, 30.0, // group 1: mean=5, std=1, n=30
660 5.5_f64, 1.2, 35.0, // group 2: mean=5.5, std=1.2, n=35
661 false, // Welch's test
662).expect("ttest_ind_from_stats failed");"#,
663 see_also: &["ttest_ind", "ttest_1samp"],
664 category: ApiCategory::HypothesisTest,
665 },
666 ApiEntry {
670 crate_name: "scirs2-signal",
671 module_path: "filter::iir",
672 function_name: "butter",
673 signature: "pub fn butter<T>(order: usize, cutoff: T, btype: FilterType, fs: Option<T>) -> SignalResult<(Vec<f64>, Vec<f64>)>",
674 description: "Design a Butterworth IIR filter and return (b, a) coefficients.",
675 math_reference: "|H(j omega)|^2 = 1 / (1 + (omega / omega_c)^{2N}) where N is the filter order. \
676 Maximally flat magnitude response in the passband. \
677 Poles are equally spaced on a circle in the s-plane.",
678 example: r#"use scirs2_signal::filter::iir::butter;
679
680// 4th-order lowpass Butterworth at 10 Hz, sampled at 100 Hz
681let (b, a) = butter(4, 10.0, scirs2_signal::FilterType::Lowpass, Some(100.0))
682 .expect("butter failed");"#,
683 see_also: &["firwin", "lfilter", "filtfilt"],
684 category: ApiCategory::SignalProcessing,
685 },
686 ApiEntry {
687 crate_name: "scirs2-signal",
688 module_path: "filter::fir",
689 function_name: "firwin",
690 signature: "pub fn firwin<T>(numtaps: usize, cutoff: T, pass_zero: bool, fs: Option<T>) -> SignalResult<Vec<f64>>",
691 description: "Design a FIR filter using the window method (Hamming window by default).",
692 math_reference: "h[n] = w[n] * h_ideal[n] where h_ideal is the ideal impulse response \
693 and w[n] is the window function. Linear phase guaranteed for symmetric coefficients. \
694 numtaps controls filter length (higher = sharper transition).",
695 example: r#"use scirs2_signal::filter::fir::firwin;
696
697// 65-tap lowpass FIR at 10 Hz, sampled at 100 Hz
698let h = firwin(65, 10.0, true, Some(100.0))
699 .expect("firwin failed");
700assert_eq!(h.len(), 65);"#,
701 see_also: &["butter", "lfilter", "filtfilt"],
702 category: ApiCategory::SignalProcessing,
703 },
704 ApiEntry {
705 crate_name: "scirs2-signal",
706 module_path: "filter::application",
707 function_name: "lfilter",
708 signature: "pub fn lfilter<T>(b: &[f64], a: &[f64], x: &[T]) -> SignalResult<Vec<f64>>",
709 description: "Apply a digital filter (IIR or FIR) to a signal using the direct-form II transposed structure.",
710 math_reference: "y[n] = (1/a[0]) * (sum_{k=0}^{M} b[k] x[n-k] - sum_{k=1}^{N} a[k] y[n-k]). \
711 For FIR: a = [1.0] (no feedback). Causal (forward-only) filtering introduces phase distortion.",
712 example: r#"use scirs2_signal::filter::application::lfilter;
713
714let b = vec![0.1, 0.2, 0.3, 0.2, 0.1]; // FIR coefficients
715let a = vec![1.0]; // FIR (no feedback)
716let signal = vec![1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0];
717let filtered = lfilter(&b, &a, &signal).expect("lfilter failed");"#,
718 see_also: &["filtfilt", "butter", "firwin"],
719 category: ApiCategory::SignalProcessing,
720 },
721 ApiEntry {
722 crate_name: "scirs2-signal",
723 module_path: "filter::application",
724 function_name: "filtfilt",
725 signature: "pub fn filtfilt<T>(b: &[f64], a: &[f64], x: &[T]) -> SignalResult<Vec<f64>>",
726 description: "Zero-phase digital filtering: apply filter forward and backward to eliminate phase distortion.",
727 math_reference: "y = lfilter(b, a, lfilter(b, a, x, forward), backward). \
728 Effective transfer function: |H(omega)|^2 (magnitude squared, zero phase). \
729 Result has zero phase distortion but squared magnitude response.",
730 example: r#"use scirs2_signal::filter::application::filtfilt;
731
732let b = vec![0.1, 0.2, 0.4, 0.2, 0.1];
733let a = vec![1.0];
734let signal: Vec<f64> = (0..100).map(|i| (i as f64 * 0.1).sin()).collect();
735let filtered = filtfilt(&b, &a, &signal).expect("filtfilt failed");"#,
736 see_also: &["lfilter", "butter", "firwin"],
737 category: ApiCategory::SignalProcessing,
738 },
739 ApiEntry {
740 crate_name: "scirs2-signal",
741 module_path: "spectral::legacy",
742 function_name: "welch",
743 signature: "pub fn welch<T>(x: &[T], fs: f64, nperseg: usize, noverlap: Option<usize>) -> SignalResult<(Vec<f64>, Vec<f64>)>",
744 description: "Estimate power spectral density using Welch's method (averaged modified periodograms).",
745 math_reference: "PSD = (1/K) sum_{k=1}^{K} |FFT(w * x_k)|^2 / (fs * sum(w^2)) \
746 where x_k are overlapping segments and w is a window function. \
747 Reduces variance at the cost of frequency resolution compared to a single periodogram.",
748 example: r#"use scirs2_signal::spectral::legacy::welch;
749
750let fs = 1000.0;
751let signal: Vec<f64> = (0..4096)
752 .map(|i| (2.0 * std::f64::consts::PI * 50.0 * i as f64 / fs).sin())
753 .collect();
754let (freqs, psd) = welch(&signal, fs, 256, None)
755 .expect("welch failed");
756// Peak in PSD near 50 Hz"#,
757 see_also: &["stft", "spectrogram", "fft"],
758 category: ApiCategory::SignalProcessing,
759 },
760 ApiEntry {
761 crate_name: "scirs2-signal",
762 module_path: "spectral::legacy",
763 function_name: "stft",
764 signature: "pub fn stft<T>(x: &[T], fs: f64, nperseg: usize, noverlap: Option<usize>) -> SignalResult<(Vec<f64>, Vec<f64>, Array2<Complex64>)>",
765 description: "Compute the Short-Time Fourier Transform for time-frequency analysis.",
766 math_reference: "STFT(t, f) = sum_{n} x[n] w[n - t] exp(-j 2 pi f n) \
767 where w is a window function centered at time t. \
768 Returns (frequencies, times, complex STFT matrix).",
769 example: r#"use scirs2_signal::spectral::legacy::stft;
770
771let fs = 1000.0;
772let signal: Vec<f64> = (0..4096)
773 .map(|i| (2.0 * std::f64::consts::PI * 100.0 * i as f64 / fs).sin())
774 .collect();
775let (freqs, times, stft_matrix) = stft(&signal, fs, 256, None)
776 .expect("stft failed");"#,
777 see_also: &["welch", "spectrogram", "fft"],
778 category: ApiCategory::SignalProcessing,
779 },
780 ApiEntry {
781 crate_name: "scirs2-signal",
782 module_path: "spectral::legacy",
783 function_name: "spectrogram",
784 signature: "pub fn spectrogram<T>(x: &[T], fs: f64, nperseg: usize, noverlap: Option<usize>) -> SignalResult<(Vec<f64>, Vec<f64>, Array2<f64>)>",
785 description: "Compute the spectrogram (magnitude-squared STFT) for time-frequency visualization.",
786 math_reference: "S(t, f) = |STFT(t, f)|^2. \
787 Returns (frequencies, times, power matrix). \
788 Useful for visualizing how the spectral content of a signal changes over time.",
789 example: r#"use scirs2_signal::spectral::legacy::spectrogram;
790
791let fs = 1000.0;
792let signal: Vec<f64> = (0..8192)
793 .map(|i| {
794 let t = i as f64 / fs;
795 (2.0 * std::f64::consts::PI * (50.0 + 200.0 * t) * t).sin()
796 })
797 .collect();
798let (freqs, times, power) = spectrogram(&signal, fs, 256, None)
799 .expect("spectrogram failed");"#,
800 see_also: &["stft", "welch", "fft"],
801 category: ApiCategory::SignalProcessing,
802 },
803 ApiEntry {
804 crate_name: "scirs2-signal",
805 module_path: "filter::iir",
806 function_name: "butter_bandpass_bandstop",
807 signature: "pub fn butter_bandpass_bandstop(order: usize, low: f64, high: f64, btype: FilterType, fs: Option<f64>) -> SignalResult<(Vec<f64>, Vec<f64>)>",
808 description: "Design a Butterworth bandpass or bandstop filter with low and high cutoff frequencies.",
809 math_reference: "Bandpass: passes frequencies between low and high, attenuates outside. \
810 Bandstop (notch): attenuates frequencies between low and high, passes outside. \
811 Achieved via analog prototype lowpass-to-bandpass frequency transformation.",
812 example: r#"use scirs2_signal::filter::iir::butter_bandpass_bandstop;
813
814// 4th-order bandpass filter, 20-80 Hz, sampled at 500 Hz
815let (b, a) = butter_bandpass_bandstop(
816 4, 20.0, 80.0,
817 scirs2_signal::FilterType::Bandpass,
818 Some(500.0),
819).expect("bandpass filter design failed");"#,
820 see_also: &["butter", "firwin", "filtfilt"],
821 category: ApiCategory::SignalProcessing,
822 },
823 ApiEntry {
827 crate_name: "scirs2-fft",
828 module_path: "memory_efficient_v2",
829 function_name: "fft_optimized",
830 signature: "pub fn fft_optimized<T>(x: &[T], n: Option<usize>) -> FFTResult<Vec<Complex64>>",
831 description: "Compute the 1-D discrete Fourier transform using an optimized Cooley-Tukey FFT algorithm.",
832 math_reference: "X[k] = sum_{n=0}^{N-1} x[n] exp(-j 2 pi k n / N) for k = 0, ..., N-1. \
833 Uses mixed-radix Cooley-Tukey decomposition (radix-2/4). \
834 Complexity: O(N log N) vs O(N^2) for naive DFT.",
835 example: r#"use scirs2_fft::memory_efficient_v2::fft_optimized;
836
837let signal = vec![1.0, 0.0, -1.0, 0.0]; // simple test signal
838let spectrum = fft_optimized(&signal, None)
839 .expect("fft failed");
840assert_eq!(spectrum.len(), 4);"#,
841 see_also: &["ifft_optimized", "rfft_optimized", "fft_frequencies"],
842 category: ApiCategory::FFT,
843 },
844 ApiEntry {
845 crate_name: "scirs2-fft",
846 module_path: "memory_efficient_v2",
847 function_name: "ifft_optimized",
848 signature: "pub fn ifft_optimized<T>(x: &[T], n: Option<usize>) -> FFTResult<Vec<Complex64>>",
849 description: "Compute the 1-D inverse discrete Fourier transform.",
850 math_reference: "x[n] = (1/N) sum_{k=0}^{N-1} X[k] exp(j 2 pi k n / N) for n = 0, ..., N-1. \
851 IFFT(X) = conj(FFT(conj(X))) / N. Complexity: O(N log N).",
852 example: r#"use scirs2_fft::memory_efficient_v2::{fft_optimized, ifft_optimized};
853use scirs2_fft::num_complex::Complex64;
854
855let signal = vec![1.0, 2.0, 3.0, 4.0];
856let spectrum = fft_optimized(&signal, None).expect("fft failed");
857let recovered = ifft_optimized(&spectrum, None).expect("ifft failed");
858// recovered[i].re should be approximately signal[i]"#,
859 see_also: &["fft_optimized", "rfft_optimized"],
860 category: ApiCategory::FFT,
861 },
862 ApiEntry {
863 crate_name: "scirs2-fft",
864 module_path: "real_fft",
865 function_name: "rfft_optimized",
866 signature: "pub fn rfft_optimized<T>(x: &[T], n: Option<usize>) -> FFTResult<Vec<Complex64>>",
867 description: "Compute the 1-D FFT of a real-valued signal, returning only the non-redundant half of the spectrum.",
868 math_reference: "For real input of length N, the FFT satisfies X[k] = conj(X[N-k]), \
869 so only N/2+1 complex values are needed. \
870 Approximately 2x faster than complex FFT for real data.",
871 example: r#"use scirs2_fft::real_fft::rfft_optimized;
872
873let signal: Vec<f64> = (0..1024)
874 .map(|i| (2.0 * std::f64::consts::PI * 50.0 * i as f64 / 1000.0).sin())
875 .collect();
876let spectrum = rfft_optimized(&signal, None).expect("rfft failed");
877assert_eq!(spectrum.len(), 513); // N/2 + 1"#,
878 see_also: &["fft_optimized", "ifft_optimized"],
879 category: ApiCategory::FFT,
880 },
881 ApiEntry {
882 crate_name: "scirs2-fft",
883 module_path: "multidimensional",
884 function_name: "fft_frequencies",
885 signature: "pub fn fft_frequencies(n: usize, sample_rate: f64) -> Vec<f64>",
886 description: "Return the DFT sample frequencies for a signal of length n at the given sample rate.",
887 math_reference: "f[k] = k * sample_rate / n for k = 0, ..., n/2, \
888 then -(n/2-1)*sr/n, ..., -sr/n for the negative frequencies. \
889 Matches the ordering of FFT output bins.",
890 example: r#"use scirs2_fft::multidimensional::fft_frequencies;
891
892let freqs = fft_frequencies(1024, 1000.0);
893assert_eq!(freqs.len(), 1024);
894// freqs[0] = 0.0 (DC), freqs[1] ~ 0.977 Hz, ..."#,
895 see_also: &["fft_optimized", "rfft_optimized"],
896 category: ApiCategory::FFT,
897 },
898 ApiEntry {
899 crate_name: "scirs2-fft",
900 module_path: "memory_efficient_v2",
901 function_name: "fft2_optimized",
902 signature: "pub fn fft2_optimized<T>(x: &[Vec<T>], shape: Option<(usize, usize)>) -> FFTResult<Vec<Vec<Complex64>>>",
903 description: "Compute the 2-D discrete Fourier transform of a matrix.",
904 math_reference: "X[k1, k2] = sum_{n1} sum_{n2} x[n1, n2] exp(-j 2 pi (k1 n1/N1 + k2 n2/N2)). \
905 Computed as 1-D FFTs along rows, then 1-D FFTs along columns. \
906 Complexity: O(N1 N2 log(N1 N2)).",
907 example: r#"use scirs2_fft::memory_efficient_v2::fft2_optimized;
908
909let matrix = vec![
910 vec![1.0, 0.0, 0.0, 0.0],
911 vec![0.0, 1.0, 0.0, 0.0],
912 vec![0.0, 0.0, 1.0, 0.0],
913 vec![0.0, 0.0, 0.0, 1.0],
914];
915let spectrum_2d = fft2_optimized(&matrix, None)
916 .expect("fft2 failed");"#,
917 see_also: &["fft_optimized", "ifft2_optimized"],
918 category: ApiCategory::FFT,
919 },
920 ApiEntry {
924 crate_name: "scirs2-optimize",
925 module_path: "unconstrained::lbfgs",
926 function_name: "minimize_lbfgs",
927 signature: "pub fn minimize_lbfgs<F, G, S>(f: F, grad: G, x0: &[f64], options: S) -> OptimizeResult<OptResult>",
928 description: "Minimize a function using the L-BFGS quasi-Newton method (limited-memory BFGS).",
929 math_reference: "Approximates inverse Hessian using m most recent (s_k, y_k) pairs \
930 where s_k = x_{k+1} - x_k, y_k = g_{k+1} - g_k. \
931 Two-loop recursion computes H_k g_k in O(mn) time and O(mn) memory. \
932 Superlinear convergence for smooth, unconstrained problems.",
933 example: r#"use scirs2_optimize::unconstrained::lbfgs::minimize_lbfgs;
934
935// Minimize Rosenbrock function: f(x,y) = (1-x)^2 + 100*(y-x^2)^2
936let f = |x: &[f64]| (1.0 - x[0]).powi(2) + 100.0 * (x[1] - x[0].powi(2)).powi(2);
937let grad = |x: &[f64]| vec![
938 -2.0 * (1.0 - x[0]) - 400.0 * x[0] * (x[1] - x[0].powi(2)),
939 200.0 * (x[1] - x[0].powi(2)),
940];
941let x0 = vec![-1.0, 1.0];
942let result = minimize_lbfgs(&f, &grad, &x0, ())
943 .expect("L-BFGS failed");
944// result.x should be near [1.0, 1.0]"#,
945 see_also: &["minimize_lbfgsb", "minimize_conjugate_gradient", "minimize_trust_ncg"],
946 category: ApiCategory::Optimization,
947 },
948 ApiEntry {
949 crate_name: "scirs2-optimize",
950 module_path: "unconstrained::lbfgs",
951 function_name: "minimize_lbfgsb",
952 signature: "pub fn minimize_lbfgsb<F, G, S>(f: F, grad: G, x0: &[f64], bounds: Option<Vec<(Option<f64>, Option<f64>)>>, options: S) -> OptimizeResult<OptResult>",
953 description: "Minimize a function with optional box constraints using L-BFGS-B (bounded L-BFGS).",
954 math_reference: "Extension of L-BFGS that handles bound constraints l_i <= x_i <= u_i. \
955 Uses the gradient projection method and Cauchy point computation \
956 to identify the active set, then applies L-BFGS within the free variables.",
957 example: r#"use scirs2_optimize::unconstrained::lbfgs::minimize_lbfgsb;
958
959let f = |x: &[f64]| x[0].powi(2) + x[1].powi(2);
960let grad = |x: &[f64]| vec![2.0 * x[0], 2.0 * x[1]];
961let bounds = Some(vec![
962 (Some(0.5), None), // x[0] >= 0.5
963 (Some(-1.0), Some(1.0)), // -1 <= x[1] <= 1
964]);
965let result = minimize_lbfgsb(&f, &grad, &[2.0, 0.5], bounds, ())
966 .expect("L-BFGS-B failed");
967// x[0] should be 0.5 (active bound), x[1] should be 0.0"#,
968 see_also: &["minimize_lbfgs", "minimize_trust_ncg"],
969 category: ApiCategory::Optimization,
970 },
971 ApiEntry {
972 crate_name: "scirs2-optimize",
973 module_path: "scalar",
974 function_name: "minimize_scalar",
975 signature: "pub fn minimize_scalar<F>(f: F, bracket: Option<(f64, f64, f64)>, bounds: Option<(f64, f64)>, method: ScalarMethod) -> OptimizeResult<ScalarResult>",
976 description: "Minimize a scalar function of one variable using Brent's method or golden section search.",
977 math_reference: "Brent's method: combines golden section search with parabolic interpolation. \
978 Guaranteed convergence with superlinear rate in smooth regions. \
979 Tolerance: finds x* such that |x - x*| < tol, where tol ~ sqrt(machine epsilon).",
980 example: r#"use scirs2_optimize::scalar::minimize_scalar;
981
982let f = |x: &f64| (x - 3.0).powi(2) + 1.0;
983// Minimize (x-3)^2 + 1 near x=3"#,
984 see_also: &["minimize_lbfgs", "root"],
985 category: ApiCategory::Optimization,
986 },
987 ApiEntry {
988 crate_name: "scirs2-optimize",
989 module_path: "roots",
990 function_name: "root",
991 signature: "pub fn root<F, J, S>(f: F, x0: &[f64], method: RootMethod, jac: Option<J>, options: S) -> OptimizeResult<RootResult>",
992 description: "Find a root of a vector-valued function F(x) = 0 using Newton, Broyden, or other methods.",
993 math_reference: "Newton: x_{k+1} = x_k - J(x_k)^{-1} F(x_k) where J is the Jacobian. \
994 Quadratic convergence near the root. \
995 Broyden: approximates Jacobian via rank-1 updates (no Jacobian computation needed). \
996 Krylov: uses GMRES to solve the Newton system inexactly.",
997 example: r#"use scirs2_optimize::roots::root;
998
999// Find root of f(x) = [x[0]^2 + x[1] - 1, x[0] - x[1]^2 + 1]
1000let f = |x: &[f64]| vec![
1001 x[0] * x[0] + x[1] - 1.0,
1002 x[0] - x[1] * x[1] + 1.0,
1003];"#,
1004 see_also: &["minimize_lbfgs", "minimize_scalar"],
1005 category: ApiCategory::Optimization,
1006 },
1007 ApiEntry {
1008 crate_name: "scirs2-optimize",
1009 module_path: "stochastic::adam",
1010 function_name: "minimize_adam",
1011 signature: "pub fn minimize_adam<F>(f: F, x0: &[f64], learning_rate: f64, max_iter: usize) -> OptimizeResult<OptResult>",
1012 description: "Minimize a function using the Adam optimizer (Adaptive Moment Estimation).",
1013 math_reference: "m_t = beta1 * m_{t-1} + (1-beta1) * g_t (1st moment). \
1014 v_t = beta2 * v_{t-1} + (1-beta2) * g_t^2 (2nd moment). \
1015 x_{t+1} = x_t - lr * m_hat_t / (sqrt(v_hat_t) + eps) \
1016 where hat denotes bias-corrected estimates. Default: beta1=0.9, beta2=0.999.",
1017 example: r#"use scirs2_optimize::stochastic::adam::minimize_adam;
1018
1019let f = |x: &[f64]| x[0].powi(2) + x[1].powi(2);
1020let result = minimize_adam(&f, &[5.0, 5.0], 0.01, 1000)
1021 .expect("Adam failed");"#,
1022 see_also: &["minimize_sgd", "minimize_lbfgs"],
1023 category: ApiCategory::Optimization,
1024 },
1025 ApiEntry {
1026 crate_name: "scirs2-optimize",
1027 module_path: "unconstrained::conjugate_gradient",
1028 function_name: "minimize_conjugate_gradient",
1029 signature: "pub fn minimize_conjugate_gradient<F, G, S>(f: F, grad: G, x0: &[f64], options: S) -> OptimizeResult<OptResult>",
1030 description: "Minimize a function using the nonlinear conjugate gradient method (Fletcher-Reeves or Polak-Ribiere).",
1031 math_reference: "d_k = -g_k + beta_k d_{k-1} where beta_k controls the conjugate direction. \
1032 Fletcher-Reeves: beta_k = ||g_k||^2 / ||g_{k-1}||^2. \
1033 Polak-Ribiere: beta_k = g_k^T (g_k - g_{k-1}) / ||g_{k-1}||^2. \
1034 Convergence: n-step quadratic termination for quadratic objectives.",
1035 example: r#"use scirs2_optimize::unconstrained::conjugate_gradient::minimize_conjugate_gradient;
1036
1037let f = |x: &[f64]| x[0].powi(2) + 2.0 * x[1].powi(2);
1038let grad = |x: &[f64]| vec![2.0 * x[0], 4.0 * x[1]];
1039let result = minimize_conjugate_gradient(&f, &grad, &[5.0, 3.0], ())
1040 .expect("CG failed");"#,
1041 see_also: &["minimize_lbfgs", "minimize_trust_ncg"],
1042 category: ApiCategory::Optimization,
1043 },
1044 ApiEntry {
1048 crate_name: "scirs2-integrate",
1049 module_path: "quad",
1050 function_name: "quad",
1051 signature: "pub fn quad<F, Func>(f: Func, a: F, b: F, opts: QuadOpts<F>) -> IntegrateResult<(F, F)>",
1052 description: "Adaptive numerical integration using Gauss-Kronrod quadrature, returning (result, error_estimate).",
1053 math_reference: "Uses Gauss-Kronrod rule: G_n = sum w_i f(x_i) (n-point Gauss), \
1054 K_{2n+1} = sum w'_i f(x'_i) (2n+1 point Kronrod extension). \
1055 Error estimate: |G_n - K_{2n+1}|. Recursively bisects intervals with large errors. \
1056 Default: G7-K15 (7-point Gauss, 15-point Kronrod).",
1057 example: r#"use scirs2_integrate::quad::quad;
1058
1059// Integrate sin(x) from 0 to pi => result should be 2.0
1060let f = |x: f64| x.sin();
1061let (result, error) = quad(f, 0.0, std::f64::consts::PI, Default::default())
1062 .expect("quad failed");
1063assert!((result - 2.0).abs() < 1e-10);"#,
1064 see_also: &["trapezoid", "simpson", "solve_ivp"],
1065 category: ApiCategory::Integration,
1066 },
1067 ApiEntry {
1068 crate_name: "scirs2-integrate",
1069 module_path: "quad",
1070 function_name: "trapezoid",
1071 signature: "pub fn trapezoid<F, Func>(f: Func, a: F, b: F, n: usize) -> F",
1072 description: "Compute a definite integral using the composite trapezoidal rule with n subintervals.",
1073 math_reference: "integral ~ h * [f(a)/2 + sum_{i=1}^{n-1} f(a + ih) + f(b)/2] where h = (b-a)/n. \
1074 Error: O(h^2) for smooth functions (second-order). \
1075 Exact for piecewise linear functions.",
1076 example: r#"use scirs2_integrate::quad::trapezoid;
1077
1078let f = |x: f64| x * x; // x^2
1079let result = trapezoid(f, 0.0, 1.0, 1000);
1080// integral of x^2 from 0 to 1 = 1/3
1081assert!((result - 1.0 / 3.0).abs() < 1e-5);"#,
1082 see_also: &["simpson", "quad"],
1083 category: ApiCategory::Integration,
1084 },
1085 ApiEntry {
1086 crate_name: "scirs2-integrate",
1087 module_path: "quad",
1088 function_name: "simpson",
1089 signature: "pub fn simpson<F, Func>(f: Func, a: F, b: F, n: usize) -> IntegrateResult<F>",
1090 description: "Compute a definite integral using composite Simpson's 1/3 rule (n must be even).",
1091 math_reference: "integral ~ (h/3) * [f(a) + 4 sum_{odd} f(x_i) + 2 sum_{even} f(x_i) + f(b)] \
1092 where h = (b-a)/n. Error: O(h^4) (fourth-order). \
1093 Exact for polynomials up to degree 3.",
1094 example: r#"use scirs2_integrate::quad::simpson;
1095
1096let f = |x: f64| x.powi(3); // x^3
1097let result = simpson(f, 0.0, 1.0, 100).expect("simpson failed");
1098// integral of x^3 from 0 to 1 = 0.25 (exact for cubic)
1099assert!((result - 0.25).abs() < 1e-12);"#,
1100 see_also: &["trapezoid", "quad"],
1101 category: ApiCategory::Integration,
1102 },
1103 ApiEntry {
1104 crate_name: "scirs2-integrate",
1105 module_path: "ode::solver",
1106 function_name: "solve_ivp",
1107 signature: "pub fn solve_ivp<F, Func>(f: Func, t_span: (F, F), y0: &[F], method: OdeMethod, options: IvpOptions<F>) -> IntegrateResult<OdeSolution<F>>",
1108 description: "Solve an initial value problem for a system of ordinary differential equations.",
1109 math_reference: "dy/dt = f(t, y), y(t0) = y0. \
1110 Methods: RK45 (Dormand-Prince, 4th/5th order adaptive), \
1111 RK23 (Bogacki-Shampine, 2nd/3rd order), \
1112 DOP853 (8th order Runge-Kutta). \
1113 Step size controlled by local error estimate: err < atol + rtol * |y|.",
1114 example: r#"use scirs2_integrate::ode::solver::solve_ivp;
1115
1116// dy/dt = -y, y(0) = 1 => y(t) = exp(-t)
1117let f = |_t: f64, y: &[f64]| vec![-y[0]];
1118let result = solve_ivp(
1119 f, (0.0, 5.0), &[1.0],
1120 Default::default(), Default::default(),
1121).expect("solve_ivp failed");"#,
1122 see_also: &["quad", "trapezoid"],
1123 category: ApiCategory::Integration,
1124 },
1125 ApiEntry {
1126 crate_name: "scirs2-integrate",
1127 module_path: "quadrature::gaussian",
1128 function_name: "quad_gauss_legendre",
1129 signature: "pub fn quad_gauss_legendre<F: Fn(f64) -> f64>(f: F, a: f64, b: f64, n: usize) -> IntegrateResult<f64>",
1130 description: "Numerical integration using Gauss-Legendre quadrature with n nodes.",
1131 math_reference: "integral ~ sum_{i=1}^{n} w_i f(x_i) where x_i are roots of P_n(x) (Legendre polynomial) \
1132 and w_i = 2 / ((1-x_i^2) [P'_n(x_i)]^2). \
1133 Exact for polynomials up to degree 2n-1. \
1134 Transformed to [a, b] via x = (b-a)/2 * t + (a+b)/2.",
1135 example: r#"use scirs2_integrate::quadrature::gaussian::quad_gauss_legendre;
1136
1137let f = |x: f64| x.exp(); // e^x
1138let result = quad_gauss_legendre(f, 0.0, 1.0, 10)
1139 .expect("gauss-legendre failed");
1140// integral of e^x from 0 to 1 = e - 1
1141assert!((result - (std::f64::consts::E - 1.0)).abs() < 1e-12);"#,
1142 see_also: &["quad", "quad_gauss_hermite"],
1143 category: ApiCategory::Integration,
1144 },
1145 ApiEntry {
1149 crate_name: "scirs2-interpolate",
1150 module_path: "spline_modules::api",
1151 function_name: "interp1d_scipy",
1152 signature: "pub fn interp1d_scipy<F: InterpolationFloat>(x: &[F], y: &[F], kind: InterpKind) -> InterpolateResult<Box<dyn Fn(F) -> InterpolateResult<F>>>",
1153 description: "Create a 1-D interpolation function from data points (SciPy-compatible API).",
1154 math_reference: "Linear: y = y_i + (y_{i+1} - y_i) * (x - x_i) / (x_{i+1} - x_i). \
1155 Cubic spline: piecewise cubic polynomials S_i(x) with C2 continuity at knots. \
1156 Solves tridiagonal system for second derivatives.",
1157 example: r#"use scirs2_interpolate::spline_modules::api::interp1d_scipy;
1158
1159let x = vec![0.0, 1.0, 2.0, 3.0, 4.0];
1160let y = vec![0.0, 1.0, 4.0, 9.0, 16.0]; // y = x^2
1161// Create a cubic interpolant"#,
1162 see_also: &["griddata", "rbf_1d"],
1163 category: ApiCategory::Interpolation,
1164 },
1165 ApiEntry {
1166 crate_name: "scirs2-interpolate",
1167 module_path: "griddata",
1168 function_name: "griddata",
1169 signature: "pub fn griddata<F>(points: &[(F, F)], values: &[F], xi: &[(F, F)], method: GridMethod) -> InterpolateResult<Vec<F>>",
1170 description: "Interpolate unstructured 2-D data onto a grid using nearest, linear, or cubic methods.",
1171 math_reference: "Nearest: value at closest data point (Voronoi cell assignment). \
1172 Linear: Delaunay triangulation + barycentric interpolation within triangles. \
1173 Cubic: Clough-Tocher C1 interpolation on Delaunay triangles.",
1174 example: r#"use scirs2_interpolate::griddata::griddata;
1175
1176let points = vec![(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (1.0, 1.0)];
1177let values = vec![0.0, 1.0, 1.0, 2.0];
1178let xi = vec![(0.5, 0.5)]; // query point"#,
1179 see_also: &["interp1d_scipy", "rbf_1d"],
1180 category: ApiCategory::Interpolation,
1181 },
1182 ApiEntry {
1183 crate_name: "scirs2-interpolate",
1184 module_path: "rbf",
1185 function_name: "rbf_1d",
1186 signature: "pub fn rbf_1d(x: &[f64], y: &[f64], kernel: RbfKernel, epsilon: Option<f64>) -> InterpolateResult<RbfInterpolator>",
1187 description: "Create a radial basis function interpolator for scattered 1-D data.",
1188 math_reference: "f(x) = sum_{i=1}^{n} w_i phi(||x - x_i||) where phi is the RBF kernel. \
1189 Kernels: Gaussian phi(r) = exp(-r^2/eps^2), Multiquadric phi(r) = sqrt(1 + (r/eps)^2), \
1190 Thin-plate spline phi(r) = r^2 log(r). Weights w solved via interpolation matrix.",
1191 example: r#"use scirs2_interpolate::rbf::rbf_1d;
1192
1193let x = vec![0.0, 1.0, 2.0, 3.0, 4.0];
1194let y = vec![0.0, 0.8, 1.0, 0.8, 0.0]; // bell-shaped data"#,
1195 see_also: &["interp1d_scipy", "griddata"],
1196 category: ApiCategory::Interpolation,
1197 },
1198 ApiEntry {
1202 crate_name: "scirs2-special",
1203 module_path: "gamma::enhanced",
1204 function_name: "gamma_enhanced",
1205 signature: "pub fn gamma_enhanced<F>(x: F) -> SpecialResult<F>",
1206 description: "Compute the Gamma function with enhanced precision using Lanczos approximation.",
1207 math_reference: "Gamma(x) = integral_0^inf t^{x-1} e^{-t} dt for x > 0. \
1208 Gamma(n) = (n-1)! for positive integers. \
1209 Reflection formula: Gamma(x) Gamma(1-x) = pi / sin(pi x). \
1210 Lanczos approx: Gamma(x+1) ~ sqrt(2 pi) (x + g + 0.5)^{x+0.5} e^{-(x+g+0.5)} sum_k c_k/(x+k).",
1211 example: r#"use scirs2_special::gamma::enhanced::gamma_enhanced;
1212
1213let g5: f64 = gamma_enhanced(5.0).expect("gamma failed");
1214// Gamma(5) = 4! = 24.0
1215assert!((g5 - 24.0).abs() < 1e-10);
1216
1217let g_half: f64 = gamma_enhanced(0.5).expect("gamma failed");
1218// Gamma(0.5) = sqrt(pi)
1219assert!((g_half - std::f64::consts::PI.sqrt()).abs() < 1e-10);"#,
1220 see_also: &["gammaln_enhanced", "gammainc", "erf"],
1221 category: ApiCategory::SpecialFunction,
1222 },
1223 ApiEntry {
1224 crate_name: "scirs2-special",
1225 module_path: "gamma::enhanced",
1226 function_name: "gammaln_enhanced",
1227 signature: "pub fn gammaln_enhanced<F>(x: F) -> SpecialResult<F>",
1228 description: "Compute the natural logarithm of the Gamma function (avoids overflow for large arguments).",
1229 math_reference: "lgamma(x) = ln(|Gamma(x)|). \
1230 For large x: lgamma(x) ~ x ln(x) - x - 0.5 ln(x) + 0.5 ln(2 pi) + Stirling corrections. \
1231 Essential for computing log-likelihoods with large factorials.",
1232 example: r#"use scirs2_special::gamma::enhanced::gammaln_enhanced;
1233
1234let lg: f64 = gammaln_enhanced(100.0).expect("gammaln failed");
1235// ln(99!) ~ 363.739
1236assert!((lg - 363.73937555556347).abs() < 1e-6);"#,
1237 see_also: &["gamma_enhanced", "gammainc"],
1238 category: ApiCategory::SpecialFunction,
1239 },
1240 ApiEntry {
1241 crate_name: "scirs2-special",
1242 module_path: "incomplete_gamma",
1243 function_name: "gammainc",
1244 signature: "pub fn gammainc<T>(a: T, x: T) -> SpecialResult<T>",
1245 description: "Compute the regularized lower incomplete gamma function P(a, x).",
1246 math_reference: "P(a, x) = gamma(a, x) / Gamma(a) = (1/Gamma(a)) integral_0^x t^{a-1} e^{-t} dt. \
1247 Range: [0, 1]. P(a, x) + Q(a, x) = 1 where Q is the upper incomplete gamma. \
1248 Computed via series expansion for x < a+1, continued fraction otherwise.",
1249 example: r#"use scirs2_special::incomplete_gamma::gammainc;
1250
1251let p: f64 = gammainc(1.0, 1.0).expect("gammainc failed");
1252// P(1, 1) = 1 - exp(-1) ~ 0.6321
1253assert!((p - (1.0 - (-1.0_f64).exp())).abs() < 1e-10);"#,
1254 see_also: &["gammaincc", "gamma_enhanced"],
1255 category: ApiCategory::SpecialFunction,
1256 },
1257 ApiEntry {
1258 crate_name: "scirs2-special",
1259 module_path: "optimizations",
1260 function_name: "bessel_j0_fast",
1261 signature: "pub fn bessel_j0_fast(x: f64) -> f64",
1262 description: "Compute the Bessel function of the first kind J_0(x) using fast polynomial approximation.",
1263 math_reference: "J_0(x) = (1/pi) integral_0^pi cos(x sin(t)) dt. \
1264 For small x: J_0(x) = sum_{k=0}^inf (-1)^k (x/2)^{2k} / (k!)^2. \
1265 For large x: J_0(x) ~ sqrt(2/(pi x)) cos(x - pi/4). \
1266 J_0(0) = 1, J_0 has infinitely many zeros.",
1267 example: r#"use scirs2_special::optimizations::bessel_j0_fast;
1268
1269let j0 = bessel_j0_fast(0.0);
1270assert!((j0 - 1.0).abs() < 1e-10); // J_0(0) = 1
1271
1272let j0_at_1 = bessel_j0_fast(1.0);
1273// J_0(1) ~ 0.7652
1274assert!((j0_at_1 - 0.7651976865579666).abs() < 1e-4);"#,
1275 see_also: &["gamma_enhanced", "gammainc"],
1276 category: ApiCategory::SpecialFunction,
1277 },
1278];