linreg_core/lib.rs
1//! # linreg-core
2//!
3//! A lightweight, self-contained linear regression library in pure Rust.
4//!
5//! **No external math dependencies.** All linear algebra (matrices, QR decomposition)
6//! and statistical functions (distributions, hypothesis tests) are implemented from
7//! scratch. Compiles to WebAssembly for browser use or runs as a native Rust crate.
8//!
9//! **[Live Demo →](https://jesse-anderson.net/linreg-core/)**
10//!
11//! ## What This Does
12//!
13//! - **OLS Regression** — Ordinary Least Squares with numerically stable QR decomposition
14//! - **Regularized Regression** — Ridge, Lasso, and Elastic Net via coordinate descent
15//! - **Diagnostic Tests** — 8+ statistical tests for validating regression assumptions
16//! - **WASM Support** — Same API works in browsers via WebAssembly
17//!
18//! ## Quick Start
19//!
20//! ### Native Rust
21//!
22//! Add to `Cargo.toml` (no WASM overhead):
23//!
24//! ```toml
25//! [dependencies]
26//! linreg-core = { version = "0.6", default-features = false }
27//! ```
28//!
29//! ```rust
30//! use linreg_core::core::ols_regression;
31//!
32//! let y = vec![2.5, 3.7, 4.2, 5.1, 6.3];
33//! let x1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
34//! let x2 = vec![2.0, 4.0, 5.0, 4.0, 3.0];
35//! let names = vec!["Intercept".into(), "Temp".into(), "Pressure".into()];
36//!
37//! let result = ols_regression(&y, &[x1, x2], &names)?;
38//! println!("R²: {}", result.r_squared);
39//! println!("F-statistic: {}", result.f_statistic);
40//! # Ok::<(), linreg_core::Error>(())
41//! ```
42//!
43//! ### WebAssembly (JavaScript)
44//!
45//! ```toml
46//! [dependencies]
47//! linreg-core = "0.6"
48//! ```
49//!
50//! Build with `wasm-pack build --target web`, then use in JavaScript:
51//!
52//! ```text
53//! import init, { ols_regression } from './linreg_core.js';
54//! await init();
55//!
56//! const result = JSON.parse(ols_regression(
57//! JSON.stringify([2.5, 3.7, 4.2, 5.1, 6.3]),
58//! JSON.stringify([[1,2,3,4,5], [2,4,5,4,3]]),
59//! JSON.stringify(["Intercept", "X1", "X2"])
60//! ));
61//! console.log("R²:", result.r_squared);
62//! ```
63//!
64//! ## Regularized Regression
65//!
66//! ```no_run
67//! use linreg_core::regularized::{ridge, lasso};
68//! use linreg_core::linalg::Matrix;
69//!
70//! let x = Matrix::new(100, 3, vec![0.0; 300]);
71//! let y = vec![0.0; 100];
72//!
73//! // Ridge regression (L2 penalty - shrinks coefficients, handles multicollinearity)
74//! let ridge_result = ridge::ridge_fit(&x, &y, &ridge::RidgeFitOptions {
75//! lambda: 1.0,
76//! intercept: true,
77//! standardize: true,
78//! ..Default::default()
79//! })?;
80//!
81//! // Lasso regression (L1 penalty - does variable selection by zeroing coefficients)
82//! let lasso_result = lasso::lasso_fit(&x, &y, &lasso::LassoFitOptions {
83//! lambda: 0.1,
84//! intercept: true,
85//! standardize: true,
86//! ..Default::default()
87//! })?;
88//! # Ok::<(), linreg_core::Error>(())
89//! ```
90//!
91//! ## Diagnostic Tests
92//!
93//! After fitting a model, validate its assumptions:
94//!
95//! | Test | Tests For | Use When |
96//! |------|-----------|----------|
97//! | [`diagnostics::rainbow_test`] | Linearity | Checking if relationships are linear |
98//! | [`diagnostics::harvey_collier_test`] | Functional form | Suspecting model misspecification |
99//! | [`diagnostics::breusch_pagan_test`] | Heteroscedasticity | Variance changes with predictors |
100//! | [`diagnostics::white_test`] | Heteroscedasticity | More general than Breusch-Pagan |
101//! | [`diagnostics::shapiro_wilk_test`] | Normality | Small to moderate samples (n ≤ 5000) |
102//! | [`diagnostics::jarque_bera_test`] | Normality | Large samples, skewness/kurtosis |
103//! | [`diagnostics::anderson_darling_test`] | Normality | Tail-sensitive, any sample size |
104//! | [`diagnostics::durbin_watson_test`] | Autocorrelation | Time series or ordered data |
105//! | [`diagnostics::cooks_distance_test`] | Influential points | Identifying high-impact observations |
106//!
107//! ```rust
108//! use linreg_core::diagnostics::{rainbow_test, breusch_pagan_test, RainbowMethod};
109//!
110//! # let y = vec![2.5, 3.7, 4.2, 5.1, 6.3];
111//! # let x1 = vec![1.0, 2.0, 3.0, 4.0, 5.0];
112//! # let x2 = vec![2.0, 4.0, 5.0, 4.0, 3.0];
113//! // Rainbow test for linearity
114//! let rainbow = rainbow_test(&y, &[x1.clone(), x2.clone()], 0.5, RainbowMethod::R)?;
115//! if rainbow.r_result.as_ref().map_or(false, |r| r.p_value < 0.05) {
116//! println!("Warning: relationship may be non-linear");
117//! }
118//!
119//! // Breusch-Pagan test for heteroscedasticity
120//! let bp = breusch_pagan_test(&y, &[x1, x2])?;
121//! if bp.p_value < 0.05 {
122//! println!("Warning: residuals have non-constant variance");
123//! }
124//! # Ok::<(), linreg_core::Error>(())
125//! ```
126//!
127//! ## Feature Flags
128//!
129//! | Flag | Default | Description |
130//! |------|---------|-------------|
131//! | `wasm` | Yes | Enables WASM bindings and browser support |
132//! | `validation` | No | Includes test data for validation tests |
133//!
134//! For native-only builds (smaller binary, no WASM deps):
135//!
136//! ```toml
137//! linreg-core = { version = "0.6", default-features = false }
138//! ```
139//!
140//! ## Why This Library?
141//!
142//! - **Zero dependencies** — No `nalgebra`, no `statrs`, no `ndarray`. Pure Rust.
143//! - **Validated** — Outputs match R's `lm()` and Python's `statsmodels`
144//! - **WASM-ready** — Same code runs natively and in browsers
145//! - **Small** — Core is ~2000 lines, compiles quickly
146//! - **Permissive license** — MIT OR Apache-2.0
147//!
148//! ## Module Structure
149//!
150//! - [`core`] — OLS regression, coefficients, residuals, VIF
151//! - [`regularized`] — Ridge, Lasso, Elastic Net, regularization paths
152//! - [`cross_validation`] — K-Fold Cross Validation for model evaluation
153//! - [`diagnostics`] — All diagnostic tests (linearity, heteroscedasticity, normality, autocorrelation)
154//! - [`distributions`] — Statistical distributions (t, F, χ², normal, beta, gamma)
155//! - [`linalg`] — Matrix operations, QR decomposition, linear system solver
156//! - [`error`] — Error types and Result alias
157//!
158//! ## Links
159//!
160//! - [Repository](https://github.com/jesse-anderson/linreg-core)
161//! - [Documentation](https://docs.rs/linreg-core)
162//! - [Examples](https://github.com/jesse-anderson/linreg-core/tree/main/examples)
163//!
164//! ## Disclaimer
165//!
166//! This library is under active development and has not reached 1.0 stability.
167//! While outputs are validated against R and Python implementations, **do not
168//! use this library for critical applications** (medical, financial, safety-critical
169//! systems) without independent verification. See the LICENSE for full terms.
170//! The software is provided "as is" without warranty of any kind.
171
172// Import core modules (always available)
173pub mod core;
174pub mod cross_validation;
175pub mod diagnostics;
176pub mod distributions;
177pub mod error;
178pub mod linalg;
179pub mod loess;
180pub mod regularized;
181pub mod serialization;
182pub mod stats;
183pub mod weighted_regression;
184
185// Python bindings (only compiled when "python" feature is enabled)
186// Module structure: src/python/ with mod.rs, error.rs, types.rs, results.rs
187#[cfg(feature = "python")]
188pub mod python;
189
190// WASM bindings (only compiled when "wasm" feature is enabled)
191// Module structure: src/wasm.rs - contains all wasm-bindgen exports
192#[cfg(feature = "wasm")]
193pub mod wasm;
194
195// Unit tests are now in tests/unit/ directory
196// - error_tests.rs -> tests/unit/error_tests.rs
197// - core_tests.rs -> tests/unit/core_tests.rs
198// - linalg_tests.rs -> tests/unit/linalg_tests.rs
199// - validation_tests.rs -> tests/validation/main.rs
200// - diagnostics_tests.rs: disabled (references unimplemented functions)
201
202// Re-export public API (always available)
203pub use core::{aic, aic_python, bic, bic_python, log_likelihood, RegressionOutput, VifResult};
204pub use diagnostics::{
205 BGTestType, BreuschGodfreyResult, CooksDistanceResult, DiagnosticTestResult,
206 RainbowMethod, RainbowSingleResult, RainbowTestOutput, ResetType,
207 WhiteMethod, WhiteSingleResult, WhiteTestOutput,
208};
209pub use cross_validation::{
210 CVResult, FoldResult, KFoldOptions, kfold_cv_elastic_net, kfold_cv_lasso, kfold_cv_ols,
211 kfold_cv_ridge,
212};
213pub use loess::{loess_fit, LoessFit, LoessOptions};
214pub use weighted_regression::{wls_regression, WlsFit};
215
216// Re-export core test functions with different names to avoid WASM conflicts
217pub use diagnostics::rainbow_test as rainbow_test_core;
218pub use diagnostics::white_test as white_test_core;
219
220pub use error::{error_json, error_to_json, Error, Result};