@compstats/core 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/README.md +127 -110
- package/dist/3d.js +1120 -122
- package/dist/3d.js.map +16 -9
- package/dist/core/arith.d.ts.map +1 -1
- package/dist/core/linalg/cov.d.ts +50 -0
- package/dist/core/linalg/cov.d.ts.map +1 -0
- package/dist/core/linalg/eigen.d.ts +53 -0
- package/dist/core/linalg/eigen.d.ts.map +1 -0
- package/dist/core/linalg/lm.d.ts +78 -0
- package/dist/core/linalg/lm.d.ts.map +1 -0
- package/dist/core/linalg/lu.d.ts +154 -0
- package/dist/core/linalg/lu.d.ts.map +1 -0
- package/dist/core/linalg/matrix.d.ts +131 -0
- package/dist/core/linalg/matrix.d.ts.map +1 -0
- package/dist/core/linalg/modelMatrix.d.ts +69 -0
- package/dist/core/linalg/modelMatrix.d.ts.map +1 -0
- package/dist/core/linalg/namedVector.d.ts +37 -0
- package/dist/core/linalg/namedVector.d.ts.map +1 -0
- package/dist/core/linalg/ops.d.ts +120 -0
- package/dist/core/linalg/ops.d.ts.map +1 -0
- package/dist/core/linalg/prcomp.d.ts +66 -0
- package/dist/core/linalg/prcomp.d.ts.map +1 -0
- package/dist/core/linalg/qr.d.ts +134 -0
- package/dist/core/linalg/qr.d.ts.map +1 -0
- package/dist/core/linalg/vector.d.ts +68 -0
- package/dist/core/linalg/vector.d.ts.map +1 -0
- package/dist/core/moderation.d.ts +6 -3
- package/dist/core/moderation.d.ts.map +1 -1
- package/dist/core/ols.d.ts +4 -7
- package/dist/core/ols.d.ts.map +1 -1
- package/dist/data/moderationData.d.ts +2 -2
- package/dist/data/pcaDegenerate.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1601 -863
- package/dist/index.js.map +17 -11
- package/dist/linalg.d.ts +36 -0
- package/dist/linalg.d.ts.map +1 -0
- package/dist/linalg.js +1860 -0
- package/dist/linalg.js.map +24 -0
- package/dist/plot/moderation3d.d.ts +1 -1
- package/dist/plot/sampling.d.ts +45 -0
- package/dist/plot/sampling.d.ts.map +1 -1
- package/dist/plot/scatter3d.d.ts +1 -1
- package/package.json +16 -5
package/dist/core/arith.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arith.d.ts","sourceRoot":"","sources":["../../src/core/arith.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mDAAmD;AACnD,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAErD;AAED,iEAAiE;AACjE,wBAAgB,IAAI,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7B,EAAE,EAAE,SAAS,CAAC,EAAE,EAChB,EAAE,EAAE,SAAS,CAAC,EAAE,EAChB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GACzB,CAAC,EAAE,CAIL;AAED;;;;;;GAMG;AACH,wBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAQpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"arith.d.ts","sourceRoot":"","sources":["../../src/core/arith.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mDAAmD;AACnD,wBAAgB,GAAG,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAErD;AAED,iEAAiE;AACjE,wBAAgB,IAAI,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAQlE;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,yDAAyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7B,EAAE,EAAE,SAAS,CAAC,EAAE,EAChB,EAAE,EAAE,SAAS,CAAC,EAAE,EAChB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GACzB,CAAC,EAAE,CAIL;AAED;;;;;;GAMG;AACH,wBAAgB,EAAE,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAQpD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAUxE;AA0BD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,EAAE,CAaV;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R's `var()`, `cov()` and `cor()`.
|
|
3
|
+
*
|
|
4
|
+
* R computes a covariance in two passes: the mean of each column, refined
|
|
5
|
+
* once by adding the mean of the residuals (its `cov.c` does this to shave
|
|
6
|
+
* the rounding off a long sum), then the sum of products of deviations over
|
|
7
|
+
* `n − 1`. A correlation is the covariance matrix scaled by the square roots
|
|
8
|
+
* of its diagonal, clamped to `[-1, 1]`, with an exact 1 on the diagonal.
|
|
9
|
+
* The port follows those steps. R accumulates in `long double` where the
|
|
10
|
+
* platform has one; the conformance fixtures come from arm64, where it does
|
|
11
|
+
* not, and the values are verified at a relative tolerance (plan Q1).
|
|
12
|
+
*
|
|
13
|
+
* A missing value gives NaN, as R's default `use = "everything"` gives NA.
|
|
14
|
+
* A constant column gives NaN for its correlations, where R warns "the
|
|
15
|
+
* standard deviation is zero" and gives NA.
|
|
16
|
+
*/
|
|
17
|
+
import { type Matrix } from "./matrix";
|
|
18
|
+
import type { Vector } from "./vector";
|
|
19
|
+
/**
|
|
20
|
+
* R's `var(x)` of a vector: the sample variance with the `n − 1` divisor.
|
|
21
|
+
*
|
|
22
|
+
* @returns The variance, or NaN below two values or with a missing value.
|
|
23
|
+
*/
|
|
24
|
+
export declare function variance(a: Vector): number;
|
|
25
|
+
/**
|
|
26
|
+
* R's `cov()`: the covariance of two vectors, or the covariance matrix of
|
|
27
|
+
* the columns of a matrix.
|
|
28
|
+
*
|
|
29
|
+
* @param x A vector, or a matrix whose columns are the variables.
|
|
30
|
+
* @param y The second vector when `x` is a vector.
|
|
31
|
+
* @returns The covariance, or the symmetric covariance matrix with the
|
|
32
|
+
* column names of `x` on both sides.
|
|
33
|
+
* @throws RangeError If two vectors differ in length.
|
|
34
|
+
*/
|
|
35
|
+
export declare function cov(x: Vector, y: Vector): number;
|
|
36
|
+
export declare function cov(x: Matrix): Matrix;
|
|
37
|
+
/**
|
|
38
|
+
* R's `cor()`: the Pearson correlation of two vectors, or the correlation
|
|
39
|
+
* matrix of the columns of a matrix.
|
|
40
|
+
*
|
|
41
|
+
* @param x A vector, or a matrix whose columns are the variables.
|
|
42
|
+
* @param y The second vector when `x` is a vector.
|
|
43
|
+
* @returns The correlation, clamped to `[-1, 1]`, or the symmetric
|
|
44
|
+
* correlation matrix with an exact 1 on its diagonal. NaN where a
|
|
45
|
+
* variable has no spread.
|
|
46
|
+
* @throws RangeError If two vectors differ in length.
|
|
47
|
+
*/
|
|
48
|
+
export declare function cor(x: Vector, y: Vector): number;
|
|
49
|
+
export declare function cor(x: Matrix): Matrix;
|
|
50
|
+
//# sourceMappingURL=cov.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cov.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/cov.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAwCvC;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;AAClD,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;AAYvC;;;;;;;;;;GAUG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;AAClD,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The eigendecomposition of a symmetric matrix, R's
|
|
3
|
+
* `eigen(x, symmetric = TRUE)`.
|
|
4
|
+
*
|
|
5
|
+
* R goes through LAPACK's `dsyevr`. The port uses cyclic Jacobi rotations,
|
|
6
|
+
* which for the matrices a teaching library sees — a covariance of a handful
|
|
7
|
+
* of variables — converge to machine precision in a few sweeps and are
|
|
8
|
+
* short enough to read. Eigenvalues come back descending, as R's do, and
|
|
9
|
+
* the eigenvectors are orthonormal columns. Verified against R in
|
|
10
|
+
* `eigen.test.ts`: the eigenvalues to a relative `1e-12`, the vectors up to
|
|
11
|
+
* sign (plan Q1).
|
|
12
|
+
*
|
|
13
|
+
* **Signs are this port's own.** LAPACK leaves the sign of each eigenvector
|
|
14
|
+
* to the arithmetic; the port makes the entry of largest magnitude positive
|
|
15
|
+
* (a tie goes to the first), which is the rule `pca.ts` already uses, so
|
|
16
|
+
* that the same input gives the same picture every time.
|
|
17
|
+
*
|
|
18
|
+
* Two departures from R, both stated: a matrix that is not symmetric is
|
|
19
|
+
* refused, where R silently reads its lower triangle; and the eigenvector
|
|
20
|
+
* matrix carries the row names of the input as its row names, where R's
|
|
21
|
+
* carries none — a loading without its variable is unreadable. The refusals
|
|
22
|
+
* R does make are followed in its order and its words: a non-square matrix,
|
|
23
|
+
* then a 0 x 0 one, then a missing or infinite entry (fixture 5e).
|
|
24
|
+
*
|
|
25
|
+
* Index loops throughout: a rotation addresses entries by position.
|
|
26
|
+
*/
|
|
27
|
+
import { type Matrix } from "./matrix";
|
|
28
|
+
import type { Vector } from "./vector";
|
|
29
|
+
/** R's `eigen()` result for a symmetric matrix. */
|
|
30
|
+
export interface SymmetricEigen {
|
|
31
|
+
/** The eigenvalues, largest first. */
|
|
32
|
+
readonly values: Vector;
|
|
33
|
+
/**
|
|
34
|
+
* The eigenvectors as columns, in the order of the values, each of unit
|
|
35
|
+
* length with its largest entry positive. Row names are the input's.
|
|
36
|
+
*/
|
|
37
|
+
readonly vectors: Matrix;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* R's `isSymmetric()`: whether a square matrix equals its transpose to a
|
|
41
|
+
* relative tolerance, R's `all.equal()` default of `100 * eps`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function isSymmetric(m: Matrix, tolerance?: number): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Decompose a symmetric matrix, as R's `eigen(x, symmetric = TRUE)` does.
|
|
46
|
+
*
|
|
47
|
+
* @param m The symmetric matrix. The function does not modify it.
|
|
48
|
+
* @returns The eigenvalues, descending, and the eigenvectors as columns.
|
|
49
|
+
* @throws RangeError If the matrix is not square, is 0 x 0, holds a missing
|
|
50
|
+
* or infinite entry, or is not symmetric.
|
|
51
|
+
*/
|
|
52
|
+
export declare function eigenSymmetric(m: Matrix): SymmetricEigen;
|
|
53
|
+
//# sourceMappingURL=eigen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eigen.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/eigen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,SAAuB,GAAG,OAAO,CAehF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,cAAc,CA0CxD"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R's `lm()` over a data frame, with what `summary.lm()` reads off the fit.
|
|
3
|
+
*
|
|
4
|
+
* `lm()` is `model.matrix()` followed by `lm.fit()`, and `lm.fit()` is
|
|
5
|
+
* `dqrls`: the `qr()` of `qr.ts` — LINPACK's `dqrdc2` with its limited
|
|
6
|
+
* column pivoting — followed by `dqrsl`'s coefficients and residuals, with
|
|
7
|
+
* the fitted values as `y` minus the residuals. The port runs that same
|
|
8
|
+
* arithmetic, so the coefficients, fitted values and residuals pin bit for
|
|
9
|
+
* bit against R. The summary statistics — R², adjusted R², σ, the standard
|
|
10
|
+
* errors and the t and p values — follow `summary.lm()`'s formulas but not
|
|
11
|
+
* its rounding step for step (`chol2inv` and `pt`), and are verified at a
|
|
12
|
+
* stated tolerance. See `lm.test.ts`.
|
|
13
|
+
*
|
|
14
|
+
* Coefficients come back as a `NamedVector` in R's order, `null` where R
|
|
15
|
+
* reports `NA` for an aliased column. Fitted values and residuals are padded
|
|
16
|
+
* with NaN to the input length where a row was dropped for a missing value,
|
|
17
|
+
* R's `na.exclude`, which is the convention every fit in this package uses.
|
|
18
|
+
*/
|
|
19
|
+
import type { DataFrame } from "../frame";
|
|
20
|
+
import { type ModelSpec } from "./modelMatrix";
|
|
21
|
+
import { type NamedVector } from "./namedVector";
|
|
22
|
+
import type { Vector } from "./vector";
|
|
23
|
+
/** The model, with the outcome required, and the rank tolerance. */
|
|
24
|
+
export interface LmOptions extends ModelSpec {
|
|
25
|
+
/** The column to fit. */
|
|
26
|
+
readonly outcome: string;
|
|
27
|
+
/** How far a column's norm may collapse before it is aliased. R's `lm.fit()` default. */
|
|
28
|
+
readonly tolerance?: number;
|
|
29
|
+
}
|
|
30
|
+
/** R's `summary(fit)$fstatistic`. */
|
|
31
|
+
export interface FStatistic {
|
|
32
|
+
readonly value: number;
|
|
33
|
+
readonly numdf: number;
|
|
34
|
+
readonly dendf: number;
|
|
35
|
+
}
|
|
36
|
+
/** A fitted linear model and its summary. */
|
|
37
|
+
export interface LmFit {
|
|
38
|
+
/** `coef(fit)`: one entry per design column, null where R reports `NA`. */
|
|
39
|
+
readonly coefficients: NamedVector;
|
|
40
|
+
/** `coef(summary(fit))[, "Std. Error"]`, null for an aliased term. */
|
|
41
|
+
readonly standardErrors: NamedVector;
|
|
42
|
+
/** `coef(summary(fit))[, "t value"]`, null for an aliased term. */
|
|
43
|
+
readonly tValues: NamedVector;
|
|
44
|
+
/** `coef(summary(fit))[, "Pr(>|t|)"]`, null for an aliased term. */
|
|
45
|
+
readonly pValues: NamedVector;
|
|
46
|
+
/** The fitted outcome of each data row, in input order; NaN for a row dropped. */
|
|
47
|
+
readonly fitted: Vector;
|
|
48
|
+
/** The outcome minus the fit, in input order; NaN for a row dropped. */
|
|
49
|
+
readonly residuals: Vector;
|
|
50
|
+
/** The number of columns the fit could identify. */
|
|
51
|
+
readonly rank: number;
|
|
52
|
+
/** `fit$df.residual`: rows fitted minus rank. */
|
|
53
|
+
readonly dfResidual: number;
|
|
54
|
+
/** `summary(fit)$r.squared`. */
|
|
55
|
+
readonly rSquared: number;
|
|
56
|
+
/** `summary(fit)$adj.r.squared`. */
|
|
57
|
+
readonly adjRSquared: number;
|
|
58
|
+
/** `summary(fit)$sigma`: the residual standard error. */
|
|
59
|
+
readonly sigma: number;
|
|
60
|
+
/** `summary(fit)$fstatistic`, or null when the model has no term beyond the intercept. */
|
|
61
|
+
readonly fStatistic: FStatistic | null;
|
|
62
|
+
/** The data rows the fit used, in input order. */
|
|
63
|
+
readonly rows: readonly number[];
|
|
64
|
+
/** R's `term.labels`. */
|
|
65
|
+
readonly termLabels: readonly string[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Fit a linear model, as R's `lm()` does.
|
|
69
|
+
*
|
|
70
|
+
* @param data The frame holding every column the model names.
|
|
71
|
+
* @param options The outcome, the terms, the intercept flag, and the rank
|
|
72
|
+
* tolerance.
|
|
73
|
+
* @returns The fit and its summary.
|
|
74
|
+
* @throws RangeError If a named column is absent or not numeric, if the
|
|
75
|
+
* frame is ragged, or if no row is complete — R's "0 (non-NA) cases".
|
|
76
|
+
*/
|
|
77
|
+
export declare function lm(data: DataFrame, options: LmOptions): LmFit;
|
|
78
|
+
//# sourceMappingURL=lm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lm.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/lm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAe,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAE9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,oEAAoE;AACpE,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,yBAAyB;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yFAAyF;IACzF,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,6CAA6C;AAC7C,MAAM,WAAW,KAAK;IACpB,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,sEAAsE;IACtE,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,kFAAkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,iDAAiD;IACjD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,yBAAyB;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,KAAK,CAyD7D"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The LU factorization with partial pivoting, and what R reads off it:
|
|
3
|
+
* `solve()`, `det()`, `determinant()`, `rcond()` and `norm()`.
|
|
4
|
+
*
|
|
5
|
+
* R's `solve(a, b)` is LAPACK `dgesv` — `dgetrf` to factor, `dgetrs` to
|
|
6
|
+
* substitute — followed by `dgecon`'s condition estimate and an error when
|
|
7
|
+
* that estimate falls below `tol`. `det()` factors the same way and then
|
|
8
|
+
* exponentiates a sum of logarithms of the diagonal, which is why the
|
|
9
|
+
* determinant of an integer matrix comes back as `30.000000000000004`. This
|
|
10
|
+
* module follows those routines step for step, with the arithmetic of the
|
|
11
|
+
* reference BLAS build the fixtures come from (each product rounded once
|
|
12
|
+
* into its sum — see `fusedMultiplyAdd`), so that the factorization, the
|
|
13
|
+
* solves and the determinant pin bit for bit. Verified in `lu.test.ts`.
|
|
14
|
+
* The 2 × 2 special case in `../matrix.ts` is the same algorithm and the
|
|
15
|
+
* two agree exactly on every fixture of the interactive demo.
|
|
16
|
+
*
|
|
17
|
+
* Three departures from R, each stated where it applies: `rcond` is the
|
|
18
|
+
* exact one-norm ratio rather than `dgecon`'s estimate; a vector right-hand
|
|
19
|
+
* side comes back as a plain array rather than R's named vector; and a
|
|
20
|
+
* negative or NaN tolerance is refused where R would skip the check.
|
|
21
|
+
*
|
|
22
|
+
* Index loops throughout: a factorization addresses single entries by
|
|
23
|
+
* position, and this one follows `dgetf2` and `dtrsm` as written.
|
|
24
|
+
*/
|
|
25
|
+
import { type Matrix } from "./matrix";
|
|
26
|
+
import type { Vector } from "./vector";
|
|
27
|
+
/** R's `solve()` result on a square matrix, factored. */
|
|
28
|
+
export interface LuDecomposition {
|
|
29
|
+
/**
|
|
30
|
+
* The compact factorization, LAPACK's: `U` on and above the diagonal, the
|
|
31
|
+
* multipliers of the unit lower triangle `L` below it, rows already
|
|
32
|
+
* interchanged.
|
|
33
|
+
*/
|
|
34
|
+
readonly lu: Matrix;
|
|
35
|
+
/**
|
|
36
|
+
* The row interchanges, LAPACK's `ipiv` **zero-based**: at step `i` row
|
|
37
|
+
* `i` was swapped with row `pivots[i]`. Apply them in order to recover
|
|
38
|
+
* `P` such that `P A = L U`. Plural, and not `pivot` as in
|
|
39
|
+
* `QrDecomposition`, because this is a list of interchanges rather than
|
|
40
|
+
* a column order.
|
|
41
|
+
*/
|
|
42
|
+
readonly pivots: readonly number[];
|
|
43
|
+
/**
|
|
44
|
+
* The zero-based index of the first exactly zero pivot — LAPACK's `info`,
|
|
45
|
+
* less one — or null if the factorization completed. R reports it as
|
|
46
|
+
* `U[i,i] = 0`, one-based.
|
|
47
|
+
*/
|
|
48
|
+
readonly zeroPivot: number | null;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Factor a square matrix, as LAPACK's `dgetrf` does.
|
|
52
|
+
*
|
|
53
|
+
* @param a The matrix. The function does not modify it.
|
|
54
|
+
* @returns The compact factorization, the row interchanges, and the first
|
|
55
|
+
* zero pivot if any. A zero pivot does not stop the factorization, as it
|
|
56
|
+
* does not in LAPACK.
|
|
57
|
+
* @throws RangeError If the matrix is not square.
|
|
58
|
+
* @throws TypeError If `a` is not a matrix.
|
|
59
|
+
*/
|
|
60
|
+
export declare function lu(a: Matrix): LuDecomposition;
|
|
61
|
+
export interface SolveOptions {
|
|
62
|
+
/**
|
|
63
|
+
* The reciprocal condition number below which the system is refused as
|
|
64
|
+
* computationally singular. R's default is `.Machine$double.eps`; zero
|
|
65
|
+
* skips the check, as it does in R. R also skips it for a negative or
|
|
66
|
+
* NA `tol`; the port refuses those with a `RangeError` — a deliberate
|
|
67
|
+
* narrowing, as `matrix()` narrows R's recycling.
|
|
68
|
+
*/
|
|
69
|
+
readonly tolerance?: number;
|
|
70
|
+
}
|
|
71
|
+
/** The singularity tolerance of R's `solve()`: one machine epsilon. */
|
|
72
|
+
export declare const DEFAULT_SOLVE_TOLERANCE: number;
|
|
73
|
+
/**
|
|
74
|
+
* R's `solve(a)`, `solve(a, b)` and `solve(a, B)`: the inverse, the solution
|
|
75
|
+
* of `a x = b` for a vector, or the solution of `a X = B` for a matrix.
|
|
76
|
+
*
|
|
77
|
+
* @param a The square coefficient matrix.
|
|
78
|
+
* @param b The right-hand side, or the options when only the inverse is
|
|
79
|
+
* wanted. A vector gives a plain array (R names it by the column names of
|
|
80
|
+
* `a`; the port carries no names on a bare array — plan Q11). A matrix
|
|
81
|
+
* gives a matrix whose row names are the column names of `a` and whose
|
|
82
|
+
* column names are those of `b`; the inverse has the column names of `a`
|
|
83
|
+
* as rows and the row names of `a` as columns, as R's does.
|
|
84
|
+
* @param options The singularity tolerance.
|
|
85
|
+
* @returns The solution.
|
|
86
|
+
* @throws RangeError If `a` is not square or has no rows, `b` does not
|
|
87
|
+
* conform or has no columns, the factorization meets an exactly zero
|
|
88
|
+
* pivot, or the reciprocal condition number is below the tolerance —
|
|
89
|
+
* each in R's own words. As in R, a non-finite entry in `a` leaves the
|
|
90
|
+
* condition unchecked: R's `dgecon` reports a bad norm and `solve()`
|
|
91
|
+
* goes on.
|
|
92
|
+
* @throws TypeError If `a` or `b` is neither a matrix nor an array.
|
|
93
|
+
*/
|
|
94
|
+
export declare function solve(a: Matrix, options?: SolveOptions): Matrix;
|
|
95
|
+
export declare function solve(a: Matrix, b: Vector, options?: SolveOptions): number[];
|
|
96
|
+
export declare function solve(a: Matrix, b: Matrix, options?: SolveOptions): Matrix;
|
|
97
|
+
/**
|
|
98
|
+
* R's `det()`: the determinant, through the factorization and a sum of
|
|
99
|
+
* logarithms, as R computes it. A 0 × 0 matrix has determinant 1, as in R.
|
|
100
|
+
*
|
|
101
|
+
* @throws RangeError If the matrix is not square.
|
|
102
|
+
* @throws TypeError If `a` is not a matrix.
|
|
103
|
+
*/
|
|
104
|
+
export declare function det(a: Matrix): number;
|
|
105
|
+
/**
|
|
106
|
+
* R's `determinant()`: the logarithm of the absolute determinant and its
|
|
107
|
+
* sign. An exactly singular matrix reports `-Infinity` and sign 1, so that
|
|
108
|
+
* `det()` is a positive zero, as R's is.
|
|
109
|
+
*
|
|
110
|
+
* @throws RangeError If the matrix is not square.
|
|
111
|
+
* @throws TypeError If `a` is not a matrix.
|
|
112
|
+
*/
|
|
113
|
+
export declare function determinant(a: Matrix): {
|
|
114
|
+
readonly modulus: number;
|
|
115
|
+
readonly sign: 1 | -1;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* The reciprocal condition number in the one-norm, R's `rcond(x)`:
|
|
119
|
+
* `1 / (norm(x) * norm(solve(x)))` for a square matrix, 0 when it is
|
|
120
|
+
* exactly singular, and Infinity for a 0 × 0 matrix. A matrix that is not
|
|
121
|
+
* square goes through the triangular factor of its QR, as R's does
|
|
122
|
+
* (`rcond(qr.R(qr(x)))`, transposed first when wide).
|
|
123
|
+
*
|
|
124
|
+
* R's `rcond()` and `solve()` read an estimate of this number from LAPACK's
|
|
125
|
+
* `dgecon` rather than computing it, and the port computes it exactly. On
|
|
126
|
+
* the fixtures the two agree to the last bit for most matrices (3a, 3c, 3d,
|
|
127
|
+
* 3e, 3i) and differ by one unit in the last place on two (3b, 3h);
|
|
128
|
+
* `solve()`'s error message matches R's to the six digits it prints on
|
|
129
|
+
* every singular case pinned. The estimate bounds the norm of the inverse
|
|
130
|
+
* from below, so R's number is never smaller than the port's.
|
|
131
|
+
*
|
|
132
|
+
* @throws RangeError If an entry is not finite — R's "error code -5 from
|
|
133
|
+
* Lapack routine 'dgecon()'", because `dgecon` refuses a norm it cannot
|
|
134
|
+
* read.
|
|
135
|
+
* @throws TypeError If `a` is not a matrix.
|
|
136
|
+
*/
|
|
137
|
+
export declare function rcond(a: Matrix): number;
|
|
138
|
+
/**
|
|
139
|
+
* R's `norm()` types. `"O"` is R's default; the letters are accepted in
|
|
140
|
+
* either case, as R's `lsame` accepts them. R's `"2"`, the spectral norm,
|
|
141
|
+
* needs a singular value decomposition, which this plan leaves out.
|
|
142
|
+
*/
|
|
143
|
+
export type MatrixNormType = "O" | "1" | "I" | "F" | "E" | "M" | "o" | "i" | "f" | "e" | "m";
|
|
144
|
+
/**
|
|
145
|
+
* R's `norm(x, type)`: the one-norm (`"O"` or `"1"`, the largest absolute
|
|
146
|
+
* column sum), the infinity norm (`"I"`, the largest absolute row sum), the
|
|
147
|
+
* Frobenius norm (`"F"` or `"E"`), or the largest absolute entry (`"M"`).
|
|
148
|
+
* Named `matrixNorm` because `norm` in this entry is the vector length.
|
|
149
|
+
*
|
|
150
|
+
* @throws RangeError If the type is none of those, in R's words.
|
|
151
|
+
* @throws TypeError If `a` is not a matrix.
|
|
152
|
+
*/
|
|
153
|
+
export declare function matrixNorm(a: Matrix, type?: MatrixNormType): number;
|
|
154
|
+
//# sourceMappingURL=lu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lu.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/lu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,EAAuB,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAG5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAUvC,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;;;;GASG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,eAAe,CAoD7C;AAWD,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,uEAAuE;AACvE,eAAO,MAAM,uBAAuB,QAAiB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;AACjE,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,EAAE,CAAC;AAC9E,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;AA2I5E;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAGrC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,CAoB1F;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAoBvC;AAED;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAE7F;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,cAAoB,GAAG,MAAM,CAmCxE"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A matrix, held the way R holds one.
|
|
3
|
+
*
|
|
4
|
+
* R stores a matrix as one vector in column-major order with a `dim`
|
|
5
|
+
* attribute and optional `dimnames`. This module keeps that shape as a plain
|
|
6
|
+
* object: a `Float64Array` of the entries column by column, the two extents,
|
|
7
|
+
* and the names. Plain data, not a class — a matrix serializes, clones and
|
|
8
|
+
* crosses a worker boundary as it is, and every operation on it is a function
|
|
9
|
+
* in R's vocabulary (`t`, `matmul`, `crossprod`, `cbind`, …) in `ops.ts`.
|
|
10
|
+
*
|
|
11
|
+
* Column-major is load-bearing. It is what R, LAPACK and every conformance
|
|
12
|
+
* fixture assume, so `matrix(c(x1, y1, x2, y2), nrow = 2)` translates with
|
|
13
|
+
* no reordering, and a factorization ported from LINPACK reads the same
|
|
14
|
+
* memory in the same order.
|
|
15
|
+
*
|
|
16
|
+
* Indices are zero-based throughout, as the language's are. R's `A[1, 1]` is
|
|
17
|
+
* `at(a, 0, 0)` here.
|
|
18
|
+
*
|
|
19
|
+
* R recycles the data to fill the matrix: a scalar silently, a sub-multiple
|
|
20
|
+
* of the extent silently too (`matrix(1:3, 3, 2)` repeats the column), and
|
|
21
|
+
* any other length with a warning. This module recycles a scalar only —
|
|
22
|
+
* `matrix([0], {nrow: 3, ncol: 3})` is R's `matrix(0, 3, 3)` — and refuses
|
|
23
|
+
* every other mismatch, warned or not. A silently recycled column lets a
|
|
24
|
+
* typo fit the wrong model; a caller who wants the repeat writes
|
|
25
|
+
* `cbind(v, v)`.
|
|
26
|
+
*/
|
|
27
|
+
import { type DataFrame } from "../frame";
|
|
28
|
+
import type { Vector } from "./vector";
|
|
29
|
+
/** Row names and column names, either of which R may leave `NULL`. */
|
|
30
|
+
export type Dimnames = readonly [
|
|
31
|
+
readonly string[] | null,
|
|
32
|
+
readonly string[] | null
|
|
33
|
+
];
|
|
34
|
+
/** A matrix in R's layout: column-major data with its two extents. */
|
|
35
|
+
export interface Matrix {
|
|
36
|
+
readonly nrow: number;
|
|
37
|
+
readonly ncol: number;
|
|
38
|
+
/**
|
|
39
|
+
* The entries, column by column: entry `(i, j)` is `data[j * nrow + i]`.
|
|
40
|
+
* Treat it as read-only. A `Float64Array` has no read-only type, so the
|
|
41
|
+
* rule is stated rather than enforced.
|
|
42
|
+
*/
|
|
43
|
+
readonly data: Float64Array;
|
|
44
|
+
/** R's `dimnames`, or null when the matrix has none. */
|
|
45
|
+
readonly dimnames: Dimnames | null;
|
|
46
|
+
}
|
|
47
|
+
/** The named arguments of R's `matrix()`. */
|
|
48
|
+
export interface MatrixOptions {
|
|
49
|
+
/** The number of rows. At least one of `nrow` and `ncol` is required. */
|
|
50
|
+
readonly nrow?: number;
|
|
51
|
+
/** The number of columns. */
|
|
52
|
+
readonly ncol?: number;
|
|
53
|
+
/** Fill row by row instead of column by column. False by default. */
|
|
54
|
+
readonly byrow?: boolean;
|
|
55
|
+
/** Row names and column names. */
|
|
56
|
+
readonly dimnames?: Dimnames;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build a matrix from its entries, as R's `matrix()` does.
|
|
60
|
+
*
|
|
61
|
+
* @param values The entries, in column-major order unless `byrow` is set,
|
|
62
|
+
* or a single value to fill the whole matrix with. The function copies
|
|
63
|
+
* them; a hole in a sparse array reads as NaN.
|
|
64
|
+
* @param options `nrow` or `ncol` (or both, in which case they must agree
|
|
65
|
+
* with the length), `byrow`, and `dimnames`. An extent may be zero, as
|
|
66
|
+
* R's may.
|
|
67
|
+
* @returns The matrix.
|
|
68
|
+
* @throws RangeError If neither extent is given, an extent is not a
|
|
69
|
+
* non-negative integer, the length is not a multiple of the extent given
|
|
70
|
+
* (R warns and recycles; the port refuses), both extents are given and do
|
|
71
|
+
* not multiply to the length (R recycles a sub-multiple silently; the port
|
|
72
|
+
* refuses), or a dimnames entry has the wrong length.
|
|
73
|
+
*/
|
|
74
|
+
export declare function matrix(values: Vector, options: MatrixOptions): Matrix;
|
|
75
|
+
/**
|
|
76
|
+
* Assemble a matrix from data already in column-major order, checking the
|
|
77
|
+
* dimnames against the extents and copying the name arrays so that no two
|
|
78
|
+
* matrices share one. The data is taken as is, not copied.
|
|
79
|
+
*
|
|
80
|
+
* @internal Not part of the entry point. The other linalg modules build
|
|
81
|
+
* their results through it.
|
|
82
|
+
*/
|
|
83
|
+
export declare function make(nrow: number, ncol: number, data: Float64Array, dimnames: Dimnames | null): Matrix;
|
|
84
|
+
/**
|
|
85
|
+
* Build a matrix from its rows.
|
|
86
|
+
*
|
|
87
|
+
* @param rows One array per row, each one value per column. Copied.
|
|
88
|
+
* @returns The matrix.
|
|
89
|
+
* @throws RangeError If there are no rows, a row is empty, or the rows have
|
|
90
|
+
* different lengths.
|
|
91
|
+
*/
|
|
92
|
+
export declare function fromRows(rows: readonly Vector[]): Matrix;
|
|
93
|
+
/**
|
|
94
|
+
* Build a matrix from its columns. This is R's `cbind()` over vectors and
|
|
95
|
+
* the natural constructor from a column-keyed data frame.
|
|
96
|
+
*
|
|
97
|
+
* @param columns One array per column, each one value per row. Copied.
|
|
98
|
+
* @returns The matrix.
|
|
99
|
+
* @throws RangeError If there are no columns, a column is empty, or the
|
|
100
|
+
* columns have different lengths.
|
|
101
|
+
*/
|
|
102
|
+
export declare function fromColumns(columns: readonly Vector[]): Matrix;
|
|
103
|
+
/**
|
|
104
|
+
* Read one entry. R's `m[i + 1, j + 1]`.
|
|
105
|
+
*
|
|
106
|
+
* @throws RangeError If the index is outside the matrix.
|
|
107
|
+
*/
|
|
108
|
+
export declare function at(m: Matrix, i: number, j: number): number;
|
|
109
|
+
/** Read one row as a plain array. R's `m[i + 1, ]`. */
|
|
110
|
+
export declare function row(m: Matrix, i: number): number[];
|
|
111
|
+
/** Read one column as a plain array. R's `m[, j + 1]`. */
|
|
112
|
+
export declare function column(m: Matrix, j: number): number[];
|
|
113
|
+
/** The matrix as an array of rows. */
|
|
114
|
+
export declare function toRows(m: Matrix): number[][];
|
|
115
|
+
/** The matrix as an array of columns. */
|
|
116
|
+
export declare function toColumns(m: Matrix): number[][];
|
|
117
|
+
/**
|
|
118
|
+
* R's `as.matrix()` of a data frame: the numeric columns side by side, with
|
|
119
|
+
* the column names carried. The natural way into `cov`, `prcomp` and
|
|
120
|
+
* `matmul` from a column-keyed frame.
|
|
121
|
+
*
|
|
122
|
+
* @param data The frame.
|
|
123
|
+
* @param columns The columns to take, in order. By default every numeric
|
|
124
|
+
* column, in frame order — R's `Filter(is.numeric, data)`.
|
|
125
|
+
* @returns The matrix, `frameRows(data)` by `columns.length`, with the
|
|
126
|
+
* column names as its column names.
|
|
127
|
+
* @throws RangeError If a named column is absent or not numeric (through
|
|
128
|
+
* `requireNumericColumn`), or if the frame is ragged.
|
|
129
|
+
*/
|
|
130
|
+
export declare function fromFrame(data: DataFrame, columns?: readonly string[]): Matrix;
|
|
131
|
+
//# sourceMappingURL=matrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/matrix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,sEAAsE;AACtE,MAAM,MAAM,QAAQ,GAAG,SAAS;IAC9B,SAAS,MAAM,EAAE,GAAG,IAAI;IACxB,SAAS,MAAM,EAAE,GAAG,IAAI;CACzB,CAAC;AAEF,sEAAsE;AACtE,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;CACpC;AAED,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,MAAM,CACpB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,GACrB,MAAM,CAqBR;AAwDD;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,QAAQ,GAAG,IAAI,GACxB,MAAM,CAwBR;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAsBxD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,MAAM,CAqBR;AAED;;;;GAIG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED,uDAAuD;AACvD,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAKlD;AAED,0DAA0D;AAC1D,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAKrD;AAED,sCAAsC;AACtC,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAE5C;AAED,yCAAyC;AACzC,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAE/C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAQ9E"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R's `model.matrix()`: a data frame and a list of terms → the design
|
|
3
|
+
* matrix, with the column names `lm()` gives its coefficients.
|
|
4
|
+
*
|
|
5
|
+
* R builds this from a formula. The port has no formulas (CLAUDE.md: the
|
|
6
|
+
* canonical form is explicit column names in an options object), so a
|
|
7
|
+
* model is a list of terms — a column name for a main effect, an array of
|
|
8
|
+
* column names for an interaction — and the intercept is a flag. R's
|
|
9
|
+
* `y ~ x * z + w` is `{ outcome: "y", terms: ["x", "z", "w", ["x", "z"]] }`.
|
|
10
|
+
*
|
|
11
|
+
* The columns come out in R's order, whatever order the terms were written
|
|
12
|
+
* in: the intercept, then the terms by degree — every main effect before
|
|
13
|
+
* every two-way interaction before every three-way — and within a degree in
|
|
14
|
+
* the order given. A term written twice enters once. The `assign` vector is
|
|
15
|
+
* R's: the index of the term each column came from, 0 for the intercept.
|
|
16
|
+
*
|
|
17
|
+
* Rows with a missing (non-finite) value in the outcome or in any column a
|
|
18
|
+
* term names are dropped, R's `model.frame()` under `na.omit`; the indices
|
|
19
|
+
* of the rows kept are returned, so a fit can pad its results back to the
|
|
20
|
+
* input order (the `na.exclude` convention every fit in this package uses).
|
|
21
|
+
* Only numeric columns can enter; R's factors and contrasts are out of
|
|
22
|
+
* scope.
|
|
23
|
+
*/
|
|
24
|
+
import { type DataFrame } from "../frame";
|
|
25
|
+
import { type Matrix } from "./matrix";
|
|
26
|
+
/**
|
|
27
|
+
* One term of a model: a column name for a main effect, or the column names
|
|
28
|
+
* of an interaction, R's `a:b`.
|
|
29
|
+
*/
|
|
30
|
+
export type Term = string | readonly string[];
|
|
31
|
+
/** Which columns make the model. */
|
|
32
|
+
export interface ModelSpec {
|
|
33
|
+
/**
|
|
34
|
+
* The outcome column. It enters no design column, but a row missing it is
|
|
35
|
+
* dropped, as `model.frame()` drops it. Optional here; `lm()` requires it.
|
|
36
|
+
*/
|
|
37
|
+
readonly outcome?: string;
|
|
38
|
+
/** The terms, in any order. R's order is restored. */
|
|
39
|
+
readonly terms: readonly Term[];
|
|
40
|
+
/** Whether to lead with a column of ones. True by default, R's `+ 1`. */
|
|
41
|
+
readonly intercept?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/** A design matrix and where its rows came from. */
|
|
44
|
+
export interface ModelMatrix {
|
|
45
|
+
/**
|
|
46
|
+
* The design, one row per complete data row, with the coefficient names
|
|
47
|
+
* as column names: `(Intercept)`, the main effects, the interactions as
|
|
48
|
+
* `a:b`.
|
|
49
|
+
*/
|
|
50
|
+
readonly matrix: Matrix;
|
|
51
|
+
/** The data rows the design holds, in input order. */
|
|
52
|
+
readonly rows: readonly number[];
|
|
53
|
+
/** R's `assign`: the term each column came from, 0 for the intercept. */
|
|
54
|
+
readonly assign: readonly number[];
|
|
55
|
+
/** R's `term.labels`: the terms in the order the columns follow. */
|
|
56
|
+
readonly termLabels: readonly string[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build the design matrix of a model, as R's `model.matrix()` does.
|
|
60
|
+
*
|
|
61
|
+
* @param data The frame holding every column the model names.
|
|
62
|
+
* @param spec The outcome, the terms, and the intercept flag.
|
|
63
|
+
* @returns The design, the rows it kept, and R's `assign` and term labels.
|
|
64
|
+
* @throws RangeError If a named column is absent or not numeric (through
|
|
65
|
+
* `requireNumericColumn`, naming the option it arrived through), if the
|
|
66
|
+
* frame is ragged, or if an interaction term names no column.
|
|
67
|
+
*/
|
|
68
|
+
export declare function modelMatrix(data: DataFrame, spec: ModelSpec): ModelMatrix;
|
|
69
|
+
//# sourceMappingURL=modelMatrix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelMatrix.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/modelMatrix.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAmC,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAC3E,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,UAAU,CAAC;AAE7C;;;GAGG;AACH,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;AAE9C,oCAAoC;AACpC,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAChC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,oDAAoD;AACpD,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,oEAAoE;IACpE,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,WAAW,CA0DzE"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R's named vector: values with a name each, in order.
|
|
3
|
+
*
|
|
4
|
+
* A coefficient vector is the case that matters here — `coef(fit)` in R
|
|
5
|
+
* prints `(Intercept)`, `x`, `z`, `x:z` above its values, and `summary()`
|
|
6
|
+
* lines the standard errors up under the same names. The port holds the
|
|
7
|
+
* names alongside the values rather than in an object keyed by name,
|
|
8
|
+
* because a JavaScript object moves an integer-like key to the front: a
|
|
9
|
+
* column called `"1"` would jump ahead of `(Intercept)`. The pair of arrays
|
|
10
|
+
* keeps R's order, and pairs with `dimnames` on a `Matrix`, so the column
|
|
11
|
+
* names of a model matrix become the names of a fit with no reshaping
|
|
12
|
+
* (plan Q11).
|
|
13
|
+
*
|
|
14
|
+
* `null` is R's `NA`: a coefficient the fit could not identify.
|
|
15
|
+
*/
|
|
16
|
+
/** Values with a name each, in order. */
|
|
17
|
+
export interface NamedVector {
|
|
18
|
+
readonly names: readonly string[];
|
|
19
|
+
/** One value per name; null where R reports `NA`. */
|
|
20
|
+
readonly values: readonly (number | null)[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Pair names with values.
|
|
24
|
+
*
|
|
25
|
+
* @param names One name per value. Copied.
|
|
26
|
+
* @param values One value per name; null for R's `NA`. Copied.
|
|
27
|
+
* @throws RangeError If the two lengths differ.
|
|
28
|
+
*/
|
|
29
|
+
export declare function namedVector(names: readonly string[], values: readonly (number | null)[]): NamedVector;
|
|
30
|
+
/**
|
|
31
|
+
* Read one value by name. R's `v[["name"]]`.
|
|
32
|
+
*
|
|
33
|
+
* @returns The value, null where the entry is R's `NA`, or undefined when
|
|
34
|
+
* no entry carries the name. With a repeated name, the first.
|
|
35
|
+
*/
|
|
36
|
+
export declare function lookup(v: NamedVector, name: string): number | null | undefined;
|
|
37
|
+
//# sourceMappingURL=namedVector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"namedVector.d.ts","sourceRoot":"","sources":["../../../src/core/linalg/namedVector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,yCAAyC;AACzC,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,qDAAqD;IACrD,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CAC7C;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,MAAM,EAAE,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC,EAAE,GACjC,WAAW,CAOb;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAG9E"}
|