# Architecture
How datarust is organized and the design decisions behind it.
## Design philosophy
1. **Zero external dependencies by default.** `cargo add datarust` pulls in nothing. All linear algebra — Jacobi eigendecomposition, one-sided Jacobi SVD, Cholesky factorization, coordinate descent, IRLS — is pure Rust. Feature flags (`serde`, `rayon`, `matrixmultiply`) opt in to extras.
2. **sklearn-inspired but Rust-native.** The familiar `fit`/`transform`/`predict` API, but using `Result` (panic-free), builder-pattern config, and enum-based parameters (`Norm::L2`, `ImputeStrategy::Median`) instead of strings.
3. **Type-safe modality separation.** Four traits enforce that numeric, categorical, target, and label data go to the right transformer. The compiler catches misuse.
4. **Composability via type-erased enums.** `TransformerKind`, `CategoricalTransformerKind`, and `TargetTransformerKind` allow heterogeneous pipelines that are still serializable.
## Module layout
```
src/
├── lib.rs # Crate root: re-exports + module declarations
├── error.rs # DatarustError enum + Result alias
├── traits.rs # Estimator, Predictor, Regressor, Classifier, transformers, FeatureNames
├── matrix.rs # Matrix (f64 flat), StrMatrix, SparseMatrix (CSR)
├── stats.rs # Column statistics, covariance/correlation
├── pipeline.rs # Sequential and supervised Pipeline
├── transformer_kind.rs # TransformerKind enum (type erasure)
├── categorical_kind.rs # CategoricalTransformerKind enum
├── target_kind.rs # TargetTransformerKind enum
├── function_transformer.rs
├── polynomial.rs # PolynomialFeatures
├── serialize.rs # JSON save/load (serde feature)
├── linalg/
│ └── cholesky.rs # Cholesky decomposition + SPD solver
├── scaler/ # 9 transformers (standard, minmax, robust, ...)
├── encoder/ # 5 encoders (onehot, ordinal, label, target, frequency)
├── imputer/ # SimpleImputer, KnnImputer
├── selection/ # VarianceThreshold, SelectKBest
├── decomposition/ # PCA, TruncatedSVD, Jacobi, randomized_svd
├── linear_model/ # LinearRegression, Ridge, Lasso, LogisticRegression
├── metrics/
│ ├── regression.rs # MSE, MAE, R², max_error, explained_variance
│ └── classification.rs # accuracy, precision, recall, F1, confusion_matrix, log_loss
├── model_selection/
│ ├── split.rs # train_test_split
│ ├── kfold.rs # KFold, StratifiedKFold
│ ├── cross_val.rs # cross_val_score
│ └── rng.rs # shared xorshift64 PRNG
└── compose/
├── column_transformer.rs
└── output.rs
```
## Trait hierarchy
| `Transformer` | `Matrix → Matrix` | all scalers, PCA, TruncatedSVD, PolynomialFeatures, VarianceThreshold, SelectKBest, imputers, FunctionTransformer |
| `Predictor` | `fit(X, y)` + `predict(X) → Vec<f64>` | all linear models and supervised pipelines |
| `Regressor` | continuous-prediction semantics | LinearRegression, Ridge, Lasso |
| `Classifier` | class-label prediction semantics | LogisticRegression |
| `CategoricalTransformer` | `StrMatrix → Matrix` | OneHotEncoder, OrdinalEncoder, FrequencyEncoder |
| `TargetTransformer` | `fit(StrMatrix, y)` | TargetEncoder |
| `LabelTransformer` | `&[String] ↔ Vec<usize>` | LabelEncoder |
| `FeatureNames` | output column names | every output-producing transformer |
## Solver infrastructure
Three distinct solver families, all pure-Rust, in `linalg/`:
1. **Cholesky** (`linalg::cholesky`) — symmetric positive-definite system solver. Used by `LinearRegression`, `Ridge`, and `LogisticRegression` (per IRLS iteration).
2. **Coordinate descent** (`Lasso`) — soft-thresholding iteration for L1-regularized problems.
3. **IRLS** (`LogisticRegression`) — Newton-Raphson on the logistic loss, solving a weighted least-squares system each iteration.
All three are backed by the shared `Matrix::matmul` for forming Gram matrices, which dispatches to a tuned GEMM under the `matrixmultiply` feature.
## Error handling
Hand-rolled `DatarustError` enum (no `anyhow`/`thiserror`, consistent with the zero-dependency ethos). Every fallible public API returns `Result<T, DatarustError>`. The variant set is ML-domain-specific (`NotFitted`, `UnknownCategory`, `Singular`, etc.), more informative than a generic error blob.