@compstats/core 0.3.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 +71 -0
- package/README.md +117 -116
- 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.js +1455 -863
- package/dist/index.js.map +16 -10
- 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/scatter3d.d.ts +1 -1
- package/package.json +7 -2
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/frame.ts", "../src/core/linalg/matrix.ts", "../src/core/arith.ts", "../src/core/linalg/ops.ts", "../src/core/linalg/qr.ts", "../src/core/linalg/lu.ts", "../src/core/linalg/namedVector.ts", "../src/core/linalg/modelMatrix.ts", "../src/core/special.ts", "../src/core/tdist.ts", "../src/core/linalg/lm.ts", "../src/core/linalg/cov.ts", "../src/core/linalg/eigen.ts", "../src/core/linalg/prcomp.ts", "../src/core/linalg/vector.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Column-keyed data frames, and the checks R gets for free.\n *\n * The 3D functions of the R package take an R data frame, which guarantees\n * two things a JavaScript object does not: every column holds one type, and\n * every column has the same length. `moderation.ts` and the scatter3d module\n * both need those guarantees, so the questions are asked in one place and\n * answered the same way for both.\n *\n * The port follows `../compstatslib/R/scatter3d_helpers.R`:\n *\n * ```r\n * scatter3d_numeric_cols <- function(data) {\n * names(data)[vapply(data, is.numeric, logical(1))]\n * }\n * ```\n *\n * with two departures, both forced by the language and both pinned by tests.\n * R reads a vector's declared type, so `is.numeric(numeric(0))` is TRUE and a\n * column of mixed types cannot exist. A JavaScript array declares nothing, so\n * this module reads the values: **a column is numeric when it holds at least\n * one value and every value is a number.** An empty column therefore is not\n * numeric — it offers no evidence either way, and an empty axis draws nothing\n * — and a column of numbers with one string in it is not numeric either,\n * because fitting it would give `NaN` for every coefficient.\n */\n\n/**\n * One column of a data frame.\n *\n * Numeric columns carry the statistics. The other two types are here because\n * `plot_scatter3d()` accepts a categorical column for `color`, which R allows\n * to be a factor, a character vector, or a logical vector.\n */\nexport type Column = readonly number[] | readonly string[] | readonly boolean[];\n\n/**\n * A data frame: named columns of equal length.\n *\n * The equal length is a rule, not a type. `frameRows` enforces it.\n */\nexport type DataFrame = { readonly [name: string]: Column };\n\n/**\n * Report whether a column holds numbers, and narrow it when it does.\n *\n * @param column The column to inspect.\n * @returns True when the column has at least one value and every value is a\n * number. `NaN` counts as a number, as R's missing values do.\n */\nexport function isNumericColumn(column: Column): column is readonly number[] {\n return column.length > 0 && column.every((value) => typeof value === \"number\");\n}\n\n/**\n * Name the numeric columns, in the order the frame declares them.\n *\n * This is R's `scatter3d_numeric_cols()`. The order matters: the scatter3d\n * default takes the first three names this returns.\n *\n * @param data The frame to inspect.\n * @returns The names of the numeric columns, in insertion order.\n */\nexport function numericColumns(data: DataFrame): string[] {\n return Object.keys(data).filter((name) =>\n isNumericColumn(data[name] as Column),\n );\n}\n\n/**\n * Refuse a frame that cannot fill three numeric axes.\n *\n * This is R's `scatter3d_require_3_numeric()`, which both the plot and the\n * gadget call with their own name, so that the message says which function\n * the caller reached.\n *\n * @param numeric The numeric column names, from `numericColumns`.\n * @param caller The name to print, such as `plotScatter3d`.\n * @throws RangeError If fewer than three names were given.\n */\nexport function requireThreeNumericColumns(\n numeric: readonly string[],\n caller: string,\n): void {\n if (numeric.length < 3) {\n throw new RangeError(\n `${caller}() needs at least 3 numeric columns; got ${numeric.length}. ` +\n \"Supply x/y/z explicitly or add numeric columns.\",\n );\n }\n}\n\n/**\n * Return the number of rows, and refuse a frame that has no single answer.\n *\n * @param data The frame to measure.\n * @returns The shared length of the columns. A frame with no columns has no\n * rows.\n * @throws RangeError If two columns have different lengths. An R data frame\n * cannot be built that way, so nothing downstream is written to survive it.\n */\nexport function frameRows(data: DataFrame): number {\n const names = Object.keys(data);\n const first = names[0];\n if (first === undefined) {\n return 0;\n }\n\n const rows = (data[first] as Column).length;\n const ragged = names.find((name) => (data[name] as Column).length !== rows);\n if (ragged !== undefined) {\n throw new RangeError(\n `every column needs the same number of rows: \"${first}\" has ${rows} ` +\n `but \"${ragged}\" has ${(data[ragged] as Column).length}`,\n );\n }\n\n return rows;\n}\n\n/**\n * Read one numeric column, or explain why it cannot be used.\n *\n * The wording follows R's own, which names both the column and the argument\n * it arrived through: `Column \"b\" (passed as \\`x\\`) is not in \\`data\\`.`\n *\n * @param data The frame to read.\n * @param name The column name the caller asked for.\n * @param role The option that carried the name, such as `iv` or `mod`. It\n * appears in the error, so the caller learns which argument is wrong.\n * @returns The column.\n * @throws RangeError If the frame has no such column, or the column is not\n * numeric.\n */\nexport function requireNumericColumn(\n data: DataFrame,\n name: string,\n role: string,\n): readonly number[] {\n const column = data[name];\n if (column === undefined) {\n throw new RangeError(\n `Column \"${name}\" (passed as \\`${role}\\`) is not in the data.`,\n );\n }\n if (!isNumericColumn(column)) {\n throw new RangeError(\n `Column \"${name}\" (passed as \\`${role}\\`) is not numeric; ` +\n \"only numeric columns can carry the statistics.\",\n );\n }\n\n return column;\n}\n",
|
|
6
|
+
"/**\n * A matrix, held the way R holds one.\n *\n * R stores a matrix as one vector in column-major order with a `dim`\n * attribute and optional `dimnames`. This module keeps that shape as a plain\n * object: a `Float64Array` of the entries column by column, the two extents,\n * and the names. Plain data, not a class — a matrix serializes, clones and\n * crosses a worker boundary as it is, and every operation on it is a function\n * in R's vocabulary (`t`, `matmul`, `crossprod`, `cbind`, …) in `ops.ts`.\n *\n * Column-major is load-bearing. It is what R, LAPACK and every conformance\n * fixture assume, so `matrix(c(x1, y1, x2, y2), nrow = 2)` translates with\n * no reordering, and a factorization ported from LINPACK reads the same\n * memory in the same order.\n *\n * Indices are zero-based throughout, as the language's are. R's `A[1, 1]` is\n * `at(a, 0, 0)` here.\n *\n * R recycles the data to fill the matrix: a scalar silently, a sub-multiple\n * of the extent silently too (`matrix(1:3, 3, 2)` repeats the column), and\n * any other length with a warning. This module recycles a scalar only —\n * `matrix([0], {nrow: 3, ncol: 3})` is R's `matrix(0, 3, 3)` — and refuses\n * every other mismatch, warned or not. A silently recycled column lets a\n * typo fit the wrong model; a caller who wants the repeat writes\n * `cbind(v, v)`.\n */\n\nimport {\n frameRows,\n numericColumns,\n requireNumericColumn,\n type DataFrame,\n} from \"../frame\";\nimport type { Vector } from \"./vector\";\n\n/** Row names and column names, either of which R may leave `NULL`. */\nexport type Dimnames = readonly [\n readonly string[] | null,\n readonly string[] | null,\n];\n\n/** A matrix in R's layout: column-major data with its two extents. */\nexport interface Matrix {\n readonly nrow: number;\n readonly ncol: number;\n /**\n * The entries, column by column: entry `(i, j)` is `data[j * nrow + i]`.\n * Treat it as read-only. A `Float64Array` has no read-only type, so the\n * rule is stated rather than enforced.\n */\n readonly data: Float64Array;\n /** R's `dimnames`, or null when the matrix has none. */\n readonly dimnames: Dimnames | null;\n}\n\n/** The named arguments of R's `matrix()`. */\nexport interface MatrixOptions {\n /** The number of rows. At least one of `nrow` and `ncol` is required. */\n readonly nrow?: number;\n /** The number of columns. */\n readonly ncol?: number;\n /** Fill row by row instead of column by column. False by default. */\n readonly byrow?: boolean;\n /** Row names and column names. */\n readonly dimnames?: Dimnames;\n}\n\n/**\n * Build a matrix from its entries, as R's `matrix()` does.\n *\n * @param values The entries, in column-major order unless `byrow` is set,\n * or a single value to fill the whole matrix with. The function copies\n * them; a hole in a sparse array reads as NaN.\n * @param options `nrow` or `ncol` (or both, in which case they must agree\n * with the length), `byrow`, and `dimnames`. An extent may be zero, as\n * R's may.\n * @returns The matrix.\n * @throws RangeError If neither extent is given, an extent is not a\n * non-negative integer, the length is not a multiple of the extent given\n * (R warns and recycles; the port refuses), both extents are given and do\n * not multiply to the length (R recycles a sub-multiple silently; the port\n * refuses), or a dimnames entry has the wrong length.\n */\nexport function matrix(\n values: Vector,\n options: MatrixOptions,\n): Matrix {\n const { byrow = false, dimnames } = options;\n const [nrow, ncol] = extents(values.length, options);\n // A typed array has no holes, so every fill path below sees the same\n // dense sequence, with NaN where the caller's array had a gap.\n const dense = Float64Array.from(values);\n\n const data = new Float64Array(nrow * ncol);\n if (dense.length === 1 && data.length > 1) {\n data.fill(dense[0] as number);\n } else if (byrow) {\n dense.forEach((value, index) => {\n const i = Math.floor(index / ncol);\n const j = index % ncol;\n data[j * nrow + i] = value;\n });\n } else {\n data.set(dense);\n }\n\n return make(nrow, ncol, data, dimnames ?? null);\n}\n\n/**\n * Resolve `nrow` and `ncol` from whichever the caller gave. A single value\n * fills any extents; otherwise the length must match them.\n */\nfunction extents(\n length: number,\n { nrow, ncol }: MatrixOptions,\n): [number, number] {\n if (nrow === undefined && ncol === undefined) {\n throw new RangeError(\"matrix() needs nrow or ncol\");\n }\n if (nrow !== undefined) {\n requireExtent(nrow, \"nrow\");\n }\n if (ncol !== undefined) {\n requireExtent(ncol, \"ncol\");\n }\n const scalar = length === 1;\n\n if (nrow !== undefined && ncol !== undefined) {\n if (!scalar && nrow * ncol !== length) {\n throw new RangeError(\n length > nrow * ncol\n ? \"data is too long\"\n : `data length [${length}] is not nrow * ncol [${nrow} * ${ncol}]`,\n );\n }\n return [nrow, ncol];\n }\n // One extent given. R's `matrix(numeric(0), nrow = 0)` is 0 x 0.\n const given = (nrow ?? ncol) as number;\n const name = nrow !== undefined ? \"rows\" : \"columns\";\n if (given === 0) {\n if (length !== 0) {\n throw new RangeError(\"data is too long\");\n }\n return [0, 0];\n }\n const other = scalar ? 1 : length / given;\n if (!scalar && length % given !== 0) {\n throw new RangeError(\n `data length [${length}] is not a multiple of the number of ${name} [${given}]`,\n );\n }\n return nrow !== undefined ? [nrow, other] : [other, given];\n}\n\n/** Reject an extent that is not a non-negative integer a double can count. */\nfunction requireExtent(value: number, name: string): void {\n if (!Number.isSafeInteger(value) || value < 0) {\n throw new RangeError(`${name} must be a non-negative integer, got ${value}`);\n }\n}\n\n/**\n * Assemble a matrix from data already in column-major order, checking the\n * dimnames against the extents and copying the name arrays so that no two\n * matrices share one. The data is taken as is, not copied.\n *\n * @internal Not part of the entry point. The other linalg modules build\n * their results through it.\n */\nexport function make(\n nrow: number,\n ncol: number,\n data: Float64Array,\n dimnames: Dimnames | null,\n): Matrix {\n if (data.length !== nrow * ncol) {\n throw new RangeError(\n `data length [${data.length}] is not nrow * ncol [${nrow} * ${ncol}]`,\n );\n }\n if (dimnames !== null) {\n const [rows, columns] = dimnames;\n if (rows !== null && rows.length !== nrow) {\n throw new RangeError(\n `length of dimnames [1] (${rows.length}) not equal to array extent (${nrow})`,\n );\n }\n if (columns !== null && columns.length !== ncol) {\n throw new RangeError(\n `length of dimnames [2] (${columns.length}) not equal to array extent (${ncol})`,\n );\n }\n dimnames =\n rows === null && columns === null\n ? null\n : [rows === null ? null : [...rows], columns === null ? null : [...columns]];\n }\n return { nrow, ncol, data, dimnames };\n}\n\n/**\n * Build a matrix from its rows.\n *\n * @param rows One array per row, each one value per column. Copied.\n * @returns The matrix.\n * @throws RangeError If there are no rows, a row is empty, or the rows have\n * different lengths.\n */\nexport function fromRows(rows: readonly Vector[]): Matrix {\n const nrow = rows.length;\n const first = rows[0];\n if (first === undefined || first.length === 0) {\n throw new RangeError(\"fromRows() needs at least one row with one value\");\n }\n const ncol = first.length;\n const ragged = rows.findIndex((row) => row.length !== ncol);\n if (ragged !== -1) {\n throw new RangeError(\n `every row needs ${ncol} values; row ${ragged} has ${(rows[ragged] as Vector).length}`,\n );\n }\n\n const data = new Float64Array(nrow * ncol);\n rows.forEach((row, i) => {\n // Through a typed array, so a hole reads as NaN rather than being skipped.\n Float64Array.from(row).forEach((value, j) => {\n data[j * nrow + i] = value;\n });\n });\n return make(nrow, ncol, data, null);\n}\n\n/**\n * Build a matrix from its columns. This is R's `cbind()` over vectors and\n * the natural constructor from a column-keyed data frame.\n *\n * @param columns One array per column, each one value per row. Copied.\n * @returns The matrix.\n * @throws RangeError If there are no columns, a column is empty, or the\n * columns have different lengths.\n */\nexport function fromColumns(\n columns: readonly Vector[],\n): Matrix {\n const ncol = columns.length;\n const first = columns[0];\n if (first === undefined || first.length === 0) {\n throw new RangeError(\n \"fromColumns() needs at least one column with one value\",\n );\n }\n const nrow = first.length;\n const ragged = columns.findIndex((column) => column.length !== nrow);\n if (ragged !== -1) {\n throw new RangeError(\n `every column needs ${nrow} values; column ${ragged} has ${(columns[ragged] as Vector).length}`,\n );\n }\n\n const data = new Float64Array(nrow * ncol);\n columns.forEach((column, j) => {\n data.set(column, j * nrow);\n });\n return make(nrow, ncol, data, null);\n}\n\n/**\n * Read one entry. R's `m[i + 1, j + 1]`.\n *\n * @throws RangeError If the index is outside the matrix.\n */\nexport function at(m: Matrix, i: number, j: number): number {\n if (!Number.isInteger(i) || i < 0 || i >= m.nrow) {\n throw new RangeError(`row index ${i} is outside 0..${m.nrow - 1}`);\n }\n if (!Number.isInteger(j) || j < 0 || j >= m.ncol) {\n throw new RangeError(`column index ${j} is outside 0..${m.ncol - 1}`);\n }\n return m.data[j * m.nrow + i] as number;\n}\n\n/** Read one row as a plain array. R's `m[i + 1, ]`. */\nexport function row(m: Matrix, i: number): number[] {\n if (!Number.isInteger(i) || i < 0 || i >= m.nrow) {\n throw new RangeError(`row index ${i} is outside 0..${m.nrow - 1}`);\n }\n return Array.from({ length: m.ncol }, (_, j) => m.data[j * m.nrow + i] as number);\n}\n\n/** Read one column as a plain array. R's `m[, j + 1]`. */\nexport function column(m: Matrix, j: number): number[] {\n if (!Number.isInteger(j) || j < 0 || j >= m.ncol) {\n throw new RangeError(`column index ${j} is outside 0..${m.ncol - 1}`);\n }\n return Array.from(m.data.subarray(j * m.nrow, (j + 1) * m.nrow));\n}\n\n/** The matrix as an array of rows. */\nexport function toRows(m: Matrix): number[][] {\n return Array.from({ length: m.nrow }, (_, i) => row(m, i));\n}\n\n/** The matrix as an array of columns. */\nexport function toColumns(m: Matrix): number[][] {\n return Array.from({ length: m.ncol }, (_, j) => column(m, j));\n}\n\n/**\n * R's `as.matrix()` of a data frame: the numeric columns side by side, with\n * the column names carried. The natural way into `cov`, `prcomp` and\n * `matmul` from a column-keyed frame.\n *\n * @param data The frame.\n * @param columns The columns to take, in order. By default every numeric\n * column, in frame order — R's `Filter(is.numeric, data)`.\n * @returns The matrix, `frameRows(data)` by `columns.length`, with the\n * column names as its column names.\n * @throws RangeError If a named column is absent or not numeric (through\n * `requireNumericColumn`), or if the frame is ragged.\n */\nexport function fromFrame(data: DataFrame, columns?: readonly string[]): Matrix {\n const nrow = frameRows(data);\n const names = columns ?? numericColumns(data);\n const buffer = new Float64Array(nrow * names.length);\n names.forEach((name, j) => {\n buffer.set(requireNumericColumn(data, name, \"columns\"), j * nrow);\n });\n return make(nrow, names.length, buffer, names.length === 0 ? null : [null, [...names]]);\n}\n",
|
|
7
|
+
"/**\n * Shared array arithmetic for the core modules.\n *\n * Use these helpers with `map` instead of index-based loops. See the\n * iteration convention in CLAUDE.md.\n */\n\n/** Add all values. Return 0 for an empty array. */\nexport function sum(values: readonly number[]): number {\n return values.reduce((total, value) => total + value, 0);\n}\n\n/** Return the arithmetic mean. Return NaN for an empty array. */\nexport function mean(values: readonly number[]): number {\n return sum(values) / values.length;\n}\n\n/**\n * Return the smallest and the largest value, as R's `range()` does.\n *\n * Written as a fold rather than `Math.min(...values)`, which overflows the\n * call stack on a long column.\n *\n * @param values The observations.\n * @returns The lowest and the highest value. An empty array returns\n * [Infinity, -Infinity], the shape of R's `range(numeric(0))`.\n *\n * A comparison keeps the accumulator when it is false, so a NaN entry is\n * skipped rather than carried through. No caller supports NaN input: the\n * modules that call this either drop the non-finite values first or state\n * that they do not handle R's NA.\n */\nexport function extent(values: readonly number[]): [number, number] {\n return values.reduce<[number, number]>(\n ([low, high], value) => [\n value < low ? value : low,\n value > high ? value : high,\n ],\n [Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY],\n );\n}\n\n/**\n * Map a negative zero to a positive one.\n *\n * A computed zero can come out of an algorithm with a sign that R's own\n * zeros never carry: of 1498 zero entries of a matrix inverse over a sweep of\n * 20000 slider settings, R gives a positive zero every time.\n */\nexport function withoutNegativeZero(value: number): number {\n return value === 0 ? 0 : value;\n}\n\n/** Reject a count that is not a non-negative integer. */\nexport function requireCount(value: number, name: string): void {\n if (!Number.isInteger(value) || value < 0) {\n throw new RangeError(`${name} must be a non-negative integer, got ${value}`);\n }\n}\n\n/**\n * Combine two arrays element by element.\n *\n * Stop at the end of the shorter array.\n */\nexport function zipWith<A, B, C>(\n as: readonly A[],\n bs: readonly B[],\n combine: (a: A, b: B) => C,\n): C[] {\n const length = Math.min(as.length, bs.length);\n // The slice bounds the index, so the access cannot be undefined.\n return as.slice(0, length).map((a, index) => combine(a, bs[index] as B));\n}\n\n/**\n * Return the standard deviation, with the n − 1 denominator of R's `sd()`.\n *\n * @param values The observations.\n * @returns The standard deviation, or NaN below two values. R returns NA\n * there, with a warning that a library cannot give.\n */\nexport function sd(values: readonly number[]): number {\n if (values.length < 2) {\n return Number.NaN;\n }\n\n const center = mean(values);\n const squares = values.map((value) => (value - center) * (value - center));\n return Math.sqrt(sum(squares) / (values.length - 1));\n}\n\n/**\n * Return the mean absolute deviation, `mean(|x - mean(x)|)`.\n *\n * R base has no function for this. R's `mad()` is the *median* absolute\n * deviation from the median, scaled by 1.4826, which is a different\n * statistic. A caller that shows either one to a reader must write the name\n * in full, because the abbreviation covers both.\n *\n * The sampling demonstration offers this as one of its choices of statistic.\n * It measures spread in the units of the data, as the standard deviation\n * does, but a value far from the mean moves it less, because the distance is\n * not squared.\n *\n * @param values The observations.\n * @returns The mean distance from the mean. One value gives 0, because it\n * sits at its own mean. No values gives NaN, as `mean` does.\n */\nexport function meanAbsoluteDeviation(values: readonly number[]): number {\n const center = mean(values);\n return mean(values.map((value) => Math.abs(value - center)));\n}\n\n/**\n * Return `a * b + c`, rounded once.\n *\n * Written as `a * b + c`, JavaScript rounds twice — once for the product,\n * once for the sum — and the two roundings show. R's `seq.int` rounds once\n * and lands one unit in the last place away often enough to change a tick.\n * The linear algebra in `matrix.ts` needs the same: the compiler of the R\n * install the fixtures come from contracts a multiply and an add into one\n * instruction, so a matrix near singular differs in every digit without it.\n *\n * The two helpers below split each operation into the value a double can\n * hold plus the part it drops, so the dropped parts can be added back before\n * the one rounding that remains. Both are the standard error-free\n * transformations (Dekker 1971, Knuth). Both need every intermediate to stay\n * in range, which fails only within a factor of 2^28 of the largest double.\n * There the plain form is used: the result is already dominated by its own\n * overflow.\n */\nexport function fusedMultiplyAdd(a: number, b: number, c: number): number {\n // A zero product adds exactly, and only the plain form keeps the sign of\n // a zero sum the way the hardware instruction does: fma(-1, 0, -0) is -0.\n if (a * b === 0) {\n return c + a * b;\n }\n const [product, productError] = twoProduct(a, b);\n const [sum, sumError] = twoSum(c, product);\n const rounded = sum + (sumError + productError);\n return Number.isFinite(rounded) ? rounded : a * b + c;\n}\n\n/** Split a double into two halves whose product is exact. Dekker's method. */\nfunction split(value: number): [number, number] {\n const scaled = 134217729 * value;\n const high = scaled - (scaled - value);\n return [high, value - high];\n}\n\n/** Return the product and the part of it the product cannot hold. */\nfunction twoProduct(a: number, b: number): [number, number] {\n const product = a * b;\n const [aHigh, aLow] = split(a);\n const [bHigh, bLow] = split(b);\n const error =\n aLow * bLow - (product - aHigh * bHigh - aLow * bHigh - aHigh * bLow);\n return [product, error];\n}\n\n/** Return the sum and the part of it the sum cannot hold. */\nfunction twoSum(a: number, b: number): [number, number] {\n const sum = a + b;\n const carried = sum - a;\n return [sum, a - (sum - carried) + (b - carried)];\n}\n\n/**\n * Return a sample quantile, by the rule of R's `quantile(type = 7)`.\n *\n * Type 7 is the default of R's `quantile()`, and so the rule behind the\n * `IQR()` that `bw.nrd0()` uses to pick a bandwidth. It reads the sorted\n * values at position `1 + (n - 1) * p` and interpolates between the two\n * neighbors of a fractional position.\n *\n * @param values The observations. The function does not modify them.\n * @param p The probability. It must be in [0, 1].\n * @returns The quantile, or NaN for no values. R returns NA there.\n * @throws RangeError If p is outside [0, 1], as R does.\n */\nexport function quantile(values: readonly number[], p: number): number {\n return quantiles(values, [p])[0] as number;\n}\n\n/**\n * Return several sample quantiles, by the rule of R's `quantile(type = 7)`.\n *\n * R's `quantile()` also takes a vector of probabilities, and for one reason:\n * it sorts once and reads every position off the one sorted copy. Asking for\n * the two quartiles together instead of one at a time halves the work, which\n * is what the bandwidth rule does over a pooled sample.\n *\n * @param values The observations. The function does not modify them.\n * @param probs The probabilities. Each must be in [0, 1].\n * @returns One quantile per probability, in the order given. Each is NaN for\n * no values, where R returns NA.\n * @throws RangeError If a probability is outside [0, 1], as R does.\n */\nexport function quantiles(\n values: readonly number[],\n probs: readonly number[],\n): number[] {\n if (probs.some((p) => !(p >= 0 && p <= 1))) {\n throw new RangeError(`every probability must be in [0, 1], got ${probs}`);\n }\n if (values.length === 0) {\n return probs.map(() => Number.NaN);\n }\n\n // A Float64Array sorts by value with no comparator to call, which is about\n // three times faster than sorting a copy of the array over a pooled sample.\n const sorted = Float64Array.from(values).sort();\n\n return probs.map((p) => type7(sorted, p));\n}\n\n/**\n * Return the median, the value with half the observations on each side.\n *\n * R's `median()` sorts the values and, on an even count, averages the two in\n * the middle. That is the type-7 quantile at 0.5, which weights those same two\n * values by a half each, so this delegates rather than repeat the rule. The\n * two forms land on the same double, the halves included.\n *\n * The sampling demonstration offers this as one of its choices of statistic.\n * It marks the center in the units of the data, as the mean does, but a value\n * far from the center moves it very little, because only the ordering counts.\n *\n * @param values The observations. The function does not modify them.\n * @returns The median, or NaN for no values. R returns NA there.\n */\nexport function median(values: readonly number[]): number {\n return quantile(values, 0.5);\n}\n\n/** Read one type-7 quantile off already sorted values. */\nfunction type7(sorted: Float64Array, p: number): number {\n const position = 1 + (sorted.length - 1) * p;\n const below = Math.floor(position);\n const above = Math.ceil(position);\n // Both indices are inside the array: p in [0, 1] bounds the position by\n // 1 and by the length.\n const low = sorted[below - 1] as number;\n const high = sorted[above - 1] as number;\n\n if (position > below && high !== low) {\n // R's own form. The algebraically equal low + h * (high - low) rounds\n // differently, and this keeps the last bits with R.\n const h = position - below;\n return (1 - h) * low + h * high;\n }\n return low;\n}\n",
|
|
8
|
+
"/**\n * The elementary matrix operations, named as R names them.\n *\n * `t()`, `%*%` (`matmul`), `crossprod()`, `tcrossprod()`, `cbind()`,\n * `rbind()` and `diag()`. Each takes matrices (and, where R allows it, plain\n * vectors) and returns a new matrix; nothing here modifies its input.\n *\n * A bare vector in a product takes the shape R gives it, which is not\n * always the one that would conform (fixtures 1g and 1h probe the rules).\n * In `%*%`, a left vector is a row when its length matches the rows of the\n * right factor and otherwise a column; a right vector is a column when its\n * length matches the columns of the left factor and otherwise a row; two\n * vectors give their inner product. In `crossprod` a vector `x` is always\n * a column, and a vector `y` is a column when its length matches the rows\n * of `x` and otherwise a row. In `tcrossprod` a vector `x` is a row when\n * its length matches the columns of a matrix `y` and otherwise a column,\n * and a vector `y` is a row only when `x` has one row; two vectors are both\n * columns, the outer product.\n *\n * Dimnames travel as they do in R: a transpose swaps them, a product keeps\n * the row names of the left factor and the column names of the right, and\n * binding stacks them, with `\"\"` for a bare vector joined to a named matrix.\n *\n * The product follows the reference BLAS `dgemm` that R ships: the loop\n * over `i` innermost walks each column of the left factor in order, and each\n * product is rounded once into its running sum with `fusedMultiplyAdd`,\n * because the build the conformance fixtures come from contracts\n * `C + A * B` into one instruction (the fixture README records this; the LU\n * and QR here already follow it). Index loops throughout: a product\n * addresses entries by position. (CLAUDE.md allows an index loop with a\n * stated reason; that is the reason.)\n */\n\nimport { fusedMultiplyAdd } from \"../arith\";\nimport { make, type Dimnames, type Matrix } from \"./matrix\";\nimport type { Vector } from \"./vector\";\n\n/** A matrix, or a vector R would treat as a one-column matrix. */\nexport type MatrixOrVector = Matrix | Vector;\n\n/** R's `t()`. Also exported as `transpose`, for an app whose `t` is already taken. */\nexport function t(m: Matrix): Matrix {\n const { nrow, ncol } = m;\n const data = new Float64Array(nrow * ncol);\n for (let j = 0; j < ncol; j++) {\n for (let i = 0; i < nrow; i++) {\n data[i * ncol + j] = m.data[j * nrow + i] as number;\n }\n }\n const dimnames: Dimnames | null =\n m.dimnames === null ? null : [m.dimnames[1], m.dimnames[0]];\n return make(ncol, nrow, data, dimnames);\n}\n\n/** R's `t()`, under a name that does not collide with an i18n `t`. */\nexport const transpose = t;\n\n/**\n * R's `x %*% y`.\n *\n * @param x The left factor. A vector is a row when its length matches the\n * rows of `y`, else a column when `y` has one row.\n * @param y The right factor. A vector is a column when its length matches\n * the columns of `x`, else a row when `x` has one column. Two vectors of\n * one length give their inner product as a 1 x 1 matrix.\n * @returns The product, with the row names of `x` and the column names of\n * `y`.\n * @throws RangeError If the inner extents differ: R's \"non-conformable\n * arguments\".\n */\nexport function matmul(x: MatrixOrVector, y: MatrixOrVector): Matrix {\n const [left, right] = conformProduct(x, y);\n if (left.ncol !== right.nrow) {\n throw new RangeError(\n `non-conformable arguments: ${left.nrow} x ${left.ncol} %*% ${right.nrow} x ${right.ncol}`,\n );\n }\n const data = product(left, right);\n return make(left.nrow, right.ncol, data, productDimnames(left, right));\n}\n\n/** Shape the factors of `%*%` by R's rules for a bare vector. */\nfunction conformProduct(x: MatrixOrVector, y: MatrixOrVector): [Matrix, Matrix] {\n if (isMatrix(x)) {\n if (isMatrix(y)) {\n return [x, y];\n }\n return [x, y.length === x.ncol ? asColumn(y) : asRow(y)];\n }\n if (isMatrix(y)) {\n return [x.length === y.nrow ? asRow(x) : asColumn(x), y];\n }\n // Two vectors: `x` is a row, and `y` is a row too when `x` is a single\n // value, else a column — the inner product when the lengths agree.\n return [asRow(x), x.length === 1 ? asRow(y) : asColumn(y)];\n}\n\n/**\n * R's `crossprod(x, y)`: `t(x) %*% y`, with `crossprod(x)` for `t(x) %*% x`.\n * A bare vector `x` is a column; a bare vector `y` is a column when its\n * length matches the rows of `x`, else a row (fixture 1h).\n *\n * @throws RangeError If the row counts differ.\n */\nexport function crossprod(x: MatrixOrVector, y: MatrixOrVector = x): Matrix {\n const left = asColumn(x);\n const right = isMatrix(y) ? y : y.length === left.nrow ? asColumn(y) : asRow(y);\n if (left.nrow !== right.nrow) {\n throw new RangeError(\n `non-conformable arguments: crossprod of ${left.nrow} x ${left.ncol} and ${right.nrow} x ${right.ncol}`,\n );\n }\n return matmul(t(left), right);\n}\n\n/**\n * R's `tcrossprod(x, y)`: `x %*% t(y)`, with `tcrossprod(x)` for\n * `x %*% t(x)`. A bare vector `x` is a row when its length matches the\n * columns of a matrix `y`, else a column; a bare vector `y` is a row only\n * when `x` has one row, and two bare vectors are both columns (fixture 1h).\n *\n * @throws RangeError If the column counts differ.\n */\nexport function tcrossprod(x: MatrixOrVector, y: MatrixOrVector = x): Matrix {\n const bothVectors = !isMatrix(x) && !isMatrix(y);\n const left = isMatrix(x) ? x : isMatrix(y) && y.ncol === x.length ? asRow(x) : asColumn(x);\n const right = isMatrix(y)\n ? y\n : !bothVectors && left.nrow === 1\n ? asRow(y)\n : asColumn(y);\n if (left.ncol !== right.ncol) {\n throw new RangeError(\n `non-conformable arguments: tcrossprod of ${left.nrow} x ${left.ncol} and ${right.nrow} x ${right.ncol}`,\n );\n }\n return matmul(left, t(right));\n}\n\n/** The raw product of two conformable matrices, column-major. */\nfunction product(x: Matrix, y: Matrix): Float64Array {\n const { nrow, ncol: inner } = x;\n const { ncol } = y;\n const data = new Float64Array(nrow * ncol);\n for (let j = 0; j < ncol; j++) {\n for (let k = 0; k < inner; k++) {\n const factor = y.data[j * y.nrow + k] as number;\n for (let i = 0; i < nrow; i++) {\n data[j * nrow + i] = fusedMultiplyAdd(\n x.data[k * nrow + i] as number,\n factor,\n data[j * nrow + i] as number,\n );\n }\n }\n }\n return data;\n}\n\n/** Row names of the left factor, column names of the right. */\nfunction productDimnames(x: Matrix, y: Matrix): Dimnames | null {\n const rows = x.dimnames?.[0] ?? null;\n const columns = y.dimnames?.[1] ?? null;\n return rows === null && columns === null ? null : [rows, columns];\n}\n\n/** A vector as R's one-column matrix; a matrix as it is. */\nfunction asColumn(value: MatrixOrVector): Matrix {\n if (isMatrix(value)) {\n return value;\n }\n return make(value.length, 1, Float64Array.from(value), null);\n}\n\n/** A vector as a one-row matrix. */\nfunction asRow(value: Vector): Matrix {\n return make(1, value.length, Float64Array.from(value), null);\n}\n\n/**\n * Tell a matrix from a vector by shape, and refuse anything else — a typed\n * array or a stray object — with a TypeError rather than a wrong shape.\n *\n * @internal Shared with the other linalg modules; not part of the entry.\n */\nexport function isMatrix(value: MatrixOrVector): value is Matrix {\n if (Array.isArray(value)) {\n return false;\n }\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"nrow\" in value &&\n \"ncol\" in value &&\n \"data\" in value\n ) {\n return true;\n }\n throw new TypeError(\"expected a Matrix or an array of numbers\");\n}\n\n/**\n * R's `cbind()`: join matrices and vectors side by side.\n *\n * @param parts Matrices, and vectors taken as columns. At least one.\n * @returns The joined matrix. Row names come from the first part that has\n * them. Column names are kept when any part has them, with `\"\"` for a part\n * that does not, as R names a bare vector.\n * @throws RangeError If the row counts differ, in R's words for a matrix\n * part and for a vector part. R recycles a short vector with a warning;\n * the port refuses.\n */\nexport function cbind(...parts: readonly MatrixOrVector[]): Matrix {\n const matrices = parts.map(asColumn);\n const first = matrices[0];\n if (first === undefined) {\n throw new RangeError(\"cbind() needs at least one argument\");\n }\n const nrow = first.nrow;\n matrices.forEach((m, index) => {\n if (m.nrow !== nrow) {\n throw new RangeError(\n isMatrix(parts[index] as MatrixOrVector)\n ? `number of rows of matrices must match (see arg ${index + 1})`\n : `number of rows of result is not a multiple of vector length (arg ${index + 1})`,\n );\n }\n });\n\n const ncol = matrices.reduce((total, m) => total + m.ncol, 0);\n const data = new Float64Array(nrow * ncol);\n let offset = 0;\n matrices.forEach((m) => {\n data.set(m.data, offset);\n offset += m.data.length;\n });\n\n const rows = matrices.find((m) => m.dimnames?.[0])?.dimnames?.[0] ?? null;\n const columns = boundNames(\n matrices.map((m) => ({ names: m.dimnames?.[1] ?? null, count: m.ncol })),\n );\n return make(nrow, ncol, data, rows === null && columns === null ? null : [rows, columns]);\n}\n\n/**\n * R's `rbind()`: stack matrices and vectors.\n *\n * @param parts Matrices, and vectors taken as rows. At least one.\n * @returns The stacked matrix, with names as `cbind` carries them, rows and\n * columns exchanged.\n * @throws RangeError If the column counts differ.\n */\nexport function rbind(...parts: readonly MatrixOrVector[]): Matrix {\n if (parts.length === 0) {\n throw new RangeError(\"rbind() needs at least one argument\");\n }\n const transposed = parts.map((part) => (isMatrix(part) ? t(part) : part));\n try {\n return t(cbind(...transposed));\n } catch (error) {\n if (error instanceof RangeError) {\n throw new RangeError(\n error.message.replace(\"number of rows\", \"number of columns\"),\n );\n }\n throw error;\n }\n}\n\n/** Concatenate the names of bound parts, `\"\"` where a part has none. */\nfunction boundNames(\n parts: readonly { names: readonly string[] | null; count: number }[],\n): readonly string[] | null {\n if (parts.every((part) => part.names === null)) {\n return null;\n }\n return parts.flatMap(\n (part) => part.names ?? new Array<string>(part.count).fill(\"\"),\n );\n}\n\n/**\n * R's `diag()` in its three forms: a vector gives the diagonal matrix of it,\n * a count gives the identity of that order, and a matrix gives its diagonal.\n *\n * The form is chosen by type, not by length, which is R's own gotcha\n * removed: `diag([5])` is the 1 x 1 matrix `[5]` where R's `diag(c(5))` is\n * the 5 x 5 identity, and `diag(2.5)` refuses where R truncates to 2 x 2.\n * The diagonal of a matrix comes back as a plain array; R names it when the\n * row and column names agree, which the port will do once a named vector\n * exists (plan Q11).\n */\nexport function diag(values: Vector): Matrix;\nexport function diag(order: number): Matrix;\nexport function diag(m: Matrix): number[];\nexport function diag(arg: Vector | number | Matrix): Matrix | number[] {\n if (typeof arg === \"number\") {\n return identity(arg);\n }\n if (Array.isArray(arg)) {\n const values = arg as Vector;\n const n = values.length;\n const data = new Float64Array(n * n);\n values.forEach((value, i) => {\n data[i * n + i] = value;\n });\n return make(n, n, data, null);\n }\n const m = arg as Matrix;\n const n = Math.min(m.nrow, m.ncol);\n return Array.from({ length: n }, (_, i) => m.data[i * m.nrow + i] as number);\n}\n\n/**\n * The identity matrix of the given order. R's `diag(n)`.\n *\n * @throws RangeError If the order is not a non-negative integer.\n */\nexport function identity(order: number): Matrix {\n if (!Number.isInteger(order) || order < 0) {\n throw new RangeError(`order must be a non-negative integer, got ${order}`);\n }\n const data = new Float64Array(order * order);\n for (let i = 0; i < order; i++) {\n data[i * order + i] = 1;\n }\n return make(order, order, data, null);\n}\n",
|
|
9
|
+
"/**\n * The QR factorization, R's `qr()` with `LAPACK = FALSE`.\n *\n * R factors a design with LINPACK's `dqrdc2`, a Householder QR with a\n * limited column-pivoting rule: a column whose norm has collapsed against\n * the columns to its left is moved to the right edge and its coefficient is\n * reported as `NA`. That rule is what makes `lm()` and `glm()` report an\n * aliased coefficient instead of dividing by a near-zero pivot. This module\n * reproduces it and exposes R's result — the compact `qr` matrix, `qraux`,\n * `pivot` and `rank` — and R's readers of it: `qr.coef`, `qr.fitted`,\n * `qr.resid`, `qr.qy`, `qr.qty`, `qr.Q` and `qr.R`. Verified against R in\n * `qr.test.ts`; `leastSquares` in `../ols.ts` is a wrapper over it.\n *\n * Designs here are small — two columns for logit, four for a moderation\n * surface — so the code follows the LINPACK routines plainly rather than\n * blocking or vectorizing them. Index loops throughout: a factorization\n * addresses single entries by position, and this one follows `dqrdc2` and\n * `dqrsl` step for step so that the fixtures pin bit for bit.\n */\n\nimport { fusedMultiplyAdd } from \"../arith\";\nimport { make, type Dimnames, type Matrix } from \"./matrix\";\nimport { isMatrix, type MatrixOrVector } from \"./ops\";\nimport type { Vector } from \"./vector\";\n\n/** R's `qr()` result. */\nexport interface QrDecomposition {\n /**\n * The compact factorization, R's `qr$qr`: `R` on and above the diagonal,\n * the Householder vectors below it, columns in pivot order. Column names\n * follow the pivot, as R's do.\n */\n readonly qr: Matrix;\n /**\n * R's `qr$qraux`: for each reflected column, the leading entry of its\n * Householder reflector; for a column never reflected — the trailing\n * column of a square or wide design, or an aliased column — its remaining\n * norm, which is what R reports there (fixtures 2b, 2c, 2g).\n */\n readonly qraux: Vector;\n /**\n * The column order after pivoting, R's `qr$pivot` **zero-based**:\n * `pivot[k]` is the original index of the column now at position `k`.\n * The aliased columns are at the end.\n */\n readonly pivot: readonly number[];\n /** The number of columns the factorization could identify. */\n readonly rank: number;\n}\n\nexport interface QrOptions {\n /**\n * How far a column's norm may collapse before it is aliased: the column is\n * moved to the end when its remaining norm falls below this fraction of\n * its original norm. The default is R's `qr()` and `lm.fit()` default.\n * `glm.fit()` passes `min(1e-7, epsilon / 1000)`. Zero aliases nothing,\n * as R's `tol = 0` does; a negative or NaN value is refused, where R\n * would pass it through — a deliberate narrowing.\n */\n readonly tolerance?: number;\n}\n\n/** The rank tolerance of R's `qr()` and `lm.fit()`. */\nexport const DEFAULT_QR_TOLERANCE = 1e-7;\n\n/**\n * Factor a matrix, as R's `qr(x, LAPACK = FALSE)` does.\n *\n * @param x The matrix. The function does not modify it. Row names travel\n * onto the compact form; column names follow the pivot.\n * @param options The rank tolerance.\n * @returns The compact factorization, `qraux`, the pivot, and the rank.\n * @throws RangeError If the tolerance is negative or NaN, or if an entry is\n * not finite — R's \"NA/NaN/Inf in foreign function call (arg 1)\". NaN is\n * this library's missing value; a caller drops incomplete rows first, as\n * `modelMatrix` does.\n * @throws TypeError If `x` is not a matrix.\n */\nexport function qr(x: Matrix, options: QrOptions = {}): QrDecomposition {\n const { tolerance = DEFAULT_QR_TOLERANCE } = options;\n if (!(tolerance >= 0)) {\n throw new RangeError(`tolerance must be a non-negative number, got ${tolerance}`);\n }\n if (!isMatrix(x)) {\n throw new TypeError(\"expected a Matrix\");\n }\n if (!x.data.every(Number.isFinite)) {\n throw new RangeError(\"NA/NaN/Inf in foreign function call (arg 1)\");\n }\n const { nrow, ncol } = x;\n\n // Work on a copy of each column. `dqrdc2` overwrites the matrix in place;\n // the copies keep the caller's matrix untouched.\n const columns = Array.from({ length: ncol }, (_, j) =>\n Array.from(x.data.subarray(j * nrow, (j + 1) * nrow)),\n );\n const { householders, pivot, rank } = decompose(columns, tolerance, nrow);\n\n const data = new Float64Array(nrow * ncol);\n columns.forEach((column, j) => {\n data.set(column, j * nrow);\n });\n const rows = x.dimnames?.[0] ?? null;\n const names = x.dimnames?.[1] ?? null;\n const dimnames: Dimnames | null =\n rows === null && names === null\n ? null\n : [rows, names === null ? null : pivot.map((from) => names[from] as string)];\n\n return { qr: make(nrow, ncol, data, dimnames), qraux: householders, pivot, rank };\n}\n\n/**\n * Solve for the coefficients, R's `qr.coef(qr, y)`.\n *\n * @param q The factorization.\n * @param y The response, one value per row — or a matrix with one response\n * per column, as R also takes.\n * @returns One coefficient per column of the factored matrix, **in the\n * original column order**, with null for an aliased column (R's `NA`).\n * For a matrix `y`, a matrix with one column per response, the factored\n * matrix's column names as row names and `y`'s column names as column\n * names; an aliased column reads NaN there, since a matrix holds no null.\n * @throws RangeError If `y` has the wrong number of rows.\n */\nexport function qrCoef(q: QrDecomposition, y: Vector): (number | null)[];\nexport function qrCoef(q: QrDecomposition, y: Matrix): Matrix;\nexport function qrCoef(q: QrDecomposition, y: MatrixOrVector): (number | null)[] | Matrix {\n if (isMatrix(y)) {\n requireRows(q, y.nrow);\n const width = q.qr.ncol;\n const data = new Float64Array(width * y.ncol);\n for (let j = 0; j < y.ncol; j++) {\n const solved = coefficientsOf(q, Array.from(y.data.subarray(j * y.nrow, (j + 1) * y.nrow)));\n solved.forEach((value, i) => {\n data[j * width + i] = value ?? Number.NaN;\n });\n }\n return make(width, y.ncol, data, readerDimnames(originalColumnNames(q), y));\n }\n requireRows(q, y.length);\n return coefficientsOf(q, y);\n}\n\n/** The coefficients of one response, in the original column order. */\nfunction coefficientsOf(q: QrDecomposition, y: Vector): (number | null)[] {\n const qty = transformed(q, y, true);\n const solved = backSubstitute(q.qr, qty, q.rank);\n const coefficients = new Array<number | null>(q.qr.ncol).fill(null);\n q.pivot.slice(0, q.rank).forEach((column, position) => {\n coefficients[column] = solved[position] as number;\n });\n return coefficients;\n}\n\n/** The factored matrix's column names in their original order, if any. */\nfunction originalColumnNames(q: QrDecomposition): readonly string[] | null {\n const pivoted = q.qr.dimnames?.[1] ?? null;\n if (pivoted === null) {\n return null;\n }\n const names = new Array<string>(pivoted.length);\n q.pivot.forEach((original, position) => {\n names[original] = pivoted[position] as string;\n });\n return names;\n}\n\n/**\n * The fitted values, R's `qr.fitted(qr, y)`: `Q` applied to the first `rank`\n * entries of `Qᵀy`, the rest set to zero. A matrix `y` gives a matrix with\n * its column names.\n *\n * @throws RangeError If `y` has the wrong number of rows.\n */\nexport function qrFitted(q: QrDecomposition, y: Vector): number[];\nexport function qrFitted(q: QrDecomposition, y: Matrix): Matrix;\nexport function qrFitted(q: QrDecomposition, y: MatrixOrVector): number[] | Matrix {\n return perColumn(q, y, (column) =>\n transformed(q, transformed(q, column, true).map((value, index) => (index < q.rank ? value : 0)), false),\n );\n}\n\n/**\n * The residuals, R's `qr.resid(qr, y)`: `Q` applied to `Qᵀy` with its first\n * `rank` entries set to zero. A matrix `y` gives a matrix with its column\n * names.\n *\n * @throws RangeError If `y` has the wrong number of rows.\n */\nexport function qrResid(q: QrDecomposition, y: Vector): number[];\nexport function qrResid(q: QrDecomposition, y: Matrix): Matrix;\nexport function qrResid(q: QrDecomposition, y: MatrixOrVector): number[] | Matrix {\n return perColumn(q, y, (column) =>\n transformed(q, transformed(q, column, true).map((value, index) => (index < q.rank ? 0 : value)), false),\n );\n}\n\n/**\n * `Qᵀy`, R's `qr.qty(qr, y)`: the reflectors applied first to last. A\n * matrix `y` gives a matrix with its column names.\n *\n * @throws RangeError If `y` has the wrong number of rows.\n */\nexport function qrQty(q: QrDecomposition, y: Vector): number[];\nexport function qrQty(q: QrDecomposition, y: Matrix): Matrix;\nexport function qrQty(q: QrDecomposition, y: MatrixOrVector): number[] | Matrix {\n return perColumn(q, y, (column) => transformed(q, column, true));\n}\n\n/**\n * `Qy`, R's `qr.qy(qr, y)`: the reflectors applied last to first. A matrix\n * `y` gives a matrix with its column names.\n *\n * @throws RangeError If `y` has the wrong number of rows.\n */\nexport function qrQy(q: QrDecomposition, y: Vector): number[];\nexport function qrQy(q: QrDecomposition, y: Matrix): Matrix;\nexport function qrQy(q: QrDecomposition, y: MatrixOrVector): number[] | Matrix {\n return perColumn(q, y, (column) => transformed(q, column, false));\n}\n\n/** Apply a vector reader to a vector, or to each column of a matrix. */\nfunction perColumn(\n q: QrDecomposition,\n y: MatrixOrVector,\n read: (column: Vector) => number[],\n): number[] | Matrix {\n if (isMatrix(y)) {\n requireRows(q, y.nrow);\n const data = new Float64Array(y.nrow * y.ncol);\n for (let j = 0; j < y.ncol; j++) {\n data.set(read(Array.from(y.data.subarray(j * y.nrow, (j + 1) * y.nrow))), j * y.nrow);\n }\n return make(y.nrow, y.ncol, data, readerDimnames(null, y));\n }\n requireRows(q, y.length);\n return read(y);\n}\n\n/** Row names given, column names of `y`; null when there are neither. */\nfunction readerDimnames(rows: readonly string[] | null, y: Matrix): Dimnames | null {\n const columns = y.dimnames?.[1] ?? null;\n return rows === null && columns === null ? null : [rows, columns];\n}\n\n/** Apply the reflectors to a copy of `y`, first to last for `Qᵀy`, last to first for `Qy`. */\nfunction transformed(q: QrDecomposition, y: Vector, transpose: boolean): number[] {\n const result = [...y];\n const count = reflectorCount(q);\n if (transpose) {\n for (let step = 0; step < count; step++) {\n applyReflector(q, step, result);\n }\n } else {\n for (let step = count - 1; step >= 0; step--) {\n applyReflector(q, step, result);\n }\n }\n return result;\n}\n\n/**\n * The orthogonal factor, R's `qr.Q(qr)`: `n` rows by `min(n, p)` columns —\n * `Q` applied to the leading columns of the identity. It carries no names,\n * as R's does not.\n */\nexport function qrQ(q: QrDecomposition): Matrix {\n const { nrow, ncol } = q.qr;\n const width = Math.min(nrow, ncol);\n const data = new Float64Array(nrow * width);\n for (let j = 0; j < width; j++) {\n const unit = new Array<number>(nrow).fill(0);\n unit[j] = 1;\n data.set(transformed(q, unit, false), j * nrow);\n }\n return make(nrow, width, data, null);\n}\n\n/**\n * The triangular factor, R's `qr.R(qr)`: `min(n, p)` rows by `p` columns,\n * the upper triangle of the compact form, with the leading row names and\n * the column names in pivot order.\n */\nexport function qrR(q: QrDecomposition): Matrix {\n const { nrow, ncol } = q.qr;\n const height = Math.min(nrow, ncol);\n const data = new Float64Array(height * ncol);\n for (let j = 0; j < ncol; j++) {\n for (let i = 0; i <= Math.min(j, height - 1); i++) {\n data[j * height + i] = q.qr.data[j * nrow + i] as number;\n }\n }\n const rows = q.qr.dimnames?.[0]?.slice(0, height) ?? null;\n const columns = q.qr.dimnames?.[1] ?? null;\n return make(height, ncol, data, rows === null && columns === null ? null : [rows, columns]);\n}\n\n/** Refuse a response that does not match the rows. R's own wording. */\nfunction requireRows(q: QrDecomposition, rows: number): void {\n if (rows !== q.qr.nrow) {\n throw new RangeError(\"'qr' and 'y' must have the same number of rows\");\n }\n}\n\n/**\n * How many reflectors `dqrsl` applies: `min(k, n - 1)`, because the last\n * row of a square or wide matrix is never reflected.\n */\nfunction reflectorCount(q: QrDecomposition): number {\n return Math.min(q.rank, q.qr.nrow - 1);\n}\n\n/**\n * Apply one stored reflector to a vector in place: one step of LINPACK's\n * `dqrsl`.\n *\n * The reflector's leading entry lives in `qraux`, outside the column, so the\n * inner product and the update read it separately from the entries under\n * the diagonal. Both are BLAS calls in LINPACK — `ddot` and `daxpy` — and on\n * the build the fixtures come from each product is contracted into a fused\n * multiply-add, so `fusedMultiplyAdd` is used where the BLAS would round\n * once.\n */\nfunction applyReflector(\n q: QrDecomposition,\n step: number,\n vector: number[],\n): void {\n const leading = q.qraux[step] as number;\n if (leading === 0) {\n return;\n }\n const { nrow } = q.qr;\n const column = q.qr.data.subarray(step * nrow, (step + 1) * nrow);\n\n let inner = leading * (vector[step] as number);\n for (let row = step + 1; row < nrow; row++) {\n inner = fusedMultiplyAdd(column[row] as number, vector[row] as number, inner);\n }\n const factor = -inner / leading;\n vector[step] = fusedMultiplyAdd(factor, leading, vector[step] as number);\n for (let row = step + 1; row < nrow; row++) {\n vector[row] = fusedMultiplyAdd(factor, column[row] as number, vector[row] as number);\n }\n}\n\n/**\n * Factor the columns in place: LINPACK's `dqrdc2`, R's modification of\n * `dqrdc` with limited column pivoting.\n *\n * The routine walks the columns left to right, keeping in `qraux` a running\n * norm of each column's remaining part — downdated after every reflection\n * rather than recomputed, and recomputed only when the downdate would lose\n * too much (the `1e-6` rule). A column whose running norm has fallen below\n * `tolerance` times its original norm moves to the right edge and the\n * columns behind it shift left, so the columns that survive keep their\n * original order — which is why R can report the coefficients of a rank-\n * deficient fit in their own slots, with `NA` in the slot of the column it\n * dropped.\n *\n * On return each column holds its part of R above the diagonal and the\n * Householder vector below it, `qraux` holds the leading entry of each\n * reflector — or, for a column that was never reflected, its running norm,\n * which is what R reports there.\n *\n * @returns `qraux`, the column order, and the rank.\n */\nfunction decompose(\n columns: number[][],\n tolerance: number,\n rows: number,\n): { householders: number[]; pivot: number[]; rank: number } {\n const width = columns.length;\n const pivot = columns.map((_, column) => column);\n const qraux = columns.map((column) => norm(column, 0));\n // `work(j, 1)`: the norm the running value was last set from.\n const lastNorms = [...qraux];\n // `work(j, 2)`: the original norm, with 1 substituted for zero so that an\n // all-zero column compares as negligible rather than dividing by zero.\n const originalNorms = qraux.map((value) => value || 1);\n // R's `k`, one past the count of columns still in play.\n let k = width + 1;\n\n for (let step = 0; step < Math.min(rows, width); step++) {\n // Cycle the columns from `step` rightward until one with a non-negligible\n // norm is found. `step + 1` is R's one-based `l`.\n while (\n step + 1 < k &&\n (qraux[step] as number) < (originalNorms[step] as number) * tolerance\n ) {\n moveToEnd(columns, step);\n moveToEnd(pivot, step);\n moveToEnd(qraux, step);\n moveToEnd(lastNorms, step);\n moveToEnd(originalNorms, step);\n k -= 1;\n }\n\n // The last row leaves nothing to reflect. R skips it and keeps the entry\n // as it stands, which is how a design with more columns than rows still\n // resolves the coefficients it can.\n if (step === rows - 1) {\n continue;\n }\n reflect(columns, qraux, lastNorms, step, rows);\n }\n\n return { householders: qraux, pivot, rank: Math.min(k - 1, rows) };\n}\n\n/**\n * Build the Householder reflector of one column, apply it to the columns to\n * its right, and downdate their running norms. On return `qraux[step]` holds\n * the reflector's leading entry.\n */\nfunction reflect(\n columns: number[][],\n qraux: number[],\n lastNorms: number[],\n step: number,\n rows: number,\n): void {\n const column = columns[step] as number[];\n const length = norm(column, step);\n if (length === 0) {\n return;\n }\n // Reflect away from the leading entry, so that nothing cancels.\n const pivotNorm = (column[step] as number) < 0 ? -length : length;\n\n // `dscal(n, 1/nrmxl, x)`: LINPACK multiplies by the reciprocal rather than\n // dividing, and the two round differently. Dividing lands one ulp away from\n // R in the Householder vector of the very first fixture.\n const reciprocal = 1 / pivotNorm;\n for (let row = step; row < rows; row++) {\n column[row] = (column[row] as number) * reciprocal;\n }\n const leading = 1 + (column[step] as number);\n column[step] = leading;\n\n for (let index = step + 1; index < columns.length; index++) {\n const other = columns[index] as number[];\n // `ddot` and `daxpy`, each product rounded once with its addition.\n let inner = 0;\n for (let row = step; row < rows; row++) {\n inner = fusedMultiplyAdd(column[row] as number, other[row] as number, inner);\n }\n const factor = -inner / leading;\n for (let row = step; row < rows; row++) {\n other[row] = fusedMultiplyAdd(factor, column[row] as number, other[row] as number);\n }\n\n // Downdate the running norm of the column just updated, or recompute it\n // when the downdate would cancel too much.\n const running = qraux[index] as number;\n if (running !== 0) {\n const ratio = Math.abs(other[step] as number) / running;\n const remaining = Math.max(1 - ratio * ratio, 0);\n if (Math.abs(remaining) < 1e-6) {\n qraux[index] = norm(other, step + 1);\n lastNorms[index] = qraux[index] as number;\n } else {\n qraux[index] = running * Math.sqrt(remaining);\n }\n }\n }\n\n qraux[step] = leading;\n column[step] = -pivotNorm;\n}\n\n/**\n * Solve the leading `rank` columns of the triangular system, as `dqrsl`\n * does: column by column from the last, each solved coefficient subtracted\n * from the entries above it with `daxpy`.\n */\nfunction backSubstitute(\n compact: Matrix,\n response: Vector,\n rank: number,\n): number[] {\n const { nrow } = compact;\n const entry = (i: number, j: number): number =>\n compact.data[j * nrow + i] as number;\n const solved = response.slice(0, rank);\n\n for (let column = rank - 1; column >= 0; column--) {\n const value = (solved[column] as number) / entry(column, column);\n solved[column] = value;\n for (let row = 0; row < column; row++) {\n solved[row] = fusedMultiplyAdd(-value, entry(row, column), solved[row] as number);\n }\n }\n\n return solved;\n}\n\n/** Move one entry of an array to its end, sliding the rest left. */\nfunction moveToEnd<T>(track: T[], from: number): void {\n const [moved] = track.splice(from, 1) as [T];\n track.push(moved);\n}\n\n/**\n * The Euclidean length of a column from `from` down: the BLAS `dnrm2`.\n *\n * For values in the ordinary range `dnrm2` is a sum of squares under a\n * square root; its scaling engages only near overflow or underflow, which\n * no fixture and no teaching dataset reaches. Written as a fold —\n * `Math.hypot(...column)` overflows the call stack past about a million\n * entries, and its rounding is not specified — with each square rounded\n * once into the sum, as the contracted BLAS does.\n */\nfunction norm(column: Vector, from: number): number {\n let squares = 0;\n for (let row = from; row < column.length; row++) {\n const value = column[row] as number;\n squares = fusedMultiplyAdd(value, value, squares);\n }\n return Math.sqrt(squares);\n}\n",
|
|
10
|
+
"/**\n * The LU factorization with partial pivoting, and what R reads off it:\n * `solve()`, `det()`, `determinant()`, `rcond()` and `norm()`.\n *\n * R's `solve(a, b)` is LAPACK `dgesv` — `dgetrf` to factor, `dgetrs` to\n * substitute — followed by `dgecon`'s condition estimate and an error when\n * that estimate falls below `tol`. `det()` factors the same way and then\n * exponentiates a sum of logarithms of the diagonal, which is why the\n * determinant of an integer matrix comes back as `30.000000000000004`. This\n * module follows those routines step for step, with the arithmetic of the\n * reference BLAS build the fixtures come from (each product rounded once\n * into its sum — see `fusedMultiplyAdd`), so that the factorization, the\n * solves and the determinant pin bit for bit. Verified in `lu.test.ts`.\n * The 2 × 2 special case in `../matrix.ts` is the same algorithm and the\n * two agree exactly on every fixture of the interactive demo.\n *\n * Three departures from R, each stated where it applies: `rcond` is the\n * exact one-norm ratio rather than `dgecon`'s estimate; a vector right-hand\n * side comes back as a plain array rather than R's named vector; and a\n * negative or NaN tolerance is refused where R would skip the check.\n *\n * Index loops throughout: a factorization addresses single entries by\n * position, and this one follows `dgetf2` and `dtrsm` as written.\n */\n\nimport { fusedMultiplyAdd } from \"../arith\";\nimport { make, type Dimnames, type Matrix } from \"./matrix\";\nimport { isMatrix, t, type MatrixOrVector } from \"./ops\";\nimport { qr, qrR } from \"./qr\";\nimport type { Vector } from \"./vector\";\n\n/**\n * The smallest normal double, LAPACK's `dlamch(\"S\")`.\n *\n * Below it, `dgetf2` divides the column by the pivot instead of multiplying\n * by the reciprocal, because the reciprocal would overflow.\n */\nconst SMALLEST_NORMAL = 2.2250738585072014e-308;\n\n/** R's `solve()` result on a square matrix, factored. */\nexport interface LuDecomposition {\n /**\n * The compact factorization, LAPACK's: `U` on and above the diagonal, the\n * multipliers of the unit lower triangle `L` below it, rows already\n * interchanged.\n */\n readonly lu: Matrix;\n /**\n * The row interchanges, LAPACK's `ipiv` **zero-based**: at step `i` row\n * `i` was swapped with row `pivots[i]`. Apply them in order to recover\n * `P` such that `P A = L U`. Plural, and not `pivot` as in\n * `QrDecomposition`, because this is a list of interchanges rather than\n * a column order.\n */\n readonly pivots: readonly number[];\n /**\n * The zero-based index of the first exactly zero pivot — LAPACK's `info`,\n * less one — or null if the factorization completed. R reports it as\n * `U[i,i] = 0`, one-based.\n */\n readonly zeroPivot: number | null;\n}\n\n/**\n * Factor a square matrix, as LAPACK's `dgetrf` does.\n *\n * @param a The matrix. The function does not modify it.\n * @returns The compact factorization, the row interchanges, and the first\n * zero pivot if any. A zero pivot does not stop the factorization, as it\n * does not in LAPACK.\n * @throws RangeError If the matrix is not square.\n * @throws TypeError If `a` is not a matrix.\n */\nexport function lu(a: Matrix): LuDecomposition {\n requireSquare(a, \"a\");\n const n = a.nrow;\n const data = Float64Array.from(a.data);\n const pivots = new Array<number>(n).fill(0);\n let zeroPivot: number | null = null;\n const entry = (i: number, j: number): number => data[j * n + i] as number;\n\n for (let j = 0; j < n; j++) {\n // Partial pivoting: the largest entry on or below the diagonal leads;\n // the first of equals, as `idamax` picks it.\n let p = j;\n for (let i = j + 1; i < n; i++) {\n if (Math.abs(entry(i, j)) > Math.abs(entry(p, j))) {\n p = i;\n }\n }\n pivots[j] = p;\n\n if (entry(p, j) !== 0) {\n if (p !== j) {\n swapRows(data, n, j, p);\n }\n // `dgetf2` scales by the reciprocal of the pivot, and divides only\n // where the reciprocal would overflow. The difference reaches the\n // result: see the note on `../matrix.ts`.\n const pivot = entry(j, j);\n if (Math.abs(pivot) >= SMALLEST_NORMAL) {\n const reciprocal = 1 / pivot;\n for (let i = j + 1; i < n; i++) {\n data[j * n + i] = entry(i, j) * reciprocal;\n }\n } else {\n for (let i = j + 1; i < n; i++) {\n data[j * n + i] = entry(i, j) / pivot;\n }\n }\n } else if (zeroPivot === null) {\n zeroPivot = j;\n }\n\n // The rank-one update of the trailing block, `dger`: each product is\n // rounded once into the entry it updates.\n for (let jj = j + 1; jj < n; jj++) {\n const factor = -entry(j, jj);\n for (let i = j + 1; i < n; i++) {\n data[jj * n + i] = fusedMultiplyAdd(entry(i, j), factor, entry(i, jj));\n }\n }\n }\n\n return { lu: make(n, n, data, null), pivots, zeroPivot };\n}\n\n/** Exchange two rows of a column-major square buffer in place. */\nfunction swapRows(data: Float64Array, n: number, i: number, p: number): void {\n for (let j = 0; j < n; j++) {\n const held = data[j * n + i] as number;\n data[j * n + i] = data[j * n + p] as number;\n data[j * n + p] = held;\n }\n}\n\nexport interface SolveOptions {\n /**\n * The reciprocal condition number below which the system is refused as\n * computationally singular. R's default is `.Machine$double.eps`; zero\n * skips the check, as it does in R. R also skips it for a negative or\n * NA `tol`; the port refuses those with a `RangeError` — a deliberate\n * narrowing, as `matrix()` narrows R's recycling.\n */\n readonly tolerance?: number;\n}\n\n/** The singularity tolerance of R's `solve()`: one machine epsilon. */\nexport const DEFAULT_SOLVE_TOLERANCE = Number.EPSILON;\n\n/**\n * R's `solve(a)`, `solve(a, b)` and `solve(a, B)`: the inverse, the solution\n * of `a x = b` for a vector, or the solution of `a X = B` for a matrix.\n *\n * @param a The square coefficient matrix.\n * @param b The right-hand side, or the options when only the inverse is\n * wanted. A vector gives a plain array (R names it by the column names of\n * `a`; the port carries no names on a bare array — plan Q11). A matrix\n * gives a matrix whose row names are the column names of `a` and whose\n * column names are those of `b`; the inverse has the column names of `a`\n * as rows and the row names of `a` as columns, as R's does.\n * @param options The singularity tolerance.\n * @returns The solution.\n * @throws RangeError If `a` is not square or has no rows, `b` does not\n * conform or has no columns, the factorization meets an exactly zero\n * pivot, or the reciprocal condition number is below the tolerance —\n * each in R's own words. As in R, a non-finite entry in `a` leaves the\n * condition unchecked: R's `dgecon` reports a bad norm and `solve()`\n * goes on.\n * @throws TypeError If `a` or `b` is neither a matrix nor an array.\n */\nexport function solve(a: Matrix, options?: SolveOptions): Matrix;\nexport function solve(a: Matrix, b: Vector, options?: SolveOptions): number[];\nexport function solve(a: Matrix, b: Matrix, options?: SolveOptions): Matrix;\nexport function solve(\n a: Matrix,\n second?: MatrixOrVector | SolveOptions,\n third: SolveOptions = {},\n): Matrix | number[] {\n const [b, options] = splitArguments(second, third);\n const { tolerance = DEFAULT_SOLVE_TOLERANCE } = options;\n if (!(tolerance >= 0)) {\n throw new RangeError(`tolerance must be a non-negative number, got ${tolerance}`);\n }\n requireSquare(a, \"a\");\n const n = a.nrow;\n if (n === 0) {\n throw new RangeError(\"'a' is 0-diml\");\n }\n\n const rhs: Matrix =\n b === undefined\n ? identityData(n)\n : isMatrix(b)\n ? b\n : make(b.length, 1, Float64Array.from(b), null);\n if (rhs.ncol === 0) {\n throw new RangeError(\"no right-hand side in 'b'\");\n }\n if (rhs.nrow !== n) {\n throw new RangeError(\n `'b' (${rhs.nrow} x ${rhs.ncol}) must be compatible with 'a' (${n} x ${n})`,\n );\n }\n\n const factored = lu(a);\n if (factored.zeroPivot !== null) {\n const i = factored.zeroPivot + 1;\n throw new RangeError(\n `Lapack routine dgesv: system is exactly singular: U[${i},${i}] = 0`,\n );\n }\n const solution = substitute(factored, rhs);\n const anorm = oneNorm(a.data, n, n);\n if (tolerance > 0 && Number.isFinite(anorm)) {\n // The inverse is the solution itself when that is what was asked for.\n const inverse = b === undefined ? solution : substitute(factored, identityData(n));\n const reciprocal = 1 / (anorm * oneNorm(inverse, n, n));\n if (reciprocal < tolerance) {\n throw new RangeError(\n `system is computationally singular: reciprocal condition number = ${formatG(reciprocal)}`,\n );\n }\n }\n\n if (b !== undefined && !isMatrix(b)) {\n return Array.from(solution);\n }\n const aColumns = a.dimnames?.[1] ?? null;\n const dimnames: Dimnames | null =\n b === undefined\n ? a.dimnames === null\n ? null\n : [aColumns, a.dimnames[0]]\n : aColumns === null && (rhs.dimnames?.[1] ?? null) === null\n ? null\n : [aColumns, rhs.dimnames?.[1] ?? null];\n return make(n, rhs.ncol, solution, dimnames);\n}\n\n/** Tell `solve(a, options)` from `solve(a, b, options)`. */\nfunction splitArguments(\n second: MatrixOrVector | SolveOptions | undefined,\n third: SolveOptions,\n): [MatrixOrVector | undefined, SolveOptions] {\n if (second === undefined) {\n return [undefined, third];\n }\n if (Array.isArray(second) || (typeof second === \"object\" && \"data\" in second && \"nrow\" in second)) {\n return [second as MatrixOrVector, third];\n }\n if (typeof second === \"object\" && second !== null && !ArrayBuffer.isView(second)) {\n return [undefined, second as SolveOptions];\n }\n throw new TypeError(\"expected a Matrix, an array of numbers, or the options\");\n}\n\n/** The identity as a matrix, the right-hand side of `solve(a)`. */\nfunction identityData(n: number): Matrix {\n const data = new Float64Array(n * n);\n for (let i = 0; i < n; i++) {\n data[i * n + i] = 1;\n }\n return make(n, n, data, null);\n}\n\n/**\n * Solve the factored system against a right-hand side, as `dgetrs` does:\n * the row interchanges applied to `B`, then each column forward through\n * the unit lower triangle and back through the upper one (`dtrsm`). A zero\n * entry is skipped as `dtrsm` skips it, which is how a negative zero on\n * the right-hand side survives, as it does in R.\n */\nfunction substitute(factored: LuDecomposition, rhs: Matrix): Float64Array {\n const { lu: compact, pivots } = factored;\n const n = compact.nrow;\n const entry = (i: number, j: number): number => compact.data[j * n + i] as number;\n const data = Float64Array.from(rhs.data);\n const width = rhs.ncol;\n\n pivots.forEach((p, i) => {\n if (p !== i) {\n for (let j = 0; j < width; j++) {\n const held = data[j * n + i] as number;\n data[j * n + i] = data[j * n + p] as number;\n data[j * n + p] = held;\n }\n }\n });\n\n for (let j = 0; j < width; j++) {\n const at = (i: number): number => data[j * n + i] as number;\n for (let k = 0; k < n; k++) {\n if (at(k) !== 0) {\n for (let i = k + 1; i < n; i++) {\n data[j * n + i] = fusedMultiplyAdd(-at(k), entry(i, k), at(i));\n }\n }\n }\n for (let k = n - 1; k >= 0; k--) {\n if (at(k) !== 0) {\n data[j * n + k] = at(k) / entry(k, k);\n for (let i = 0; i < k; i++) {\n data[j * n + i] = fusedMultiplyAdd(-at(k), entry(i, k), at(i));\n }\n }\n }\n }\n\n return data;\n}\n\n/**\n * R's `det()`: the determinant, through the factorization and a sum of\n * logarithms, as R computes it. A 0 × 0 matrix has determinant 1, as in R.\n *\n * @throws RangeError If the matrix is not square.\n * @throws TypeError If `a` is not a matrix.\n */\nexport function det(a: Matrix): number {\n const { modulus, sign } = determinant(a);\n return sign * Math.exp(modulus);\n}\n\n/**\n * R's `determinant()`: the logarithm of the absolute determinant and its\n * sign. An exactly singular matrix reports `-Infinity` and sign 1, so that\n * `det()` is a positive zero, as R's is.\n *\n * @throws RangeError If the matrix is not square.\n * @throws TypeError If `a` is not a matrix.\n */\nexport function determinant(a: Matrix): { readonly modulus: number; readonly sign: 1 | -1 } {\n requireSquare(a, \"x\");\n const factored = lu(a);\n if (factored.zeroPivot !== null) {\n return { modulus: Number.NEGATIVE_INFINITY, sign: 1 };\n }\n const n = a.nrow;\n let modulus = 0;\n let sign: 1 | -1 = 1;\n for (let i = 0; i < n; i++) {\n const pivot = factored.lu.data[i * n + i] as number;\n if (factored.pivots[i] !== i) {\n sign = -sign as 1 | -1;\n }\n if (pivot < 0) {\n sign = -sign as 1 | -1;\n }\n modulus += Math.log(Math.abs(pivot));\n }\n return { modulus, sign };\n}\n\n/**\n * The reciprocal condition number in the one-norm, R's `rcond(x)`:\n * `1 / (norm(x) * norm(solve(x)))` for a square matrix, 0 when it is\n * exactly singular, and Infinity for a 0 × 0 matrix. A matrix that is not\n * square goes through the triangular factor of its QR, as R's does\n * (`rcond(qr.R(qr(x)))`, transposed first when wide).\n *\n * R's `rcond()` and `solve()` read an estimate of this number from LAPACK's\n * `dgecon` rather than computing it, and the port computes it exactly. On\n * the fixtures the two agree to the last bit for most matrices (3a, 3c, 3d,\n * 3e, 3i) and differ by one unit in the last place on two (3b, 3h);\n * `solve()`'s error message matches R's to the six digits it prints on\n * every singular case pinned. The estimate bounds the norm of the inverse\n * from below, so R's number is never smaller than the port's.\n *\n * @throws RangeError If an entry is not finite — R's \"error code -5 from\n * Lapack routine 'dgecon()'\", because `dgecon` refuses a norm it cannot\n * read.\n * @throws TypeError If `a` is not a matrix.\n */\nexport function rcond(a: Matrix): number {\n if (!isMatrix(a)) {\n throw new TypeError(\"expected a Matrix\");\n }\n if (a.nrow !== a.ncol) {\n return rcond(qrR(qr(a.nrow < a.ncol ? t(a) : a)));\n }\n const n = a.nrow;\n if (n === 0) {\n return Number.POSITIVE_INFINITY;\n }\n const anorm = oneNorm(a.data, n, n);\n if (!Number.isFinite(anorm)) {\n throw new RangeError(\"error code -5 from Lapack routine 'dgecon()'\");\n }\n const factored = lu(a);\n if (factored.zeroPivot !== null) {\n return 0;\n }\n return 1 / (anorm * oneNorm(substitute(factored, identityData(n)), n, n));\n}\n\n/**\n * R's `norm()` types. `\"O\"` is R's default; the letters are accepted in\n * either case, as R's `lsame` accepts them. R's `\"2\"`, the spectral norm,\n * needs a singular value decomposition, which this plan leaves out.\n */\nexport type MatrixNormType = \"O\" | \"1\" | \"I\" | \"F\" | \"E\" | \"M\" | \"o\" | \"i\" | \"f\" | \"e\" | \"m\";\n\n/**\n * R's `norm(x, type)`: the one-norm (`\"O\"` or `\"1\"`, the largest absolute\n * column sum), the infinity norm (`\"I\"`, the largest absolute row sum), the\n * Frobenius norm (`\"F\"` or `\"E\"`), or the largest absolute entry (`\"M\"`).\n * Named `matrixNorm` because `norm` in this entry is the vector length.\n *\n * @throws RangeError If the type is none of those, in R's words.\n * @throws TypeError If `a` is not a matrix.\n */\nexport function matrixNorm(a: Matrix, type: MatrixNormType = \"O\"): number {\n if (!isMatrix(a)) {\n throw new TypeError(\"expected a Matrix\");\n }\n const { nrow, ncol, data } = a;\n switch (type.toUpperCase()) {\n case \"O\":\n case \"1\":\n return oneNorm(data, nrow, ncol);\n case \"I\": {\n let largest = 0;\n for (let i = 0; i < nrow; i++) {\n let total = 0;\n for (let j = 0; j < ncol; j++) {\n total += Math.abs(data[j * nrow + i] as number);\n }\n largest = Math.max(largest, total);\n }\n return largest;\n }\n case \"F\":\n case \"E\": {\n let squares = 0;\n data.forEach((value) => {\n squares += value * value;\n });\n return Math.sqrt(squares);\n }\n case \"M\":\n return data.reduce((largest, value) => Math.max(largest, Math.abs(value)), 0);\n default:\n throw new RangeError(\n `argument type[1]='${type}' must be one of 'M','1','O','I','F' or 'E'`,\n );\n }\n}\n\n/** The largest absolute column sum of a column-major buffer. */\nfunction oneNorm(data: Float64Array, nrow: number, ncol: number): number {\n let largest = 0;\n for (let j = 0; j < ncol; j++) {\n let total = 0;\n for (let i = 0; i < nrow; i++) {\n total += Math.abs(data[j * nrow + i] as number);\n }\n largest = Math.max(largest, total);\n }\n return largest;\n}\n\n/** Refuse a non-matrix, then a matrix that is not square, in R's words for the argument. */\nfunction requireSquare(a: Matrix, name: string): void {\n if (!isMatrix(a)) {\n throw new TypeError(\"expected a Matrix\");\n }\n if (a.nrow !== a.ncol) {\n throw new RangeError(\n name === \"a\"\n ? `'a' (${a.nrow} x ${a.ncol}) must be square`\n : \"'x' must be a square matrix\",\n );\n }\n}\n\n/**\n * C's `%g` with six significant digits, the form R prints a reciprocal\n * condition number in: the value rounded to six digits, in exponent\n * notation when that rounded value's exponent is below -4 or 6 or more,\n * with trailing zeros dropped and at least two exponent digits.\n */\nfunction formatG(value: number): string {\n if (value === 0 || !Number.isFinite(value)) {\n return String(value);\n }\n // Rounding first, as C does: 9.9999999e-5 is 0.0001, not 1e-04.\n const [mantissa, power] = value.toExponential(5).split(\"e\") as [string, string];\n const exponent = Number(power);\n const trim = (digits: string): string =>\n digits.includes(\".\") ? digits.replace(/0+$/, \"\").replace(/\\.$/, \"\") : digits;\n if (exponent < -4 || exponent >= 6) {\n const sign = exponent < 0 ? \"-\" : \"+\";\n return `${trim(mantissa)}e${sign}${String(Math.abs(exponent)).padStart(2, \"0\")}`;\n }\n return trim(value.toFixed(Math.max(0, 5 - exponent)));\n}\n",
|
|
11
|
+
"/**\n * R's named vector: values with a name each, in order.\n *\n * A coefficient vector is the case that matters here — `coef(fit)` in R\n * prints `(Intercept)`, `x`, `z`, `x:z` above its values, and `summary()`\n * lines the standard errors up under the same names. The port holds the\n * names alongside the values rather than in an object keyed by name,\n * because a JavaScript object moves an integer-like key to the front: a\n * column called `\"1\"` would jump ahead of `(Intercept)`. The pair of arrays\n * keeps R's order, and pairs with `dimnames` on a `Matrix`, so the column\n * names of a model matrix become the names of a fit with no reshaping\n * (plan Q11).\n *\n * `null` is R's `NA`: a coefficient the fit could not identify.\n */\n\n/** Values with a name each, in order. */\nexport interface NamedVector {\n readonly names: readonly string[];\n /** One value per name; null where R reports `NA`. */\n readonly values: readonly (number | null)[];\n}\n\n/**\n * Pair names with values.\n *\n * @param names One name per value. Copied.\n * @param values One value per name; null for R's `NA`. Copied.\n * @throws RangeError If the two lengths differ.\n */\nexport function namedVector(\n names: readonly string[],\n values: readonly (number | null)[],\n): NamedVector {\n if (names.length !== values.length) {\n throw new RangeError(\n `a named vector needs one name per value: ${names.length} names, ${values.length} values`,\n );\n }\n return { names: [...names], values: [...values] };\n}\n\n/**\n * Read one value by name. R's `v[[\"name\"]]`.\n *\n * @returns The value, null where the entry is R's `NA`, or undefined when\n * no entry carries the name. With a repeated name, the first.\n */\nexport function lookup(v: NamedVector, name: string): number | null | undefined {\n const index = v.names.indexOf(name);\n return index === -1 ? undefined : (v.values[index] as number | null);\n}\n",
|
|
12
|
+
"/**\n * R's `model.matrix()`: a data frame and a list of terms → the design\n * matrix, with the column names `lm()` gives its coefficients.\n *\n * R builds this from a formula. The port has no formulas (CLAUDE.md: the\n * canonical form is explicit column names in an options object), so a\n * model is a list of terms — a column name for a main effect, an array of\n * column names for an interaction — and the intercept is a flag. R's\n * `y ~ x * z + w` is `{ outcome: \"y\", terms: [\"x\", \"z\", \"w\", [\"x\", \"z\"]] }`.\n *\n * The columns come out in R's order, whatever order the terms were written\n * in: the intercept, then the terms by degree — every main effect before\n * every two-way interaction before every three-way — and within a degree in\n * the order given. A term written twice enters once. The `assign` vector is\n * R's: the index of the term each column came from, 0 for the intercept.\n *\n * Rows with a missing (non-finite) value in the outcome or in any column a\n * term names are dropped, R's `model.frame()` under `na.omit`; the indices\n * of the rows kept are returned, so a fit can pad its results back to the\n * input order (the `na.exclude` convention every fit in this package uses).\n * Only numeric columns can enter; R's factors and contrasts are out of\n * scope.\n */\n\nimport { frameRows, requireNumericColumn, type DataFrame } from \"../frame\";\nimport { make, type Matrix } from \"./matrix\";\n\n/**\n * One term of a model: a column name for a main effect, or the column names\n * of an interaction, R's `a:b`.\n */\nexport type Term = string | readonly string[];\n\n/** Which columns make the model. */\nexport interface ModelSpec {\n /**\n * The outcome column. It enters no design column, but a row missing it is\n * dropped, as `model.frame()` drops it. Optional here; `lm()` requires it.\n */\n readonly outcome?: string;\n /** The terms, in any order. R's order is restored. */\n readonly terms: readonly Term[];\n /** Whether to lead with a column of ones. True by default, R's `+ 1`. */\n readonly intercept?: boolean;\n}\n\n/** A design matrix and where its rows came from. */\nexport interface ModelMatrix {\n /**\n * The design, one row per complete data row, with the coefficient names\n * as column names: `(Intercept)`, the main effects, the interactions as\n * `a:b`.\n */\n readonly matrix: Matrix;\n /** The data rows the design holds, in input order. */\n readonly rows: readonly number[];\n /** R's `assign`: the term each column came from, 0 for the intercept. */\n readonly assign: readonly number[];\n /** R's `term.labels`: the terms in the order the columns follow. */\n readonly termLabels: readonly string[];\n}\n\n/**\n * Build the design matrix of a model, as R's `model.matrix()` does.\n *\n * @param data The frame holding every column the model names.\n * @param spec The outcome, the terms, and the intercept flag.\n * @returns The design, the rows it kept, and R's `assign` and term labels.\n * @throws RangeError If a named column is absent or not numeric (through\n * `requireNumericColumn`, naming the option it arrived through), if the\n * frame is ragged, or if an interaction term names no column.\n */\nexport function modelMatrix(data: DataFrame, spec: ModelSpec): ModelMatrix {\n const { outcome, intercept = true } = spec;\n const rowCount = frameRows(data);\n const terms = orderTerms(spec.terms);\n\n const columns = new Map<string, readonly number[]>();\n const read = (name: string, role: string): readonly number[] => {\n const held = columns.get(name);\n if (held !== undefined) {\n return held;\n }\n const column = requireNumericColumn(data, name, role);\n columns.set(name, column);\n return column;\n };\n if (outcome !== undefined) {\n read(outcome, \"outcome\");\n }\n terms.forEach((factors) => {\n factors.forEach((name) => read(name, \"terms\"));\n });\n\n // R's na.omit: a row with a missing value in any model column leaves.\n // NaN is this library's missing value, and an infinity would poison the\n // fit the same way, so \"complete\" means finite everywhere.\n const involved = [...columns.values()];\n const rows = Array.from({ length: rowCount }, (_, row) => row).filter((row) =>\n involved.every((column) => Number.isFinite(column[row])),\n );\n\n const termColumns = terms.map((factors) =>\n rows.map((row) =>\n factors.reduce((product, name) => product * ((columns.get(name) as readonly number[])[row] as number), 1),\n ),\n );\n const design = intercept ? [rows.map(() => 1), ...termColumns] : termColumns;\n const names = [\n ...(intercept ? [\"(Intercept)\"] : []),\n ...terms.map((factors) => factors.join(\":\")),\n ];\n const assign = [\n ...(intercept ? [0] : []),\n ...terms.map((_, index) => index + 1),\n ];\n\n const n = rows.length;\n const p = design.length;\n const buffer = new Float64Array(n * p);\n design.forEach((column, j) => {\n buffer.set(column, j * n);\n });\n\n return {\n matrix: make(n, p, buffer, p === 0 ? null : [null, names]),\n rows,\n assign,\n termLabels: names.slice(intercept ? 1 : 0),\n };\n}\n\n/**\n * Normalize the terms to arrays of column names, drop repeats, and put them\n * in R's order: by degree, then as written.\n *\n * @throws RangeError If a term names no column.\n */\nfunction orderTerms(terms: readonly Term[]): readonly (readonly string[])[] {\n const seen = new Set<string>();\n const unique: (readonly string[])[] = [];\n terms.forEach((term) => {\n const factors = typeof term === \"string\" ? [term] : term;\n if (factors.length === 0) {\n throw new RangeError(\"an interaction term needs at least one column name\");\n }\n // R treats `a:b` and `b:a` as one term; the first spelling wins.\n const key = [...factors].sort().join(\"\u0000\");\n if (!seen.has(key)) {\n seen.add(key);\n unique.push(factors);\n }\n });\n // A stable sort by degree keeps the written order within a degree, as R's\n // terms() does.\n return unique\n .map((factors, index) => ({ factors, index }))\n .sort((a, b) => a.factors.length - b.factors.length || a.index - b.index)\n .map(({ factors }) => factors);\n}\n",
|
|
13
|
+
"/**\n * Special functions that the statistics in `core/` build on.\n *\n * JavaScript has no `lgamma` and no incomplete beta, so the distribution\n * functions need them here. R gets the same quantities from its own C\n * routines; this module is the port's replacement.\n *\n * Every function is pure. None of them touch the DOM or hold state.\n */\n\nimport { sum } from \"./arith\";\n\n/**\n * Lanczos parameter and coefficients, g = 607/128 with 15 terms.\n *\n * This set holds about 15 correct digits over the whole positive real line,\n * which is what the t quantiles need at 1e-12 relative tolerance.\n */\nconst LANCZOS_G = 607 / 128;\n\nconst LANCZOS_LEAD = 0.99999999999999709182;\n\nconst LANCZOS_TAIL: readonly number[] = [\n 57.156235665862923517, -59.597960355475491248, 14.136097974741747174,\n -0.49191381609762019978, 0.33994649984811888699e-4,\n 0.46523628927048575665e-4, -0.98374475304879564677e-4,\n 0.15808870322491248884e-3, -0.21026444172410488319e-3,\n 0.2174396181152126432e-3, -0.16431810653676389022e-3,\n 0.84418223983852743293e-4, -0.2619083840158140867e-4,\n 0.36899182659531622704e-5,\n];\n\nconst LOG_SQRT_TWO_PI = 0.5 * Math.log(2 * Math.PI);\n\n/**\n * The Lanczos series A(x), the slowly varying part of the approximation\n *\n * Γ(x) = √(2π) · (x + g − ½)^(x − ½) · e^−(x + g − ½) · A(x)\n */\nfunction lanczosSeries(x: number): number {\n return (\n LANCZOS_LEAD +\n sum(LANCZOS_TAIL.map((coefficient, index) => coefficient / (x + index)))\n );\n}\n\n/**\n * The natural log of the gamma function, R's `lgamma()`.\n *\n * @param x A positive number.\n * @returns log Γ(x), or NaN if x is zero or less.\n */\nexport function logGamma(x: number): number {\n if (!(x > 0)) {\n return Number.NaN;\n }\n const shifted = x + LANCZOS_G - 0.5;\n return (\n LOG_SQRT_TWO_PI +\n (x - 0.5) * Math.log(shifted) -\n shifted +\n Math.log(lanczosSeries(x))\n );\n}\n\n/**\n * The natural log of the beta function, R's `lbeta()`.\n *\n * The obvious route, `logGamma(a) + logGamma(b) - logGamma(a + b)`, subtracts\n * numbers near 600 for the degrees of freedom this package plots, and loses\n * about three digits doing so. Expanding the Lanczos form first cancels the\n * large terms by hand: the exponential parts collapse to the constant\n * −(g − ½), and the logarithmic parts become ratios that stay of order one.\n * What is left has no cancellation at all.\n *\n * Both ratios go through `log1p`. Each one sits just below 1, and taking the\n * quotient first would round away the small part that the log then reads —\n * a loss that grows with the larger argument, reaching 1e-13 by b = 2500.\n *\n * @param a A positive number.\n * @param b A positive number.\n * @returns log B(a, b), or NaN if either argument is zero or less.\n */\nexport function logBeta(a: number, b: number): number {\n if (!(a > 0) || !(b > 0)) {\n return Number.NaN;\n }\n const shiftedSum = a + b + LANCZOS_G - 0.5;\n return (\n LOG_SQRT_TWO_PI -\n (LANCZOS_G - 0.5) +\n Math.log(lanczosSeries(a)) +\n Math.log(lanczosSeries(b)) -\n Math.log(lanczosSeries(a + b)) +\n (a - 0.5) * Math.log1p(-b / shiftedSum) +\n (b - 0.5) * Math.log1p(-a / shiftedSum) -\n 0.5 * Math.log(shiftedSum)\n );\n}\n\n/** Iteration caps and guards for the continued fraction. */\nconst FRACTION_MAX_STEPS = 400;\nconst FRACTION_EPSILON = 3e-16;\nconst FRACTION_FLOOR = 1e-300;\n\n/**\n * The continued fraction of the incomplete beta function, by the modified\n * Lentz method.\n *\n * The loop is index based on purpose: it refines one running value step by\n * step and stops on a convergence test, so there is no array to map over.\n */\nfunction betaContinuedFraction(x: number, a: number, b: number): number {\n const total = a + b;\n const aPlus = a + 1;\n const aMinus = a - 1;\n\n let c = 1;\n let d = 1 - (total * x) / aPlus;\n if (Math.abs(d) < FRACTION_FLOOR) {\n d = FRACTION_FLOOR;\n }\n d = 1 / d;\n let value = d;\n\n for (let step = 1; step <= FRACTION_MAX_STEPS; step += 1) {\n const twice = 2 * step;\n\n const even = (step * (b - step) * x) / ((aMinus + twice) * (a + twice));\n d = 1 + even * d;\n if (Math.abs(d) < FRACTION_FLOOR) {\n d = FRACTION_FLOOR;\n }\n c = 1 + even / c;\n if (Math.abs(c) < FRACTION_FLOOR) {\n c = FRACTION_FLOOR;\n }\n d = 1 / d;\n value *= d * c;\n\n const odd = (-(a + step) * (total + step) * x) / ((a + twice) * (aPlus + twice));\n d = 1 + odd * d;\n if (Math.abs(d) < FRACTION_FLOOR) {\n d = FRACTION_FLOOR;\n }\n c = 1 + odd / c;\n if (Math.abs(c) < FRACTION_FLOOR) {\n c = FRACTION_FLOOR;\n }\n d = 1 / d;\n\n const delta = d * c;\n value *= delta;\n if (Math.abs(delta - 1) < FRACTION_EPSILON) {\n break;\n }\n }\n\n return value;\n}\n\n/**\n * The regularized incomplete beta function I_x(a, b), R's `pbeta()`.\n *\n * The continued fraction converges quickly only on one side of the\n * distribution, so the function evaluates the mirrored form when x sits above\n * the switch point and takes the complement.\n *\n * @param x A value between 0 and 1.\n * @param a A positive shape.\n * @param b A positive shape.\n * @returns The share of the beta density below x, or NaN for a bad shape.\n */\nexport function incompleteBeta(x: number, a: number, b: number): number {\n if (Number.isNaN(x)) {\n return Number.NaN;\n }\n if (x <= 0) {\n return 0;\n }\n if (x >= 1) {\n return 1;\n }\n return incompleteBetaSplit(x, 1 - x, a, b);\n}\n\n/**\n * The regularized incomplete beta function, told x and 1 − x separately.\n *\n * A caller that can write down both members of the pair should use this\n * instead of `incompleteBeta`. Once x is within 1e-16 of 1, the double\n * holding it has no room left for 1 − x, and rebuilding the complement by\n * subtraction throws away the very digits the answer rests on. `pt()` reads\n * both straight off t and df, so it gives up nothing.\n *\n * The two are treated as an exact pair, not as one value and a derived one:\n * each logarithm is taken from whichever member still carries its precision.\n *\n * @param x A value between 0 and 1.\n * @param complement The value of 1 − x, computed without subtracting.\n * @param a A positive shape.\n * @param b A positive shape.\n * @returns The share of the beta density below x, or NaN for a bad shape.\n */\nexport function incompleteBetaSplit(\n x: number,\n complement: number,\n a: number,\n b: number,\n): number {\n if (Number.isNaN(x) || Number.isNaN(complement) || !(a > 0) || !(b > 0)) {\n return Number.NaN;\n }\n if (x <= 0) {\n return 0;\n }\n if (complement <= 0) {\n return 1;\n }\n\n const logX = complement < 0.5 ? Math.log1p(-complement) : Math.log(x);\n const logComplement = x < 0.5 ? Math.log1p(-x) : Math.log(complement);\n const front = Math.exp(a * logX + b * logComplement - logBeta(a, b));\n\n if (x < (a + 1) / (a + b + 2)) {\n return (front * betaContinuedFraction(x, a, b)) / a;\n }\n return 1 - (front * betaContinuedFraction(complement, b, a)) / b;\n}\n\n/** Iteration cap and tolerance for the incomplete gamma routines. */\nconst GAMMA_MAX_STEPS = 1000;\nconst GAMMA_EPSILON = 3e-16;\n\n/**\n * P(a, x), the regularized lower incomplete gamma, by its power series.\n *\n * The series converges quickly while x stays below a + 1. Index loop with a\n * stated reason: it sums one term at a time and stops on a size test.\n */\nfunction lowerGammaSeries(a: number, x: number): number {\n let term = 1 / a;\n let total = term;\n for (let step = 1; step <= GAMMA_MAX_STEPS; step += 1) {\n term *= x / (a + step);\n total += term;\n if (Math.abs(term) < Math.abs(total) * GAMMA_EPSILON) {\n break;\n }\n }\n return total * Math.exp(-x + a * Math.log(x) - logGamma(a));\n}\n\n/**\n * Q(a, x), the regularized upper incomplete gamma, by the modified Lentz\n * method on its continued fraction.\n *\n * This is the branch that carries the far normal tail, where the answer runs\n * to 1e-70 and below and must stay accurate relative to itself.\n */\nfunction upperGammaFraction(a: number, x: number): number {\n let b = x + 1 - a;\n let c = 1 / FRACTION_FLOOR;\n let d = 1 / b;\n let value = d;\n\n for (let step = 1; step <= GAMMA_MAX_STEPS; step += 1) {\n const numerator = -step * (step - a);\n b += 2;\n d = numerator * d + b;\n if (Math.abs(d) < FRACTION_FLOOR) {\n d = FRACTION_FLOOR;\n }\n c = b + numerator / c;\n if (Math.abs(c) < FRACTION_FLOOR) {\n c = FRACTION_FLOOR;\n }\n d = 1 / d;\n const delta = d * c;\n value *= delta;\n if (Math.abs(delta - 1) < GAMMA_EPSILON) {\n break;\n }\n }\n\n return value * Math.exp(-x + a * Math.log(x) - logGamma(a));\n}\n\n/** Q(a, x), taking whichever of the two routes converges at this x. */\nfunction upperGamma(a: number, x: number): number {\n if (x <= 0) {\n return 1;\n }\n if (!Number.isFinite(x)) {\n return 0;\n }\n return x < a + 1 ? 1 - lowerGammaSeries(a, x) : upperGammaFraction(a, x);\n}\n\n/**\n * The standard normal distribution function, R's `pnorm()`.\n *\n * Built on the identity Φ(−z) = ½ · Q(½, z²/2), which keeps the far tail\n * accurate relative to itself rather than losing it against 1. The\n * non-central t needs Φ(−ncp) down to 1e-72 at the widest slider settings.\n *\n * @param z Where to evaluate the distribution.\n * @returns A probability between 0 and 1, or NaN for a NaN input.\n */\nexport function normalCdf(z: number): number {\n if (Number.isNaN(z)) {\n return Number.NaN;\n }\n const lower = 0.5 * upperGamma(0.5, 0.5 * z * z);\n return z > 0 ? 1 - lower : lower;\n}\n\n/** The largest double below 1. The inverse never returns 1 itself. */\nconst BELOW_ONE = 1 - Number.EPSILON / 2;\n\n/** Iteration cap for the inverse. Newton needs about 8 steps; 200 is slack. */\nconst INVERSE_MAX_STEPS = 200;\n\n/**\n * A starting point for the inverse, from Numerical Recipes.\n *\n * Both branches are approximations only. The Newton loop that follows carries\n * the value the rest of the way, so the guess needs to be in the right\n * neighborhood, not accurate.\n */\nfunction inverseGuess(p: number, a: number, b: number): number {\n if (a >= 1 && b >= 1) {\n const tail = p < 0.5 ? p : 1 - p;\n const t = Math.sqrt(-2 * Math.log(tail));\n const normal =\n (p < 0.5 ? -1 : 1) *\n ((2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t);\n const scale = (normal * normal - 3) / 6;\n const harmonic = 2 / (1 / (2 * a - 1) + 1 / (2 * b - 1));\n const w =\n (normal * Math.sqrt(scale + harmonic)) / harmonic -\n (1 / (2 * b - 1) - 1 / (2 * a - 1)) *\n (scale + 5 / 6 - 2 / (3 * harmonic));\n return a / (a + b * Math.exp(2 * w));\n }\n\n const lower = Math.exp(a * Math.log(a / (a + b))) / a;\n const upper = Math.exp(b * Math.log(b / (a + b))) / b;\n const total = lower + upper;\n if (p < lower / total) {\n return Math.pow(a * total * p, 1 / a);\n }\n return 1 - Math.pow(b * total * (1 - p), 1 / b);\n}\n\n/**\n * The inverse of the regularized incomplete beta function, R's `qbeta()`.\n *\n * Newton's method on I_x(a, b) − p, with the exact beta density as the\n * derivative. Every step keeps a bracket, and a step that leaves the bracket\n * falls back to bisection, so the loop cannot run away on a poor guess.\n *\n * @param p A probability between 0 and 1.\n * @param a A positive shape.\n * @param b A positive shape.\n * @returns The x where I_x(a, b) equals p, or NaN for a bad shape.\n */\nexport function inverseIncompleteBeta(\n p: number,\n a: number,\n b: number,\n): number {\n if (Number.isNaN(p) || !(a > 0) || !(b > 0)) {\n return Number.NaN;\n }\n if (p <= 0) {\n return 0;\n }\n if (p >= 1) {\n return 1;\n }\n\n const logBetaValue = logBeta(a, b);\n let lower = 0;\n let upper = 1;\n let x = inverseGuess(p, a, b);\n if (!(x > 0) || !(x < 1)) {\n x = 0.5;\n }\n\n // Index loop with a stated reason: this refines a single root and stops on\n // a convergence test.\n for (let step = 0; step < INVERSE_MAX_STEPS; step += 1) {\n const residual = incompleteBeta(x, a, b) - p;\n if (residual < 0) {\n lower = x;\n } else {\n upper = x;\n }\n\n const density = Math.exp(\n (a - 1) * Math.log(x) + (b - 1) * Math.log1p(-x) - logBetaValue,\n );\n let next =\n density > 0 && Number.isFinite(density) ? x - residual / density : Number.NaN;\n if (!(next > lower) || !(next < upper)) {\n next = 0.5 * (lower + upper);\n }\n if (next === x) {\n break;\n }\n\n const moved = Math.abs(next - x);\n x = next;\n if (moved <= Number.EPSILON * x) {\n break;\n }\n }\n\n return Math.min(x, BELOW_ONE);\n}\n",
|
|
14
|
+
"/**\n * The t distribution: density, cumulative probability, and quantile.\n *\n * These are the port of R's `dt()`, `pt()`, and `qt()`. `plot_t_test()` in\n * `../compstatslib/R/t_statistic_plot.R` draws both hypothesis curves from\n * them. Verified against R in `tdist.test.ts`.\n *\n * All three take an optional non-centrality, as in R. Left out or given as 0,\n * they run the central path, which `plot_t_test()` draws the null hypothesis\n * from; given a non-zero value they run the non-central path behind the\n * alternative-hypothesis curve, where the non-centrality is the t statistic\n * itself.\n *\n * A note on how close this comes to R. The non-central routines follow R's\n * own `pnt.c` and `dnt.c` step for step, down to the iteration cap and the\n * error bound. That is on purpose. Both stop the series on an *absolute*\n * bound, so where they stop is part of the answer, and a tidier stopping rule\n * would move the last digits away from R rather than toward the truth. It\n * also means this port inherits R's limits: at a large non-centrality the\n * series terms are built by repeated subtraction and go to noise once they\n * fall below about 1e-16, which is what R's own \"full precision may not have\n * been achieved\" warning reports. Densities near 1e-50 there agree with R in\n * absolute terms only.\n */\n\nimport {\n incompleteBetaSplit,\n inverseIncompleteBeta,\n logBeta,\n normalCdf,\n} from \"./special\";\n\n/** True when a non-centrality was given and is not the central case. */\nfunction isNonCentral(ncp: number | undefined): ncp is number {\n return ncp !== undefined && ncp !== 0;\n}\n\n/** True when any argument rules the answer out before any work starts. */\nfunction isBadArgument(value: number, df: number, ncp: number | undefined): boolean {\n return (\n Number.isNaN(value) ||\n !(df > 0) ||\n (ncp !== undefined && Number.isNaN(ncp))\n );\n}\n\n/**\n * The density of the t distribution, R's `dt()`.\n *\n * @param x Where to evaluate the density.\n * @param df Degrees of freedom. Any positive number, whole or not.\n * @param ncp The non-centrality. Left out, or 0, gives the central density.\n * @returns The density, or NaN if df is zero or less.\n */\nexport function dt(x: number, df: number, ncp?: number): number {\n if (isBadArgument(x, df, ncp)) {\n return Number.NaN;\n }\n return isNonCentral(ncp)\n ? nonCentralDensity(x, df, ncp)\n : centralDensity(x, df);\n}\n\n/**\n * The share of the distribution below x, R's `pt()`.\n *\n * @param x Where to evaluate the distribution.\n * @param df Degrees of freedom. Any positive number, whole or not.\n * @param ncp The non-centrality. Left out, or 0, gives the central case.\n * @returns A probability between 0 and 1, or NaN if df is zero or less.\n */\nexport function pt(x: number, df: number, ncp?: number): number {\n if (isBadArgument(x, df, ncp)) {\n return Number.NaN;\n }\n return isNonCentral(ncp)\n ? nonCentralProbability(x, df, ncp)\n : centralProbability(x, df);\n}\n\n/**\n * The value with probability p below it, R's `qt()`.\n *\n * @param p A probability between 0 and 1. The ends give infinities, as in R.\n * @param df Degrees of freedom. Any positive number, whole or not.\n * @param ncp The non-centrality. Left out, or 0, gives the central case.\n * @returns The quantile, or NaN for a p outside 0 to 1 or a df of zero or\n * less.\n */\nexport function qt(p: number, df: number, ncp?: number): number {\n if (isBadArgument(p, df, ncp) || p < 0 || p > 1) {\n return Number.NaN;\n }\n return isNonCentral(ncp)\n ? nonCentralQuantile(p, df, ncp)\n : centralQuantile(p, df);\n}\n\n/**\n * The density, computed in logs.\n *\n * f(x) = (1 + x²/df)^−(df+1)/2 / (√df · B(½, df/2))\n *\n * `log1p` keeps the small-x end accurate, and the log form keeps the large-df\n * end from overflowing on the way to a modest answer.\n */\nfunction centralDensity(x: number, df: number): number {\n if (!Number.isFinite(x)) {\n return 0;\n }\n const logDensity =\n -0.5 * Math.log(df) -\n logBeta(0.5, df / 2) -\n ((df + 1) / 2) * Math.log1p((x * x) / df);\n return Math.exp(logDensity);\n}\n\n/**\n * The cumulative probability, from the upper tail outward.\n *\n * Working from whichever tail holds the smaller mass avoids subtracting two\n * nearly equal numbers, which is what makes the far tails accurate.\n */\nfunction centralProbability(x: number, df: number): number {\n if (x === 0) {\n return 0.5;\n }\n if (x === Number.POSITIVE_INFINITY) {\n return 1;\n }\n if (x === Number.NEGATIVE_INFINITY) {\n return 0;\n }\n const tail = upperTail(Math.abs(x), df);\n return x < 0 ? tail : 1 - tail;\n}\n\n/**\n * The mass above t, for a t of zero or more.\n *\n * P(T > t) = ½ · I_z(df/2, ½), z = df / (df + t²)\n *\n * This is the incomplete-beta identity R's `pt()` uses. Both z and 1 − z come\n * straight out of t and df, each to full precision, so the pair goes to\n * `incompleteBetaSplit` rather than letting it subtract one from the other. A\n * small t drives z against 1, where a subtracted complement would keep only a\n * handful of digits; a large t makes the answer tiny, where building it as\n * ½ − something would cancel it away to nothing.\n */\nfunction upperTail(t: number, df: number): number {\n const squared = t * t;\n if (!Number.isFinite(squared)) {\n // t is past 1e154. The mass above it is far below the smallest double.\n return 0;\n }\n const total = df + squared;\n return 0.5 * incompleteBetaSplit(df / total, squared / total, df / 2, 0.5);\n}\n\n/** How many Newton steps the quantile takes after the beta inverse. */\nconst POLISH_MAX_STEPS = 4;\n\n/**\n * The quantile, by inverting the incomplete beta and then polishing.\n *\n * The symmetry of the distribution turns a one-sided probability into a\n * two-sided mass, which the beta inverse handles. Which shape goes first\n * depends on which side is small: taking the large side would compute the\n * answer as one minus something near one and throw away digits.\n */\nfunction centralQuantile(p: number, df: number): number {\n if (p === 0.5) {\n return 0;\n }\n if (p <= 0) {\n return Number.NEGATIVE_INFINITY;\n }\n if (p >= 1) {\n return Number.POSITIVE_INFINITY;\n }\n\n const tail = p < 0.5 ? p : 1 - p;\n const sign = p < 0.5 ? -1 : 1;\n const twoSided = 2 * tail;\n\n let squared: number;\n if (twoSided > 0.5) {\n // Near the middle: the answer is small, so solve for x²/(df + x²).\n const near = inverseIncompleteBeta(1 - twoSided, 0.5, df / 2);\n squared = (df * near) / (1 - near);\n } else {\n // Out in a tail: the answer is large, so solve for df/(df + x²).\n const far = inverseIncompleteBeta(twoSided, df / 2, 0.5);\n squared = (df * (1 - far)) / far;\n }\n\n return sign * polish(Math.sqrt(squared), tail, df);\n}\n\n/**\n * Newton steps on the upper tail, to take the last digits home.\n *\n * The beta inverse lands close but loses a little precision on the way\n * through x² and the square root. Solving P(T > t) = tail directly, with the\n * density as the derivative, recovers it. The step is measured against the\n * tail rather than against p, so a p near 1 does not lose its digits to the\n * subtraction.\n */\nfunction polish(start: number, tail: number, df: number): number {\n let t = start;\n\n // Index loop with a stated reason: this refines a single root and stops on\n // a convergence test.\n for (let step = 0; step < POLISH_MAX_STEPS; step += 1) {\n const density = centralDensity(t, df);\n if (!(density > 0) || !Number.isFinite(t)) {\n break;\n }\n\n const move = (upperTail(t, df) - tail) / density;\n const next = t + move;\n if (!(next > 0) || !Number.isFinite(next) || Math.abs(move) > 0.25 * t) {\n break;\n }\n if (next === t) {\n break;\n }\n\n t = next;\n if (Math.abs(move) <= Number.EPSILON * t) {\n break;\n }\n }\n\n return t;\n}\n\n/**\n * Iteration cap and error bound for the AS 243 series.\n *\n * These are R's own values from `pnt.c`. They are part of the answer, not a\n * detail: the series stops on an *absolute* bound, so where it stops decides\n * the last digits. Holding R's numbers here is what makes this port agree\n * with R rather than merely come close to the true value.\n */\nconst SERIES_MAX_STEPS = 1000;\nconst SERIES_ERROR_MAX = 1e-12;\n\n/** Above this non-centrality R leaves the series for a normal fit. */\nconst SERIES_NCP_LIMIT_SQUARED = 2 * Math.LN2 * 1022;\n\n/** Above this many degrees of freedom R does the same. */\nconst SERIES_DF_LIMIT = 4e5;\n\nconst SQRT_TWO_OVER_PI = Math.sqrt(2 / Math.PI);\n\n/**\n * The share of the non-central distribution below x, R's `pt(x, df, ncp)`.\n *\n * The series only runs on values of zero or more, so a negative x is\n * reflected through the origin along with the non-centrality. That names the\n * other tail, which the caller flips back.\n */\nfunction nonCentralProbability(x: number, df: number, ncp: number): number {\n if (x === Number.POSITIVE_INFINITY) {\n return 1;\n }\n if (x === Number.NEGATIVE_INFINITY) {\n return 0;\n }\n\n const reflected = x < 0;\n const t = reflected ? -x : x;\n const delta = reflected ? -ncp : ncp;\n const lower =\n df > SERIES_DF_LIMIT || delta * delta > SERIES_NCP_LIMIT_SQUARED\n ? normalApproximation(t, df, delta)\n : lenthSeries(t, df, delta);\n\n return reflected ? 1 - lower : lower;\n}\n\n/**\n * Abramowitz and Stegun 26.7.10, the fit R falls back on.\n *\n * Past a non-centrality of about 37.6 the leading Poisson weight\n * exp(−ncp²/2) drops below the smallest double and the series has nothing\n * left to sum. The sliders reach that: a difference of 4 with a standard\n * deviation of 1 over 500 observations puts the non-centrality near 89.\n */\nfunction normalApproximation(t: number, df: number, delta: number): number {\n const shrink = 1 / (4 * df);\n const spread = Math.sqrt(1 + t * t * 2 * shrink);\n return normalCdf((t * (1 - shrink) - delta) / spread);\n}\n\n/**\n * The AS 243 twin series of Lenth (1989), as R's `pnt.c` runs it.\n *\n * The distribution is a Poisson mixture of incomplete beta terms. Both\n * families of terms step by recurrence rather than being evaluated afresh,\n * and `remaining` carries the Poisson mass still to come, which bounds the\n * error of stopping early.\n *\n * @param t Where to evaluate, zero or more.\n * @param df Degrees of freedom.\n * @param delta The non-centrality, of either sign.\n */\nfunction lenthSeries(t: number, df: number, delta: number): number {\n const squared = t * t;\n const total = df + squared;\n const x = squared / total;\n const complement = df / total;\n\n let sum = 0;\n if (x > 0) {\n const lambda = delta * delta;\n let oddWeight = 0.5 * Math.exp(-0.5 * lambda);\n let evenWeight = SQRT_TWO_OVER_PI * oddWeight * delta;\n\n let remaining = 0.5 - oddWeight;\n if (remaining < 1e-7) {\n remaining = -0.5 * Math.expm1(-0.5 * lambda);\n }\n\n let a = 0.5;\n const b = 0.5 * df;\n const powered = Math.pow(complement, b);\n const logBetaValue = logBeta(0.5, b);\n\n let oddTerm = incompleteBetaSplit(x, complement, a, b);\n let oddStep = 2 * powered * Math.exp(a * Math.log(x) - logBetaValue);\n let evenTerm = 1 - powered;\n let evenStep = b * x * powered;\n sum = oddWeight * oddTerm + evenWeight * evenTerm;\n\n // Index loop with a stated reason: each pass advances one Poisson term by\n // recurrence and the loop stops on an error bound, not on a data length.\n for (let step = 1; step <= SERIES_MAX_STEPS; step += 1) {\n a += 1;\n oddTerm -= oddStep;\n evenTerm -= evenStep;\n oddStep *= (x * (a + b - 1)) / a;\n evenStep *= (x * (a + b - 0.5)) / (a + 0.5);\n oddWeight *= lambda / (2 * step);\n evenWeight *= lambda / (2 * step + 1);\n remaining -= oddWeight;\n if (remaining <= 0) {\n break;\n }\n sum += oddWeight * oddTerm + evenWeight * evenTerm;\n if (Math.abs(2 * remaining * (oddTerm - oddStep)) < SERIES_ERROR_MAX) {\n break;\n }\n }\n }\n\n return Math.min(Math.max(sum + normalCdf(-delta), 0), 1);\n}\n\n/**\n * The density of the non-central distribution, R's `dt(x, df, ncp)`.\n *\n * Away from zero the density is read off the distribution function, using\n * that its derivative can be written as a difference between two evaluations\n * two degrees of freedom apart. R notes in `dnt.c` that this still cancels,\n * and it does: at x = 1 the two probabilities agree to about two digits\n * before the difference is taken. Following R's route rather than a cleaner\n * one is deliberate, since the fixtures are R's own output.\n */\nfunction nonCentralDensity(x: number, df: number, ncp: number): number {\n if (!Number.isFinite(x)) {\n return 0;\n }\n\n if (Math.abs(x) > Math.sqrt(df * Number.EPSILON)) {\n const stepped = x * Math.sqrt((df + 2) / df);\n const difference =\n nonCentralProbability(stepped, df + 2, ncp) -\n nonCentralProbability(x, df, ncp);\n return (df / Math.abs(x)) * Math.abs(difference);\n }\n\n // At zero that difference is 0/0. The density there is the central one\n // damped by the non-centrality, exp(−ncp²/2).\n return Math.exp(\n -0.5 * Math.log(df) - logBeta(0.5, df / 2) - 0.5 * ncp * ncp,\n );\n}\n\n/** Iteration cap for the non-central quantile search. */\nconst QUANTILE_MAX_STEPS = 200;\n\n/**\n * The non-central quantile, R's `qt(p, df, ncp)`.\n *\n * There is no closed form to invert, so this brackets the root and then works\n * inward. R bisects to a relative 1e-13; Newton steps get there in a handful\n * of passes instead, with the bracket kept so that a step into the flat part\n * of a far tail cannot run away.\n */\nfunction nonCentralQuantile(p: number, df: number, ncp: number): number {\n if (p <= 0) {\n return Number.NEGATIVE_INFINITY;\n }\n if (p >= 1) {\n return Number.POSITIVE_INFINITY;\n }\n\n // Widen outward from the non-centrality until the root is enclosed.\n let upper = Math.max(1, ncp);\n while (\n Number.isFinite(upper) &&\n nonCentralProbability(upper, df, ncp) < p\n ) {\n upper *= 2;\n }\n let lower = Math.min(-1, -ncp);\n while (\n Number.isFinite(lower) &&\n nonCentralProbability(lower, df, ncp) > p\n ) {\n lower *= 2;\n }\n\n let t = 0.5 * (lower + upper);\n\n // Index loop with a stated reason: this refines a single root and stops on\n // a convergence test.\n for (let step = 0; step < QUANTILE_MAX_STEPS; step += 1) {\n const residual = nonCentralProbability(t, df, ncp) - p;\n if (residual < 0) {\n lower = t;\n } else {\n upper = t;\n }\n\n const density = nonCentralDensity(t, df, ncp);\n let next =\n density > 0 && Number.isFinite(density) ? t - residual / density : Number.NaN;\n if (!(next > lower) || !(next < upper)) {\n next = 0.5 * (lower + upper);\n }\n if (next === t) {\n break;\n }\n\n const moved = Math.abs(next - t);\n t = next;\n if (moved <= Number.EPSILON * Math.abs(t)) {\n break;\n }\n }\n\n return t;\n}\n",
|
|
15
|
+
"/**\n * R's `lm()` over a data frame, with what `summary.lm()` reads off the fit.\n *\n * `lm()` is `model.matrix()` followed by `lm.fit()`, and `lm.fit()` is\n * `dqrls`: the `qr()` of `qr.ts` — LINPACK's `dqrdc2` with its limited\n * column pivoting — followed by `dqrsl`'s coefficients and residuals, with\n * the fitted values as `y` minus the residuals. The port runs that same\n * arithmetic, so the coefficients, fitted values and residuals pin bit for\n * bit against R. The summary statistics — R², adjusted R², σ, the standard\n * errors and the t and p values — follow `summary.lm()`'s formulas but not\n * its rounding step for step (`chol2inv` and `pt`), and are verified at a\n * stated tolerance. See `lm.test.ts`.\n *\n * Coefficients come back as a `NamedVector` in R's order, `null` where R\n * reports `NA` for an aliased column. Fitted values and residuals are padded\n * with NaN to the input length where a row was dropped for a missing value,\n * R's `na.exclude`, which is the convention every fit in this package uses.\n */\n\nimport { mean, sum, zipWith } from \"../arith\";\nimport type { DataFrame } from \"../frame\";\nimport { pt } from \"../tdist\";\nimport { modelMatrix, type ModelSpec } from \"./modelMatrix\";\nimport { namedVector, type NamedVector } from \"./namedVector\";\nimport { DEFAULT_QR_TOLERANCE, qr, qrCoef, qrResid, type QrDecomposition } from \"./qr\";\nimport type { Vector } from \"./vector\";\n\n/** The model, with the outcome required, and the rank tolerance. */\nexport interface LmOptions extends ModelSpec {\n /** The column to fit. */\n readonly outcome: string;\n /** How far a column's norm may collapse before it is aliased. R's `lm.fit()` default. */\n readonly tolerance?: number;\n}\n\n/** R's `summary(fit)$fstatistic`. */\nexport interface FStatistic {\n readonly value: number;\n readonly numdf: number;\n readonly dendf: number;\n}\n\n/** A fitted linear model and its summary. */\nexport interface LmFit {\n /** `coef(fit)`: one entry per design column, null where R reports `NA`. */\n readonly coefficients: NamedVector;\n /** `coef(summary(fit))[, \"Std. Error\"]`, null for an aliased term. */\n readonly standardErrors: NamedVector;\n /** `coef(summary(fit))[, \"t value\"]`, null for an aliased term. */\n readonly tValues: NamedVector;\n /** `coef(summary(fit))[, \"Pr(>|t|)\"]`, null for an aliased term. */\n readonly pValues: NamedVector;\n /** The fitted outcome of each data row, in input order; NaN for a row dropped. */\n readonly fitted: Vector;\n /** The outcome minus the fit, in input order; NaN for a row dropped. */\n readonly residuals: Vector;\n /** The number of columns the fit could identify. */\n readonly rank: number;\n /** `fit$df.residual`: rows fitted minus rank. */\n readonly dfResidual: number;\n /** `summary(fit)$r.squared`. */\n readonly rSquared: number;\n /** `summary(fit)$adj.r.squared`. */\n readonly adjRSquared: number;\n /** `summary(fit)$sigma`: the residual standard error. */\n readonly sigma: number;\n /** `summary(fit)$fstatistic`, or null when the model has no term beyond the intercept. */\n readonly fStatistic: FStatistic | null;\n /** The data rows the fit used, in input order. */\n readonly rows: readonly number[];\n /** R's `term.labels`. */\n readonly termLabels: readonly string[];\n}\n\n/**\n * Fit a linear model, as R's `lm()` does.\n *\n * @param data The frame holding every column the model names.\n * @param options The outcome, the terms, the intercept flag, and the rank\n * tolerance.\n * @returns The fit and its summary.\n * @throws RangeError If a named column is absent or not numeric, if the\n * frame is ragged, or if no row is complete — R's \"0 (non-NA) cases\".\n */\nexport function lm(data: DataFrame, options: LmOptions): LmFit {\n const { outcome, intercept = true, tolerance = DEFAULT_QR_TOLERANCE } = options;\n const design = modelMatrix(data, options);\n const { rows } = design;\n const n = rows.length;\n if (n === 0) {\n throw new RangeError(\"0 (non-NA) cases\");\n }\n // modelMatrix has already checked the outcome column.\n const outcomeColumn = data[outcome] as Vector;\n const y = rows.map((row) => outcomeColumn[row] as number);\n\n const factored = qr(design.matrix, { tolerance });\n const coefficients = qrCoef(factored, y);\n const residuals = qrResid(factored, y);\n const fitted = zipWith(y, residuals, (value, residual) => value - residual);\n const names = design.matrix.dimnames?.[1] ?? [];\n\n const { rank } = factored;\n const dfResidual = n - rank;\n const interceptCount = intercept ? 1 : 0;\n const rss = sum(residuals.map((r) => r * r));\n const centered = intercept ? mean(fitted) : 0;\n const mss = sum(fitted.map((f) => (f - centered) * (f - centered)));\n const resvar = rss / dfResidual;\n const numdf = rank - interceptCount;\n // summary.lm() reports 0 for both when nothing beyond the intercept was\n // fitted, rather than the rounding noise the formula would give.\n const rSquared = numdf > 0 ? mss / (mss + rss) : 0;\n const adjRSquared =\n numdf > 0 ? 1 - (1 - rSquared) * ((n - interceptCount) / dfResidual) : 0;\n\n const standardErrors = standardErrorsOf(factored, resvar, names.length);\n const tValues = zipWith(coefficients, standardErrors, (b, se) =>\n b === null || se === null ? null : b / se,\n );\n const pValues = tValues.map((tv) =>\n tv === null ? null : 2 * pt(-Math.abs(tv), dfResidual),\n );\n\n return {\n coefficients: namedVector(names, coefficients),\n standardErrors: namedVector(names, standardErrors),\n tValues: namedVector(names, tValues),\n pValues: namedVector(names, pValues),\n fitted: padded(fitted, rows, outcomeColumn.length),\n residuals: padded(residuals, rows, outcomeColumn.length),\n rank,\n dfResidual,\n rSquared,\n adjRSquared,\n sigma: Math.sqrt(resvar),\n fStatistic:\n numdf > 0 ? { value: mss / numdf / resvar, numdf, dendf: dfResidual } : null,\n rows,\n termLabels: design.termLabels,\n };\n}\n\n/**\n * The standard errors, `summary.lm()`'s `sqrt(diag(chol2inv(R)) * resvar)`\n * over the leading `rank` columns of the factorization, placed back in the\n * original column order; null for an aliased column.\n *\n * `chol2inv(R)` is `(RᵀR)⁻¹ = R⁻¹ R⁻ᵀ`, whose diagonal is the sum of\n * squares of each row of `R⁻¹`. `R⁻¹` comes from back substitution against\n * the identity.\n */\nfunction standardErrorsOf(\n factored: QrDecomposition,\n resvar: number,\n width: number,\n): (number | null)[] {\n const { rank, pivot } = factored;\n const { nrow } = factored.qr;\n const r = (i: number, j: number): number => factored.qr.data[j * nrow + i] as number;\n\n // Column k of R⁻¹ solves R x = e_k; the entries above row k are the only\n // ones that can be non-zero.\n const inverse = Array.from({ length: rank }, (_, k) => {\n const x = new Array<number>(rank).fill(0);\n x[k] = 1 / r(k, k);\n for (let i = k - 1; i >= 0; i--) {\n let total = 0;\n for (let j = i + 1; j <= k; j++) {\n total += r(i, j) * (x[j] as number);\n }\n x[i] = -total / r(i, i);\n }\n return x;\n });\n const diagonal = Array.from({ length: rank }, (_, i) =>\n sum(inverse.map((columnOfInverse) => (columnOfInverse[i] as number) ** 2)),\n );\n\n const errors = new Array<number | null>(width).fill(null);\n pivot.slice(0, rank).forEach((original, position) => {\n errors[original] = Math.sqrt((diagonal[position] as number) * resvar);\n });\n return errors;\n}\n\n/** Spread values fitted on `rows` back over `length` slots, NaN elsewhere. */\nfunction padded(values: Vector, rows: readonly number[], length: number): number[] {\n const out = new Array<number>(length).fill(Number.NaN);\n rows.forEach((row, index) => {\n out[row] = values[index] as number;\n });\n return out;\n}\n",
|
|
16
|
+
"/**\n * R's `var()`, `cov()` and `cor()`.\n *\n * R computes a covariance in two passes: the mean of each column, refined\n * once by adding the mean of the residuals (its `cov.c` does this to shave\n * the rounding off a long sum), then the sum of products of deviations over\n * `n − 1`. A correlation is the covariance matrix scaled by the square roots\n * of its diagonal, clamped to `[-1, 1]`, with an exact 1 on the diagonal.\n * The port follows those steps. R accumulates in `long double` where the\n * platform has one; the conformance fixtures come from arm64, where it does\n * not, and the values are verified at a relative tolerance (plan Q1).\n *\n * A missing value gives NaN, as R's default `use = \"everything\"` gives NA.\n * A constant column gives NaN for its correlations, where R warns \"the\n * standard deviation is zero\" and gives NA.\n */\n\nimport { sum } from \"../arith\";\nimport { isMatrix, type MatrixOrVector } from \"./ops\";\nimport { make, type Dimnames, type Matrix } from \"./matrix\";\nimport type { Vector } from \"./vector\";\n\n/**\n * R's `mean()` as `cov()` computes it: the plain mean, refined by the mean\n * of the residuals. A non-finite first pass is returned as it is.\n */\nfunction refinedMean(values: Vector): number {\n const n = values.length;\n const first = sum(values) / n;\n if (!Number.isFinite(first)) {\n return first;\n }\n return first + sum(values.map((value) => value - first)) / n;\n}\n\n/** The sum of products of deviations over `n − 1`; NaN below two values. */\nfunction covariance(\n a: Vector,\n meanA: number,\n b: Vector,\n meanB: number,\n): number {\n const n = a.length;\n if (n < 2) {\n return Number.NaN;\n }\n let total = 0;\n for (let i = 0; i < n; i++) {\n total += ((a[i] as number) - meanA) * ((b[i] as number) - meanB);\n }\n return total / (n - 1);\n}\n\n/** Refuse two vectors of different lengths, in R's words. */\nfunction requireSameLength(a: Vector, b: Vector): void {\n if (a.length !== b.length) {\n throw new RangeError(\"incompatible dimensions\");\n }\n}\n\n/**\n * R's `var(x)` of a vector: the sample variance with the `n − 1` divisor.\n *\n * @returns The variance, or NaN below two values or with a missing value.\n */\nexport function variance(a: Vector): number {\n const center = refinedMean(a);\n return covariance(a, center, a, center);\n}\n\n/**\n * R's `cov()`: the covariance of two vectors, or the covariance matrix of\n * the columns of a matrix.\n *\n * @param x A vector, or a matrix whose columns are the variables.\n * @param y The second vector when `x` is a vector.\n * @returns The covariance, or the symmetric covariance matrix with the\n * column names of `x` on both sides.\n * @throws RangeError If two vectors differ in length.\n */\nexport function cov(x: Vector, y: Vector): number;\nexport function cov(x: Matrix): Matrix;\nexport function cov(x: MatrixOrVector, y?: Vector): number | Matrix {\n if (isMatrix(x)) {\n return pairwise(x, false);\n }\n if (y === undefined) {\n throw new RangeError(\"cov() of a vector needs a second vector\");\n }\n requireSameLength(x, y);\n return covariance(x, refinedMean(x), y, refinedMean(y));\n}\n\n/**\n * R's `cor()`: the Pearson correlation of two vectors, or the correlation\n * matrix of the columns of a matrix.\n *\n * @param x A vector, or a matrix whose columns are the variables.\n * @param y The second vector when `x` is a vector.\n * @returns The correlation, clamped to `[-1, 1]`, or the symmetric\n * correlation matrix with an exact 1 on its diagonal. NaN where a\n * variable has no spread.\n * @throws RangeError If two vectors differ in length.\n */\nexport function cor(x: Vector, y: Vector): number;\nexport function cor(x: Matrix): Matrix;\nexport function cor(x: MatrixOrVector, y?: Vector): number | Matrix {\n if (isMatrix(x)) {\n return pairwise(x, true);\n }\n if (y === undefined) {\n throw new RangeError(\"cor() of a vector needs a second vector\");\n }\n requireSameLength(x, y);\n const meanX = refinedMean(x);\n const meanY = refinedMean(y);\n const spread = Math.sqrt(covariance(x, meanX, x, meanX) * covariance(y, meanY, y, meanY));\n return spread === 0 ? Number.NaN : clamp(covariance(x, meanX, y, meanY) / spread);\n}\n\n/** The covariance or correlation matrix of the columns, as R builds it. */\nfunction pairwise(m: Matrix, correlation: boolean): Matrix {\n const { nrow, ncol } = m;\n const columns = Array.from({ length: ncol }, (_, j) =>\n Array.from(m.data.subarray(j * nrow, (j + 1) * nrow)),\n );\n const means = columns.map(refinedMean);\n const data = new Float64Array(ncol * ncol);\n for (let i = 0; i < ncol; i++) {\n for (let j = 0; j <= i; j++) {\n const value = covariance(\n columns[i] as number[],\n means[i] as number,\n columns[j] as number[],\n means[j] as number,\n );\n data[j * ncol + i] = value;\n data[i * ncol + j] = value;\n }\n }\n if (correlation) {\n const spreads = Array.from({ length: ncol }, (_, i) => Math.sqrt(data[i * ncol + i] as number));\n for (let i = 0; i < ncol; i++) {\n for (let j = 0; j <= i; j++) {\n const divisor = (spreads[i] as number) * (spreads[j] as number);\n const value =\n i === j ? 1 : divisor === 0 ? Number.NaN : clamp((data[j * ncol + i] as number) / divisor);\n data[j * ncol + i] = value;\n data[i * ncol + j] = value;\n }\n }\n }\n const names = m.dimnames?.[1] ?? null;\n const dimnames: Dimnames | null = names === null ? null : [names, names];\n return make(ncol, ncol, data, dimnames);\n}\n\n/** R's clamp of a correlation to `[-1, 1]`. */\nfunction clamp(value: number): number {\n return value > 1 ? 1 : value < -1 ? -1 : value;\n}\n",
|
|
17
|
+
"/**\n * The eigendecomposition of a symmetric matrix, R's\n * `eigen(x, symmetric = TRUE)`.\n *\n * R goes through LAPACK's `dsyevr`. The port uses cyclic Jacobi rotations,\n * which for the matrices a teaching library sees — a covariance of a handful\n * of variables — converge to machine precision in a few sweeps and are\n * short enough to read. Eigenvalues come back descending, as R's do, and\n * the eigenvectors are orthonormal columns. Verified against R in\n * `eigen.test.ts`: the eigenvalues to a relative `1e-12`, the vectors up to\n * sign (plan Q1).\n *\n * **Signs are this port's own.** LAPACK leaves the sign of each eigenvector\n * to the arithmetic; the port makes the entry of largest magnitude positive\n * (a tie goes to the first), which is the rule `pca.ts` already uses, so\n * that the same input gives the same picture every time.\n *\n * Two departures from R, both stated: a matrix that is not symmetric is\n * refused, where R silently reads its lower triangle; and the eigenvector\n * matrix carries the row names of the input as its row names, where R's\n * carries none — a loading without its variable is unreadable. The refusals\n * R does make are followed in its order and its words: a non-square matrix,\n * then a 0 x 0 one, then a missing or infinite entry (fixture 5e).\n *\n * Index loops throughout: a rotation addresses entries by position.\n */\n\nimport { make, type Matrix } from \"./matrix\";\nimport type { Vector } from \"./vector\";\n\n/** R's `eigen()` result for a symmetric matrix. */\nexport interface SymmetricEigen {\n /** The eigenvalues, largest first. */\n readonly values: Vector;\n /**\n * The eigenvectors as columns, in the order of the values, each of unit\n * length with its largest entry positive. Row names are the input's.\n */\n readonly vectors: Matrix;\n}\n\n/**\n * R's `isSymmetric()`: whether a square matrix equals its transpose to a\n * relative tolerance, R's `all.equal()` default of `100 * eps`.\n */\nexport function isSymmetric(m: Matrix, tolerance = 100 * Number.EPSILON): boolean {\n const { nrow, ncol, data } = m;\n if (nrow !== ncol) {\n return false;\n }\n for (let j = 0; j < ncol; j++) {\n for (let i = 0; i < j; i++) {\n const a = data[j * nrow + i] as number;\n const b = data[i * nrow + j] as number;\n if (Math.abs(a - b) > tolerance * Math.max(Math.abs(a), Math.abs(b))) {\n return false;\n }\n }\n }\n return true;\n}\n\n/**\n * Decompose a symmetric matrix, as R's `eigen(x, symmetric = TRUE)` does.\n *\n * @param m The symmetric matrix. The function does not modify it.\n * @returns The eigenvalues, descending, and the eigenvectors as columns.\n * @throws RangeError If the matrix is not square, is 0 x 0, holds a missing\n * or infinite entry, or is not symmetric.\n */\nexport function eigenSymmetric(m: Matrix): SymmetricEigen {\n if (m.nrow !== m.ncol) {\n throw new RangeError(\"non-square matrix in 'eigen'\");\n }\n if (m.nrow === 0) {\n throw new RangeError(\"0 x 0 matrix\");\n }\n if (!m.data.every(Number.isFinite)) {\n throw new RangeError(\"infinite or missing values in 'x'\");\n }\n if (!isSymmetric(m)) {\n throw new RangeError(\"'x' must be symmetric\");\n }\n const n = m.nrow;\n const a = Float64Array.from(m.data);\n const v = new Float64Array(n * n);\n for (let i = 0; i < n; i++) {\n v[i * n + i] = 1;\n }\n jacobi(a, v, n);\n\n const order = Array.from({ length: n }, (_, i) => i).sort(\n (i, j) => (a[j * n + j] as number) - (a[i * n + i] as number) || i - j,\n );\n const values = order.map((i) => a[i * n + i] as number);\n const vectors = new Float64Array(n * n);\n order.forEach((from, k) => {\n const columnVector = v.subarray(from * n, (from + 1) * n);\n let largest = 0;\n columnVector.forEach((entry) => {\n if (Math.abs(entry) > Math.abs(largest)) {\n largest = entry;\n }\n });\n const sign = largest < 0 ? -1 : 1;\n columnVector.forEach((entry, i) => {\n vectors[k * n + i] = sign * entry + 0;\n });\n });\n\n const rows = m.dimnames?.[0] ?? null;\n return { values, vectors: make(n, n, vectors, rows === null ? null : [rows, null]) };\n}\n\n/**\n * Cyclic Jacobi: rotate each off-diagonal pair to zero in turn until the\n * off-diagonal mass is negligible against the diagonal. `a` ends up\n * diagonal and `v` accumulates the rotations, both in place.\n */\nfunction jacobi(a: Float64Array, v: Float64Array, n: number): void {\n const at = (i: number, j: number): number => a[j * n + i] as number;\n const set = (i: number, j: number, value: number): void => {\n a[j * n + i] = value;\n };\n\n for (let sweep = 0; sweep < 100; sweep++) {\n let off = 0;\n for (let p = 0; p < n; p++) {\n for (let q = p + 1; q < n; q++) {\n off += at(p, q) * at(p, q);\n }\n }\n if (off === 0) {\n return;\n }\n let diagonal = 0;\n for (let p = 0; p < n; p++) {\n diagonal += at(p, p) * at(p, p);\n }\n if (off <= Number.EPSILON * Number.EPSILON * diagonal) {\n return;\n }\n\n for (let p = 0; p < n; p++) {\n for (let q = p + 1; q < n; q++) {\n const apq = at(p, q);\n if (apq === 0) {\n continue;\n }\n // The rotation angle, in the form that stays accurate when the\n // diagonal entries are far apart (Rutishauser's).\n const theta = (at(q, q) - at(p, p)) / (2 * apq);\n const t = (theta >= 0 ? 1 : -1) / (Math.abs(theta) + Math.sqrt(theta * theta + 1));\n const c = 1 / Math.sqrt(t * t + 1);\n const s = t * c;\n\n for (let k = 0; k < n; k++) {\n const akp = at(k, p);\n const akq = at(k, q);\n set(k, p, c * akp - s * akq);\n set(k, q, s * akp + c * akq);\n }\n for (let k = 0; k < n; k++) {\n const apk = at(p, k);\n const aqk = at(q, k);\n set(p, k, c * apk - s * aqk);\n set(q, k, s * apk + c * aqk);\n }\n for (let k = 0; k < n; k++) {\n const vkp = v[p * n + k] as number;\n const vkq = v[q * n + k] as number;\n v[p * n + k] = c * vkp - s * vkq;\n v[q * n + k] = s * vkp + c * vkq;\n }\n }\n }\n }\n}\n",
|
|
18
|
+
"/**\n * R's `prcomp()`: principal components of a matrix or a data frame, any\n * number of variables.\n *\n * R centers (and optionally scales) the columns and takes the singular\n * value decomposition of the result. The port centers and scales the same\n * way and then decomposes the covariance matrix with `eigenSymmetric`: the\n * standard deviations are the square roots of its eigenvalues, the rotation\n * its eigenvectors, and the scores the centered data times the rotation.\n * The two routes agree to a relative `1e-12` on the standard deviations and\n * up to the sign of each component on the rest (plan Q1), which the SVD\n * leaves arbitrary as well; the port's sign rule is `eigenSymmetric`'s.\n * Verified in `prcomp.test.ts`, including agreement with the two-variable\n * `principalComponents` of `pca.ts` on the bundled `pcaDegenerate` points.\n *\n * As `pca.ts` does, the port returns one component per variable and never\n * reduces the rank: a collinear input reports a near-zero standard\n * deviation rather than a shorter result. R's `prcomp` returns `min(n, p)`\n * components, which is the same unless there are fewer rows than columns.\n */\n\nimport type { DataFrame } from \"../frame\";\nimport { sum } from \"../arith\";\nimport { eigenSymmetric } from \"./eigen\";\nimport { fromFrame, make, type Matrix } from \"./matrix\";\nimport { matmul } from \"./ops\";\nimport type { Vector } from \"./vector\";\n\nexport interface PrcompOptions {\n /** Subtract the column means first. True by default, as R's is. */\n readonly center?: boolean;\n /**\n * Divide each column by its root mean square after centering — its\n * standard deviation, when centered. False by default, as R's is.\n */\n readonly scale?: boolean;\n}\n\n/** R's `prcomp` result. */\nexport interface Prcomp {\n /** The standard deviation along each component, largest first. */\n readonly sdev: Vector;\n /**\n * The loadings: one row per variable, one column per component, named\n * `PC1`, `PC2`, … with the variable names as row names when the input\n * has column names.\n */\n readonly rotation: Matrix;\n /** The value subtracted from each column; zeros when not centered. */\n readonly center: Vector;\n /** The value each column was divided by, or null when not scaled. */\n readonly scale: Vector | null;\n /**\n * The scores: the centered, scaled data in component coordinates, with\n * the row names of the input and `PC1`, `PC2`, … as column names, as R's\n * are (fixture 5e).\n */\n readonly x: Matrix;\n}\n\n/**\n * Compute the principal components, as R's `prcomp()` does.\n *\n * @param input A matrix with one column per variable, or a data frame whose\n * numeric columns are the variables.\n * @param options Whether to center and whether to scale.\n * @returns The standard deviations, the rotation, the centering and scaling\n * applied, and the scores.\n * @throws RangeError If any value is missing or infinite (R's `svd` refuses\n * the same), or if a column to be scaled is constant, in R's words.\n */\nexport function prcomp(input: Matrix | DataFrame, options: PrcompOptions = {}): Prcomp {\n const { center = true, scale = false } = options;\n const m = isMatrixLike(input) ? input : fromFrame(input);\n const { nrow: n, ncol: p } = m;\n if (!m.data.every(Number.isFinite)) {\n throw new RangeError(\"infinite or missing values in 'x'\");\n }\n\n const columns = Array.from({ length: p }, (_, j) =>\n Array.from(m.data.subarray(j * n, (j + 1) * n)),\n );\n const centers = columns.map((column) => (center ? sum(column) / n : 0));\n const centered = columns.map((column, j) => column.map((value) => value - (centers[j] as number)));\n // R's scale(): the root mean square with the n - 1 divisor, which is the\n // standard deviation of a centered column.\n const scales = scale\n ? centered.map((column) => Math.sqrt(sum(column.map((value) => value * value)) / Math.max(1, n - 1)))\n : null;\n if (scales !== null && scales.some((value) => value === 0)) {\n throw new RangeError(\"cannot rescale a constant/zero column to unit variance\");\n }\n const prepared = centered.map((column, j) =>\n scales === null ? column : column.map((value) => value / (scales[j] as number)),\n );\n\n // The covariance of the prepared columns, with R's max(1, n - 1) divisor.\n const divisor = Math.max(1, n - 1);\n const covariance = new Float64Array(p * p);\n for (let i = 0; i < p; i++) {\n for (let j = 0; j <= i; j++) {\n let total = 0;\n for (let k = 0; k < n; k++) {\n total += ((prepared[i] as number[])[k] as number) * ((prepared[j] as number[])[k] as number);\n }\n covariance[j * p + i] = total / divisor;\n covariance[i * p + j] = total / divisor;\n }\n }\n const variables = m.dimnames?.[1] ?? null;\n const eigen = eigenSymmetric(make(p, p, covariance, variables === null ? null : [variables, variables]));\n\n const components = Array.from({ length: p }, (_, k) => `PC${k + 1}`);\n const rotation = make(p, p, Float64Array.from(eigen.vectors.data), [variables, components]);\n const data = new Float64Array(n * p);\n prepared.forEach((column, j) => {\n data.set(column, j * n);\n });\n const scores = matmul(make(n, p, data, null), rotation);\n\n return {\n sdev: eigen.values.map((value) => Math.sqrt(Math.max(value, 0))),\n rotation,\n center: centers,\n scale: scales,\n x: make(n, p, scores.data, [m.dimnames?.[0] ?? null, components]),\n };\n}\n\n/** A matrix carries its data in a typed array; a data frame does not. */\nfunction isMatrixLike(input: Matrix | DataFrame): input is Matrix {\n return (\n \"data\" in input &&\n (input as { data: unknown }).data instanceof Float64Array &&\n typeof (input as { nrow: unknown }).nrow === \"number\"\n );\n}\n",
|
|
19
|
+
"/**\n * R's operators over vectors, by name.\n *\n * R vectors are not objects with methods: `a + 1`, `a * b` and `sum(a * b)`\n * are functions over plain vectors, with a scalar recycled to the length of\n * the other argument. This module is those functions with the operator\n * spelled out — `add(a, 1)`, `mul(a, b)`, `dot(a, b)` — over `Vector`,\n * which is `Vector` and nothing more: a bare array is a vector\n * (plan Q11, Q12).\n *\n * R recycles any shorter vector, with a warning when the lengths do not\n * divide. The port recycles a scalar only and refuses every other mismatch:\n * a silent recycle lets a typo fit the wrong model.\n */\n\nimport { sum, zipWith } from \"../arith\";\n\n/**\n * A numeric vector: R's atomic double vector, which here is a plain array of\n * numbers. `NaN` is the missing value, as `NA_real_` is in R.\n *\n * The name is erased at compile time and structural, not nominal. Any\n * `number[]` is a `Vector` and any `Vector` is an array, with nothing to wrap\n * at either end. It names the concept in a signature and carries this note to\n * every place one is taken; it constrains nothing, and in particular it does\n * not check a length.\n *\n * A function *takes* a `Vector` and *returns* a fresh `number[]` — R's\n * copy-on-modify, and the reason there is no mutable counterpart to this\n * name. A vector is never an object with methods (plan Q12).\n */\nexport type Vector = readonly number[];\n\n/** A vector, or a scalar to recycle to the vector's length. */\nexport type VectorOrScalar = Vector | number;\n\n/** Combine two vectors element by element, or a vector with a scalar. */\nfunction elementwise(\n a: Vector,\n b: VectorOrScalar,\n combine: (x: number, y: number) => number,\n): number[] {\n if (typeof b === \"number\") {\n return a.map((x) => combine(x, b));\n }\n requireSameLength(a, b);\n return zipWith(a, b, combine);\n}\n\n/** Refuse two vectors of different lengths. */\nfunction requireSameLength(a: Vector, b: Vector): void {\n if (a.length !== b.length) {\n throw new RangeError(`vector lengths differ: ${a.length} and ${b.length}`);\n }\n}\n\n/** R's `a + b`. */\nexport function add(a: Vector, b: VectorOrScalar): number[] {\n return elementwise(a, b, (x, y) => x + y);\n}\n\n/** R's `a - b`. */\nexport function sub(a: Vector, b: VectorOrScalar): number[] {\n return elementwise(a, b, (x, y) => x - y);\n}\n\n/** R's `a * b`. With a scalar, `2 * a`. */\nexport function mul(a: Vector, b: VectorOrScalar): number[] {\n return elementwise(a, b, (x, y) => x * y);\n}\n\n/** R's `a / b`. */\nexport function div(a: Vector, b: VectorOrScalar): number[] {\n return elementwise(a, b, (x, y) => x / y);\n}\n\n/** R's `a^2`. */\nexport function square(a: Vector): number[] {\n return a.map((x) => x * x);\n}\n\n/**\n * R's `sum(a * b)`: the inner product.\n *\n * @throws RangeError If the lengths differ.\n */\nexport function dot(a: Vector, b: Vector): number {\n requireSameLength(a, b);\n return sum(mul(a, b));\n}\n\n/**\n * R's `sqrt(sum(a^2))`: the Euclidean length.\n *\n * Written as a sum, not `Math.hypot(...a)`: the spread overflows the call\n * stack on a long vector, and the sum is the form R computes, so the two\n * round the same way.\n */\nexport function norm(a: Vector): number {\n return Math.sqrt(sum(square(a)));\n}\n\n/**\n * The cosine of the angle between two vectors: `dot(a, b) / (norm(a) * norm(b))`.\n *\n * Computed in exactly that order, which is the order a reader writes it in\n * R, so the port and R land on the same double — including\n * `cosine(a, a) = 1.0000000000000002` for a vector whose norm does not\n * square back to its sum of squares. A zero vector gives NaN, as `0 / 0` does\n * in R.\n *\n * @throws RangeError If the lengths differ.\n */\nexport function cosine(a: Vector, b: Vector): number {\n return dot(a, b) / (norm(a) * norm(b));\n}\n"
|
|
20
|
+
],
|
|
21
|
+
"mappings": "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",
|
|
22
|
+
"debugId": "3595AB073D7D3A5A64756E2164756E21",
|
|
23
|
+
"names": []
|
|
24
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `../compstatslib/R/moderation_3d_plot.R`. Every number comes from
|
|
7
7
|
* `moderationSurface` in `src/core/moderation.ts`; this module computes no
|
|
8
8
|
* statistics of its own. The grid values are pinned in
|
|
9
|
-
* `.claude/plans/moderation-fixtures.md` section 3.
|
|
9
|
+
* `.claude/plans/001-PLAN-port/moderation-fixtures.md` section 3.
|
|
10
10
|
*
|
|
11
11
|
* Three decisions are worth stating.
|
|
12
12
|
*
|
package/dist/plot/scatter3d.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* This is `plot_scatter3d()` of `../compstatslib/R/scatter3d_plot.R`, drawn
|
|
6
6
|
* through Plotly as the R original is. The trace and the layout follow the
|
|
7
|
-
* object R actually builds, dumped in `.claude/plans/moderation-fixtures.md`
|
|
7
|
+
* object R actually builds, dumped in `.claude/plans/001-PLAN-port/moderation-fixtures.md`
|
|
8
8
|
* section 5.
|
|
9
9
|
*
|
|
10
10
|
* Four things are worth knowing before reading the code.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@compstats/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Interactive 2D and 3D visualization of data and statistical concepts, in the browser.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,10 +50,15 @@
|
|
|
50
50
|
"import": "./dist/3d.js",
|
|
51
51
|
"default": "./dist/3d.js"
|
|
52
52
|
},
|
|
53
|
+
"./linalg": {
|
|
54
|
+
"types": "./dist/linalg.d.ts",
|
|
55
|
+
"import": "./dist/linalg.js",
|
|
56
|
+
"default": "./dist/linalg.js"
|
|
57
|
+
},
|
|
53
58
|
"./package.json": "./package.json"
|
|
54
59
|
},
|
|
55
60
|
"scripts": {
|
|
56
|
-
"build": "bun build src/index.ts src/3d.ts --outdir dist --target browser --format esm --sourcemap=linked --external plotly.js-dist-min && bunx tsc -p tsconfig.build.json",
|
|
61
|
+
"build": "bun build src/index.ts src/3d.ts src/linalg.ts --outdir dist --target browser --format esm --sourcemap=linked --external plotly.js-dist-min && bunx tsc -p tsconfig.build.json",
|
|
57
62
|
"typecheck": "bunx tsc --noEmit",
|
|
58
63
|
"test": "bun test",
|
|
59
64
|
"dev": "bun run demo/server.ts",
|