Skip to main content

scirs2_core/api_reference/
catalog.rs

1//! Programmatic API catalog for the SciRS2 ecosystem.
2//!
3//! Each [`ApiEntry`] documents a public API with its signature, mathematical background,
4//! usage example, and cross-references to related functions.
5
6/// Category of a public API entry.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum ApiCategory {
10    /// Linear algebra operations (det, inv, solve, norms)
11    LinearAlgebra,
12    /// Matrix decompositions (LU, QR, SVD, Cholesky, eigendecomposition)
13    Decomposition,
14    /// Descriptive and inferential statistics
15    Statistics,
16    /// Probability distributions (Normal, Beta, Gamma, etc.)
17    Distribution,
18    /// Hypothesis testing (t-test, chi-square, etc.)
19    HypothesisTest,
20    /// Signal processing (filters, spectral analysis)
21    SignalProcessing,
22    /// Fast Fourier Transform and related
23    FFT,
24    /// Numerical optimization (minimization, root-finding)
25    Optimization,
26    /// Numerical integration and ODE solvers
27    Integration,
28    /// Interpolation and curve fitting
29    Interpolation,
30    /// Special mathematical functions (gamma, erf, Bessel)
31    SpecialFunction,
32    /// Sparse matrix operations
33    Sparse,
34    /// Image processing and computer vision
35    ImageProcessing,
36    /// Machine learning and neural networks
37    MachineLearning,
38    /// Time series analysis and forecasting
39    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            // Future categories added via #[non_exhaustive]
61            #[allow(unreachable_patterns)]
62            _ => write!(f, "Other"),
63        }
64    }
65}
66
67/// A documented API entry with mathematical background and usage example.
68#[derive(Debug, Clone)]
69pub struct ApiEntry {
70    /// Crate that provides this API (e.g. "scirs2-linalg")
71    pub crate_name: &'static str,
72    /// Module path within the crate (e.g. "decomposition")
73    pub module_path: &'static str,
74    /// Function or type name (e.g. "svd")
75    pub function_name: &'static str,
76    /// Rust signature (e.g. `pub fn svd<F>(...) -> LinalgResult<...>`)
77    pub signature: &'static str,
78    /// Human-readable description
79    pub description: &'static str,
80    /// Mathematical formula or reference in plain text
81    pub math_reference: &'static str,
82    /// Complete Rust code example (syntactically correct)
83    pub example: &'static str,
84    /// Related API names for cross-reference
85    pub see_also: &'static [&'static str],
86    /// API category
87    pub category: ApiCategory,
88}
89
90/// Returns the full static API catalog.
91pub fn api_catalog() -> &'static [ApiEntry] {
92    &API_CATALOG
93}
94
95/// Search the catalog by query string (case-insensitive substring match
96/// against function name, description, and module path).
97pub 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
110/// Filter catalog entries by crate name (case-insensitive).
111pub 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
119/// Filter catalog entries by category.
120pub fn by_category(cat: ApiCategory) -> Vec<&'static ApiEntry> {
121    API_CATALOG.iter().filter(|e| e.category == cat).collect()
122}
123
124// ---------------------------------------------------------------------------
125// Static catalog
126// ---------------------------------------------------------------------------
127
128static API_CATALOG: [ApiEntry; 60] = [
129    // ======================================================================
130    // LINEAR ALGEBRA (indices 0-4)
131    // ======================================================================
132    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    // ======================================================================
226    // DECOMPOSITION (indices 5-14)
227    // ======================================================================
228    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    // ======================================================================
403    // STATISTICS (indices 15-19)
404    // ======================================================================
405    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    // ======================================================================
495    // DISTRIBUTIONS (indices 20-24)
496    // ======================================================================
497    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    // ======================================================================
587    // HYPOTHESIS TESTS (indices 25-28)
588    // ======================================================================
589    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    // ======================================================================
667    // SIGNAL PROCESSING (indices 29-36)
668    // ======================================================================
669    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    // ======================================================================
824    // FFT (indices 37-41)
825    // ======================================================================
826    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    // ======================================================================
921    // OPTIMIZATION (indices 42-47)
922    // ======================================================================
923    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    // ======================================================================
1045    // INTEGRATION (indices 48-52)
1046    // ======================================================================
1047    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    // ======================================================================
1146    // INTERPOLATION (indices 53-55)
1147    // ======================================================================
1148    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    // ======================================================================
1199    // SPECIAL FUNCTIONS (indices 56-59)
1200    // ======================================================================
1201    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];