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