feat:node-modules
This commit is contained in:
580
node_modules/mathjs/lib/esm/function/algebra/sparse/csAmd.js
generated
vendored
Normal file
580
node_modules/mathjs/lib/esm/function/algebra/sparse/csAmd.js
generated
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
import { csFkeep } from './csFkeep.js';
|
||||
import { csFlip } from './csFlip.js';
|
||||
import { csTdfs } from './csTdfs.js';
|
||||
var name = 'csAmd';
|
||||
var dependencies = ['add', 'multiply', 'transpose'];
|
||||
export var createCsAmd = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
add,
|
||||
multiply,
|
||||
transpose
|
||||
} = _ref;
|
||||
/**
|
||||
* Approximate minimum degree ordering. The minimum degree algorithm is a widely used
|
||||
* heuristic for finding a permutation P so that P*A*P' has fewer nonzeros in its factorization
|
||||
* than A. It is a gready method that selects the sparsest pivot row and column during the course
|
||||
* of a right looking sparse Cholesky factorization.
|
||||
*
|
||||
* @param {Number} order 0: Natural, 1: Cholesky, 2: LU, 3: QR
|
||||
* @param {Matrix} m Sparse Matrix
|
||||
*/
|
||||
return function csAmd(order, a) {
|
||||
// check input parameters
|
||||
if (!a || order <= 0 || order > 3) {
|
||||
return null;
|
||||
}
|
||||
// a matrix arrays
|
||||
var asize = a._size;
|
||||
// rows and columns
|
||||
var m = asize[0];
|
||||
var n = asize[1];
|
||||
// initialize vars
|
||||
var lemax = 0;
|
||||
// dense threshold
|
||||
var dense = Math.max(16, 10 * Math.sqrt(n));
|
||||
dense = Math.min(n - 2, dense);
|
||||
// create target matrix C
|
||||
var cm = _createTargetMatrix(order, a, m, n, dense);
|
||||
// drop diagonal entries
|
||||
csFkeep(cm, _diag, null);
|
||||
// C matrix arrays
|
||||
var cindex = cm._index;
|
||||
var cptr = cm._ptr;
|
||||
|
||||
// number of nonzero elements in C
|
||||
var cnz = cptr[n];
|
||||
|
||||
// allocate result (n+1)
|
||||
var P = [];
|
||||
|
||||
// create workspace (8 * (n + 1))
|
||||
var W = [];
|
||||
var len = 0; // first n + 1 entries
|
||||
var nv = n + 1; // next n + 1 entries
|
||||
var next = 2 * (n + 1); // next n + 1 entries
|
||||
var head = 3 * (n + 1); // next n + 1 entries
|
||||
var elen = 4 * (n + 1); // next n + 1 entries
|
||||
var degree = 5 * (n + 1); // next n + 1 entries
|
||||
var w = 6 * (n + 1); // next n + 1 entries
|
||||
var hhead = 7 * (n + 1); // last n + 1 entries
|
||||
|
||||
// use P as workspace for last
|
||||
var last = P;
|
||||
|
||||
// initialize quotient graph
|
||||
var mark = _initializeQuotientGraph(n, cptr, W, len, head, last, next, hhead, nv, w, elen, degree);
|
||||
|
||||
// initialize degree lists
|
||||
var nel = _initializeDegreeLists(n, cptr, W, degree, elen, w, dense, nv, head, last, next);
|
||||
|
||||
// minimum degree node
|
||||
var mindeg = 0;
|
||||
|
||||
// vars
|
||||
var i, j, k, k1, k2, e, pj, ln, nvi, pk, eln, p1, p2, pn, h, d;
|
||||
|
||||
// while (selecting pivots) do
|
||||
while (nel < n) {
|
||||
// select node of minimum approximate degree. amd() is now ready to start eliminating the graph. It first
|
||||
// finds a node k of minimum degree and removes it from its degree list. The variable nel keeps track of thow
|
||||
// many nodes have been eliminated.
|
||||
for (k = -1; mindeg < n && (k = W[head + mindeg]) === -1; mindeg++);
|
||||
if (W[next + k] !== -1) {
|
||||
last[W[next + k]] = -1;
|
||||
}
|
||||
// remove k from degree list
|
||||
W[head + mindeg] = W[next + k];
|
||||
// elenk = |Ek|
|
||||
var elenk = W[elen + k];
|
||||
// # of nodes k represents
|
||||
var nvk = W[nv + k];
|
||||
// W[nv + k] nodes of A eliminated
|
||||
nel += nvk;
|
||||
|
||||
// Construct a new element. The new element Lk is constructed in place if |Ek| = 0. nv[i] is
|
||||
// negated for all nodes i in Lk to flag them as members of this set. Each node i is removed from the
|
||||
// degree lists. All elements e in Ek are absorved into element k.
|
||||
var dk = 0;
|
||||
// flag k as in Lk
|
||||
W[nv + k] = -nvk;
|
||||
var p = cptr[k];
|
||||
// do in place if W[elen + k] === 0
|
||||
var pk1 = elenk === 0 ? p : cnz;
|
||||
var pk2 = pk1;
|
||||
for (k1 = 1; k1 <= elenk + 1; k1++) {
|
||||
if (k1 > elenk) {
|
||||
// search the nodes in k
|
||||
e = k;
|
||||
// list of nodes starts at cindex[pj]
|
||||
pj = p;
|
||||
// length of list of nodes in k
|
||||
ln = W[len + k] - elenk;
|
||||
} else {
|
||||
// search the nodes in e
|
||||
e = cindex[p++];
|
||||
pj = cptr[e];
|
||||
// length of list of nodes in e
|
||||
ln = W[len + e];
|
||||
}
|
||||
for (k2 = 1; k2 <= ln; k2++) {
|
||||
i = cindex[pj++];
|
||||
// check node i dead, or seen
|
||||
if ((nvi = W[nv + i]) <= 0) {
|
||||
continue;
|
||||
}
|
||||
// W[degree + Lk] += size of node i
|
||||
dk += nvi;
|
||||
// negate W[nv + i] to denote i in Lk
|
||||
W[nv + i] = -nvi;
|
||||
// place i in Lk
|
||||
cindex[pk2++] = i;
|
||||
if (W[next + i] !== -1) {
|
||||
last[W[next + i]] = last[i];
|
||||
}
|
||||
// check we need to remove i from degree list
|
||||
if (last[i] !== -1) {
|
||||
W[next + last[i]] = W[next + i];
|
||||
} else {
|
||||
W[head + W[degree + i]] = W[next + i];
|
||||
}
|
||||
}
|
||||
if (e !== k) {
|
||||
// absorb e into k
|
||||
cptr[e] = csFlip(k);
|
||||
// e is now a dead element
|
||||
W[w + e] = 0;
|
||||
}
|
||||
}
|
||||
// cindex[cnz...nzmax] is free
|
||||
if (elenk !== 0) {
|
||||
cnz = pk2;
|
||||
}
|
||||
// external degree of k - |Lk\i|
|
||||
W[degree + k] = dk;
|
||||
// element k is in cindex[pk1..pk2-1]
|
||||
cptr[k] = pk1;
|
||||
W[len + k] = pk2 - pk1;
|
||||
// k is now an element
|
||||
W[elen + k] = -2;
|
||||
|
||||
// Find set differences. The scan1 function now computes the set differences |Le \ Lk| for all elements e. At the start of the
|
||||
// scan, no entry in the w array is greater than or equal to mark.
|
||||
|
||||
// clear w if necessary
|
||||
mark = _wclear(mark, lemax, W, w, n);
|
||||
// scan 1: find |Le\Lk|
|
||||
for (pk = pk1; pk < pk2; pk++) {
|
||||
i = cindex[pk];
|
||||
// check if W[elen + i] empty, skip it
|
||||
if ((eln = W[elen + i]) <= 0) {
|
||||
continue;
|
||||
}
|
||||
// W[nv + i] was negated
|
||||
nvi = -W[nv + i];
|
||||
var wnvi = mark - nvi;
|
||||
// scan Ei
|
||||
for (p = cptr[i], p1 = cptr[i] + eln - 1; p <= p1; p++) {
|
||||
e = cindex[p];
|
||||
if (W[w + e] >= mark) {
|
||||
// decrement |Le\Lk|
|
||||
W[w + e] -= nvi;
|
||||
} else if (W[w + e] !== 0) {
|
||||
// ensure e is a live element, 1st time e seen in scan 1
|
||||
W[w + e] = W[degree + e] + wnvi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// degree update
|
||||
// The second pass computes the approximate degree di, prunes the sets Ei and Ai, and computes a hash
|
||||
// function h(i) for all nodes in Lk.
|
||||
|
||||
// scan2: degree update
|
||||
for (pk = pk1; pk < pk2; pk++) {
|
||||
// consider node i in Lk
|
||||
i = cindex[pk];
|
||||
p1 = cptr[i];
|
||||
p2 = p1 + W[elen + i] - 1;
|
||||
pn = p1;
|
||||
// scan Ei
|
||||
for (h = 0, d = 0, p = p1; p <= p2; p++) {
|
||||
e = cindex[p];
|
||||
// check e is an unabsorbed element
|
||||
if (W[w + e] !== 0) {
|
||||
// dext = |Le\Lk|
|
||||
var dext = W[w + e] - mark;
|
||||
if (dext > 0) {
|
||||
// sum up the set differences
|
||||
d += dext;
|
||||
// keep e in Ei
|
||||
cindex[pn++] = e;
|
||||
// compute the hash of node i
|
||||
h += e;
|
||||
} else {
|
||||
// aggressive absorb. e->k
|
||||
cptr[e] = csFlip(k);
|
||||
// e is a dead element
|
||||
W[w + e] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// W[elen + i] = |Ei|
|
||||
W[elen + i] = pn - p1 + 1;
|
||||
var p3 = pn;
|
||||
var p4 = p1 + W[len + i];
|
||||
// prune edges in Ai
|
||||
for (p = p2 + 1; p < p4; p++) {
|
||||
j = cindex[p];
|
||||
// check node j dead or in Lk
|
||||
var nvj = W[nv + j];
|
||||
if (nvj <= 0) {
|
||||
continue;
|
||||
}
|
||||
// degree(i) += |j|
|
||||
d += nvj;
|
||||
// place j in node list of i
|
||||
cindex[pn++] = j;
|
||||
// compute hash for node i
|
||||
h += j;
|
||||
}
|
||||
// check for mass elimination
|
||||
if (d === 0) {
|
||||
// absorb i into k
|
||||
cptr[i] = csFlip(k);
|
||||
nvi = -W[nv + i];
|
||||
// |Lk| -= |i|
|
||||
dk -= nvi;
|
||||
// |k| += W[nv + i]
|
||||
nvk += nvi;
|
||||
nel += nvi;
|
||||
W[nv + i] = 0;
|
||||
// node i is dead
|
||||
W[elen + i] = -1;
|
||||
} else {
|
||||
// update degree(i)
|
||||
W[degree + i] = Math.min(W[degree + i], d);
|
||||
// move first node to end
|
||||
cindex[pn] = cindex[p3];
|
||||
// move 1st el. to end of Ei
|
||||
cindex[p3] = cindex[p1];
|
||||
// add k as 1st element in of Ei
|
||||
cindex[p1] = k;
|
||||
// new len of adj. list of node i
|
||||
W[len + i] = pn - p1 + 1;
|
||||
// finalize hash of i
|
||||
h = (h < 0 ? -h : h) % n;
|
||||
// place i in hash bucket
|
||||
W[next + i] = W[hhead + h];
|
||||
W[hhead + h] = i;
|
||||
// save hash of i in last[i]
|
||||
last[i] = h;
|
||||
}
|
||||
}
|
||||
// finalize |Lk|
|
||||
W[degree + k] = dk;
|
||||
lemax = Math.max(lemax, dk);
|
||||
// clear w
|
||||
mark = _wclear(mark + lemax, lemax, W, w, n);
|
||||
|
||||
// Supernode detection. Supernode detection relies on the hash function h(i) computed for each node i.
|
||||
// If two nodes have identical adjacency lists, their hash functions wil be identical.
|
||||
for (pk = pk1; pk < pk2; pk++) {
|
||||
i = cindex[pk];
|
||||
// check i is dead, skip it
|
||||
if (W[nv + i] >= 0) {
|
||||
continue;
|
||||
}
|
||||
// scan hash bucket of node i
|
||||
h = last[i];
|
||||
i = W[hhead + h];
|
||||
// hash bucket will be empty
|
||||
W[hhead + h] = -1;
|
||||
for (; i !== -1 && W[next + i] !== -1; i = W[next + i], mark++) {
|
||||
ln = W[len + i];
|
||||
eln = W[elen + i];
|
||||
for (p = cptr[i] + 1; p <= cptr[i] + ln - 1; p++) {
|
||||
W[w + cindex[p]] = mark;
|
||||
}
|
||||
var jlast = i;
|
||||
// compare i with all j
|
||||
for (j = W[next + i]; j !== -1;) {
|
||||
var ok = W[len + j] === ln && W[elen + j] === eln;
|
||||
for (p = cptr[j] + 1; ok && p <= cptr[j] + ln - 1; p++) {
|
||||
// compare i and j
|
||||
if (W[w + cindex[p]] !== mark) {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
// check i and j are identical
|
||||
if (ok) {
|
||||
// absorb j into i
|
||||
cptr[j] = csFlip(i);
|
||||
W[nv + i] += W[nv + j];
|
||||
W[nv + j] = 0;
|
||||
// node j is dead
|
||||
W[elen + j] = -1;
|
||||
// delete j from hash bucket
|
||||
j = W[next + j];
|
||||
W[next + jlast] = j;
|
||||
} else {
|
||||
// j and i are different
|
||||
jlast = j;
|
||||
j = W[next + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize new element. The elimination of node k is nearly complete. All nodes i in Lk are scanned one last time.
|
||||
// Node i is removed from Lk if it is dead. The flagged status of nv[i] is cleared.
|
||||
for (p = pk1, pk = pk1; pk < pk2; pk++) {
|
||||
i = cindex[pk];
|
||||
// check i is dead, skip it
|
||||
if ((nvi = -W[nv + i]) <= 0) {
|
||||
continue;
|
||||
}
|
||||
// restore W[nv + i]
|
||||
W[nv + i] = nvi;
|
||||
// compute external degree(i)
|
||||
d = W[degree + i] + dk - nvi;
|
||||
d = Math.min(d, n - nel - nvi);
|
||||
if (W[head + d] !== -1) {
|
||||
last[W[head + d]] = i;
|
||||
}
|
||||
// put i back in degree list
|
||||
W[next + i] = W[head + d];
|
||||
last[i] = -1;
|
||||
W[head + d] = i;
|
||||
// find new minimum degree
|
||||
mindeg = Math.min(mindeg, d);
|
||||
W[degree + i] = d;
|
||||
// place i in Lk
|
||||
cindex[p++] = i;
|
||||
}
|
||||
// # nodes absorbed into k
|
||||
W[nv + k] = nvk;
|
||||
// length of adj list of element k
|
||||
if ((W[len + k] = p - pk1) === 0) {
|
||||
// k is a root of the tree
|
||||
cptr[k] = -1;
|
||||
// k is now a dead element
|
||||
W[w + k] = 0;
|
||||
}
|
||||
if (elenk !== 0) {
|
||||
// free unused space in Lk
|
||||
cnz = p;
|
||||
}
|
||||
}
|
||||
|
||||
// Postordering. The elimination is complete, but no permutation has been computed. All that is left
|
||||
// of the graph is the assembly tree (ptr) and a set of dead nodes and elements (i is a dead node if
|
||||
// nv[i] is zero and a dead element if nv[i] > 0). It is from this information only that the final permutation
|
||||
// is computed. The tree is restored by unflipping all of ptr.
|
||||
|
||||
// fix assembly tree
|
||||
for (i = 0; i < n; i++) {
|
||||
cptr[i] = csFlip(cptr[i]);
|
||||
}
|
||||
for (j = 0; j <= n; j++) {
|
||||
W[head + j] = -1;
|
||||
}
|
||||
// place unordered nodes in lists
|
||||
for (j = n; j >= 0; j--) {
|
||||
// skip if j is an element
|
||||
if (W[nv + j] > 0) {
|
||||
continue;
|
||||
}
|
||||
// place j in list of its parent
|
||||
W[next + j] = W[head + cptr[j]];
|
||||
W[head + cptr[j]] = j;
|
||||
}
|
||||
// place elements in lists
|
||||
for (e = n; e >= 0; e--) {
|
||||
// skip unless e is an element
|
||||
if (W[nv + e] <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (cptr[e] !== -1) {
|
||||
// place e in list of its parent
|
||||
W[next + e] = W[head + cptr[e]];
|
||||
W[head + cptr[e]] = e;
|
||||
}
|
||||
}
|
||||
// postorder the assembly tree
|
||||
for (k = 0, i = 0; i <= n; i++) {
|
||||
if (cptr[i] === -1) {
|
||||
k = csTdfs(i, k, W, head, next, P, w);
|
||||
}
|
||||
}
|
||||
// remove last item in array
|
||||
P.splice(P.length - 1, 1);
|
||||
// return P
|
||||
return P;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the matrix that will be used by the approximate minimum degree ordering algorithm. The function accepts the matrix M as input and returns a permutation
|
||||
* vector P. The amd algorithm operates on a symmetrix matrix, so one of three symmetric matrices is formed.
|
||||
*
|
||||
* Order: 0
|
||||
* A natural ordering P=null matrix is returned.
|
||||
*
|
||||
* Order: 1
|
||||
* Matrix must be square. This is appropriate for a Cholesky or LU factorization.
|
||||
* P = M + M'
|
||||
*
|
||||
* Order: 2
|
||||
* Dense columns from M' are dropped, M recreated from M'. This is appropriatefor LU factorization of unsymmetric matrices.
|
||||
* P = M' * M
|
||||
*
|
||||
* Order: 3
|
||||
* This is best used for QR factorization or LU factorization is matrix M has no dense rows. A dense row is a row with more than 10*sqr(columns) entries.
|
||||
* P = M' * M
|
||||
*/
|
||||
function _createTargetMatrix(order, a, m, n, dense) {
|
||||
// compute A'
|
||||
var at = transpose(a);
|
||||
|
||||
// check order = 1, matrix must be square
|
||||
if (order === 1 && n === m) {
|
||||
// C = A + A'
|
||||
return add(a, at);
|
||||
}
|
||||
|
||||
// check order = 2, drop dense columns from M'
|
||||
if (order === 2) {
|
||||
// transpose arrays
|
||||
var tindex = at._index;
|
||||
var tptr = at._ptr;
|
||||
// new column index
|
||||
var p2 = 0;
|
||||
// loop A' columns (rows)
|
||||
for (var j = 0; j < m; j++) {
|
||||
// column j of AT starts here
|
||||
var p = tptr[j];
|
||||
// new column j starts here
|
||||
tptr[j] = p2;
|
||||
// skip dense col j
|
||||
if (tptr[j + 1] - p > dense) {
|
||||
continue;
|
||||
}
|
||||
// map rows in column j of A
|
||||
for (var p1 = tptr[j + 1]; p < p1; p++) {
|
||||
tindex[p2++] = tindex[p];
|
||||
}
|
||||
}
|
||||
// finalize AT
|
||||
tptr[m] = p2;
|
||||
// recreate A from new transpose matrix
|
||||
a = transpose(at);
|
||||
// use A' * A
|
||||
return multiply(at, a);
|
||||
}
|
||||
|
||||
// use A' * A, square or rectangular matrix
|
||||
return multiply(at, a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize quotient graph. There are four kind of nodes and elements that must be represented:
|
||||
*
|
||||
* - A live node is a node i (or a supernode) that has not been selected as a pivot nad has not been merged into another supernode.
|
||||
* - A dead node i is one that has been removed from the graph, having been absorved into r = flip(ptr[i]).
|
||||
* - A live element e is one that is in the graph, having been formed when node e was selected as the pivot.
|
||||
* - A dead element e is one that has benn absorved into a subsequent element s = flip(ptr[e]).
|
||||
*/
|
||||
function _initializeQuotientGraph(n, cptr, W, len, head, last, next, hhead, nv, w, elen, degree) {
|
||||
// Initialize quotient graph
|
||||
for (var k = 0; k < n; k++) {
|
||||
W[len + k] = cptr[k + 1] - cptr[k];
|
||||
}
|
||||
W[len + n] = 0;
|
||||
// initialize workspace
|
||||
for (var i = 0; i <= n; i++) {
|
||||
// degree list i is empty
|
||||
W[head + i] = -1;
|
||||
last[i] = -1;
|
||||
W[next + i] = -1;
|
||||
// hash list i is empty
|
||||
W[hhead + i] = -1;
|
||||
// node i is just one node
|
||||
W[nv + i] = 1;
|
||||
// node i is alive
|
||||
W[w + i] = 1;
|
||||
// Ek of node i is empty
|
||||
W[elen + i] = 0;
|
||||
// degree of node i
|
||||
W[degree + i] = W[len + i];
|
||||
}
|
||||
// clear w
|
||||
var mark = _wclear(0, 0, W, w, n);
|
||||
// n is a dead element
|
||||
W[elen + n] = -2;
|
||||
// n is a root of assembly tree
|
||||
cptr[n] = -1;
|
||||
// n is a dead element
|
||||
W[w + n] = 0;
|
||||
// return mark
|
||||
return mark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize degree lists. Each node is placed in its degree lists. Nodes of zero degree are eliminated immediately. Nodes with
|
||||
* degree >= dense are alsol eliminated and merged into a placeholder node n, a dead element. Thes nodes will appera last in the
|
||||
* output permutation p.
|
||||
*/
|
||||
function _initializeDegreeLists(n, cptr, W, degree, elen, w, dense, nv, head, last, next) {
|
||||
// result
|
||||
var nel = 0;
|
||||
// loop columns
|
||||
for (var i = 0; i < n; i++) {
|
||||
// degree @ i
|
||||
var d = W[degree + i];
|
||||
// check node i is empty
|
||||
if (d === 0) {
|
||||
// element i is dead
|
||||
W[elen + i] = -2;
|
||||
nel++;
|
||||
// i is a root of assembly tree
|
||||
cptr[i] = -1;
|
||||
W[w + i] = 0;
|
||||
} else if (d > dense) {
|
||||
// absorb i into element n
|
||||
W[nv + i] = 0;
|
||||
// node i is dead
|
||||
W[elen + i] = -1;
|
||||
nel++;
|
||||
cptr[i] = csFlip(n);
|
||||
W[nv + n]++;
|
||||
} else {
|
||||
var h = W[head + d];
|
||||
if (h !== -1) {
|
||||
last[h] = i;
|
||||
}
|
||||
// put node i in degree list d
|
||||
W[next + i] = W[head + d];
|
||||
W[head + d] = i;
|
||||
}
|
||||
}
|
||||
return nel;
|
||||
}
|
||||
function _wclear(mark, lemax, W, w, n) {
|
||||
if (mark < 2 || mark + lemax < 0) {
|
||||
for (var k = 0; k < n; k++) {
|
||||
if (W[w + k] !== 0) {
|
||||
W[w + k] = 1;
|
||||
}
|
||||
}
|
||||
mark = 2;
|
||||
}
|
||||
// at this point, W [0..n-1] < mark holds
|
||||
return mark;
|
||||
}
|
||||
function _diag(i, j) {
|
||||
return i !== j;
|
||||
}
|
||||
});
|
||||
157
node_modules/mathjs/lib/esm/function/algebra/sparse/csChol.js
generated
vendored
Normal file
157
node_modules/mathjs/lib/esm/function/algebra/sparse/csChol.js
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
import { csEreach } from './csEreach.js';
|
||||
import { createCsSymperm } from './csSymperm.js';
|
||||
var name = 'csChol';
|
||||
var dependencies = ['divideScalar', 'sqrt', 'subtract', 'multiply', 'im', 're', 'conj', 'equal', 'smallerEq', 'SparseMatrix'];
|
||||
export var createCsChol = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
divideScalar,
|
||||
sqrt,
|
||||
subtract,
|
||||
multiply,
|
||||
im,
|
||||
re,
|
||||
conj,
|
||||
equal,
|
||||
smallerEq,
|
||||
SparseMatrix
|
||||
} = _ref;
|
||||
var csSymperm = createCsSymperm({
|
||||
conj,
|
||||
SparseMatrix
|
||||
});
|
||||
|
||||
/**
|
||||
* Computes the Cholesky factorization of matrix A. It computes L and P so
|
||||
* L * L' = P * A * P'
|
||||
*
|
||||
* @param {Matrix} m The A Matrix to factorize, only upper triangular part used
|
||||
* @param {Object} s The symbolic analysis from cs_schol()
|
||||
*
|
||||
* @return {Number} The numeric Cholesky factorization of A or null
|
||||
*/
|
||||
return function csChol(m, s) {
|
||||
// validate input
|
||||
if (!m) {
|
||||
return null;
|
||||
}
|
||||
// m arrays
|
||||
var size = m._size;
|
||||
// columns
|
||||
var n = size[1];
|
||||
// symbolic analysis result
|
||||
var parent = s.parent;
|
||||
var cp = s.cp;
|
||||
var pinv = s.pinv;
|
||||
// L arrays
|
||||
var lvalues = [];
|
||||
var lindex = [];
|
||||
var lptr = [];
|
||||
// L
|
||||
var L = new SparseMatrix({
|
||||
values: lvalues,
|
||||
index: lindex,
|
||||
ptr: lptr,
|
||||
size: [n, n]
|
||||
});
|
||||
// vars
|
||||
var c = []; // (2 * n)
|
||||
var x = []; // (n)
|
||||
// compute C = P * A * P'
|
||||
var cm = pinv ? csSymperm(m, pinv, 1) : m;
|
||||
// C matrix arrays
|
||||
var cvalues = cm._values;
|
||||
var cindex = cm._index;
|
||||
var cptr = cm._ptr;
|
||||
// vars
|
||||
var k, p;
|
||||
// initialize variables
|
||||
for (k = 0; k < n; k++) {
|
||||
lptr[k] = c[k] = cp[k];
|
||||
}
|
||||
// compute L(k,:) for L*L' = C
|
||||
for (k = 0; k < n; k++) {
|
||||
// nonzero pattern of L(k,:)
|
||||
var top = csEreach(cm, k, parent, c);
|
||||
// x (0:k) is now zero
|
||||
x[k] = 0;
|
||||
// x = full(triu(C(:,k)))
|
||||
for (p = cptr[k]; p < cptr[k + 1]; p++) {
|
||||
if (cindex[p] <= k) {
|
||||
x[cindex[p]] = cvalues[p];
|
||||
}
|
||||
}
|
||||
// d = C(k,k)
|
||||
var d = x[k];
|
||||
// clear x for k+1st iteration
|
||||
x[k] = 0;
|
||||
// solve L(0:k-1,0:k-1) * x = C(:,k)
|
||||
for (; top < n; top++) {
|
||||
// s[top..n-1] is pattern of L(k,:)
|
||||
var i = s[top];
|
||||
// L(k,i) = x (i) / L(i,i)
|
||||
var lki = divideScalar(x[i], lvalues[lptr[i]]);
|
||||
// clear x for k+1st iteration
|
||||
x[i] = 0;
|
||||
for (p = lptr[i] + 1; p < c[i]; p++) {
|
||||
// row
|
||||
var r = lindex[p];
|
||||
// update x[r]
|
||||
x[r] = subtract(x[r], multiply(lvalues[p], lki));
|
||||
}
|
||||
// d = d - L(k,i)*L(k,i)
|
||||
d = subtract(d, multiply(lki, conj(lki)));
|
||||
p = c[i]++;
|
||||
// store L(k,i) in column i
|
||||
lindex[p] = k;
|
||||
lvalues[p] = conj(lki);
|
||||
}
|
||||
// compute L(k,k)
|
||||
if (smallerEq(re(d), 0) || !equal(im(d), 0)) {
|
||||
// not pos def
|
||||
return null;
|
||||
}
|
||||
p = c[k]++;
|
||||
// store L(k,k) = sqrt(d) in column k
|
||||
lindex[p] = k;
|
||||
lvalues[p] = sqrt(d);
|
||||
}
|
||||
// finalize L
|
||||
lptr[n] = cp[n];
|
||||
// P matrix
|
||||
var P;
|
||||
// check we need to calculate P
|
||||
if (pinv) {
|
||||
// P arrays
|
||||
var pvalues = [];
|
||||
var pindex = [];
|
||||
var pptr = [];
|
||||
// create P matrix
|
||||
for (p = 0; p < n; p++) {
|
||||
// initialize ptr (one value per column)
|
||||
pptr[p] = p;
|
||||
// index (apply permutation vector)
|
||||
pindex.push(pinv[p]);
|
||||
// value 1
|
||||
pvalues.push(1);
|
||||
}
|
||||
// update ptr
|
||||
pptr[n] = n;
|
||||
// P
|
||||
P = new SparseMatrix({
|
||||
values: pvalues,
|
||||
index: pindex,
|
||||
ptr: pptr,
|
||||
size: [n, n]
|
||||
});
|
||||
}
|
||||
// return L & P
|
||||
return {
|
||||
L,
|
||||
P
|
||||
};
|
||||
};
|
||||
});
|
||||
126
node_modules/mathjs/lib/esm/function/algebra/sparse/csCounts.js
generated
vendored
Normal file
126
node_modules/mathjs/lib/esm/function/algebra/sparse/csCounts.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
import { csLeaf } from './csLeaf.js';
|
||||
var name = 'csCounts';
|
||||
var dependencies = ['transpose'];
|
||||
export var createCsCounts = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
transpose
|
||||
} = _ref;
|
||||
/**
|
||||
* Computes the column counts using the upper triangular part of A.
|
||||
* It transposes A internally, none of the input parameters are modified.
|
||||
*
|
||||
* @param {Matrix} a The sparse matrix A
|
||||
*
|
||||
* @param {Matrix} ata Count the columns of A'A instead
|
||||
*
|
||||
* @return An array of size n of the column counts or null on error
|
||||
*/
|
||||
return function (a, parent, post, ata) {
|
||||
// check inputs
|
||||
if (!a || !parent || !post) {
|
||||
return null;
|
||||
}
|
||||
// a matrix arrays
|
||||
var asize = a._size;
|
||||
// rows and columns
|
||||
var m = asize[0];
|
||||
var n = asize[1];
|
||||
// variables
|
||||
var i, j, k, J, p, p0, p1;
|
||||
|
||||
// workspace size
|
||||
var s = 4 * n + (ata ? n + m + 1 : 0);
|
||||
// allocate workspace
|
||||
var w = []; // (s)
|
||||
var ancestor = 0; // first n entries
|
||||
var maxfirst = n; // next n entries
|
||||
var prevleaf = 2 * n; // next n entries
|
||||
var first = 3 * n; // next n entries
|
||||
var head = 4 * n; // next n + 1 entries (used when ata is true)
|
||||
var next = 5 * n + 1; // last entries in workspace
|
||||
// clear workspace w[0..s-1]
|
||||
for (k = 0; k < s; k++) {
|
||||
w[k] = -1;
|
||||
}
|
||||
|
||||
// allocate result
|
||||
var colcount = []; // (n)
|
||||
|
||||
// AT = A'
|
||||
var at = transpose(a);
|
||||
// at arrays
|
||||
var tindex = at._index;
|
||||
var tptr = at._ptr;
|
||||
|
||||
// find w[first + j]
|
||||
for (k = 0; k < n; k++) {
|
||||
j = post[k];
|
||||
// colcount[j]=1 if j is a leaf
|
||||
colcount[j] = w[first + j] === -1 ? 1 : 0;
|
||||
for (; j !== -1 && w[first + j] === -1; j = parent[j]) {
|
||||
w[first + j] = k;
|
||||
}
|
||||
}
|
||||
|
||||
// initialize ata if needed
|
||||
if (ata) {
|
||||
// invert post
|
||||
for (k = 0; k < n; k++) {
|
||||
w[post[k]] = k;
|
||||
}
|
||||
// loop rows (columns in AT)
|
||||
for (i = 0; i < m; i++) {
|
||||
// values in column i of AT
|
||||
for (k = n, p0 = tptr[i], p1 = tptr[i + 1], p = p0; p < p1; p++) {
|
||||
k = Math.min(k, w[tindex[p]]);
|
||||
}
|
||||
// place row i in linked list k
|
||||
w[next + i] = w[head + k];
|
||||
w[head + k] = i;
|
||||
}
|
||||
}
|
||||
|
||||
// each node in its own set
|
||||
for (i = 0; i < n; i++) {
|
||||
w[ancestor + i] = i;
|
||||
}
|
||||
for (k = 0; k < n; k++) {
|
||||
// j is the kth node in postordered etree
|
||||
j = post[k];
|
||||
// check j is not a root
|
||||
if (parent[j] !== -1) {
|
||||
colcount[parent[j]]--;
|
||||
}
|
||||
|
||||
// J=j for LL'=A case
|
||||
for (J = ata ? w[head + k] : j; J !== -1; J = ata ? w[next + J] : -1) {
|
||||
for (p = tptr[J]; p < tptr[J + 1]; p++) {
|
||||
i = tindex[p];
|
||||
var r = csLeaf(i, j, w, first, maxfirst, prevleaf, ancestor);
|
||||
// check A(i,j) is in skeleton
|
||||
if (r.jleaf >= 1) {
|
||||
colcount[j]++;
|
||||
}
|
||||
// check account for overlap in q
|
||||
if (r.jleaf === 2) {
|
||||
colcount[r.q]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parent[j] !== -1) {
|
||||
w[ancestor + j] = parent[j];
|
||||
}
|
||||
}
|
||||
// sum up colcount's of each child
|
||||
for (j = 0; j < n; j++) {
|
||||
if (parent[j] !== -1) {
|
||||
colcount[parent[j]] += colcount[j];
|
||||
}
|
||||
}
|
||||
return colcount;
|
||||
};
|
||||
});
|
||||
28
node_modules/mathjs/lib/esm/function/algebra/sparse/csCumsum.js
generated
vendored
Normal file
28
node_modules/mathjs/lib/esm/function/algebra/sparse/csCumsum.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* It sets the p[i] equal to the sum of c[0] through c[i-1].
|
||||
*
|
||||
* @param {Array} ptr The Sparse Matrix ptr array
|
||||
* @param {Array} c The Sparse Matrix ptr array
|
||||
* @param {Number} n The number of columns
|
||||
*/
|
||||
export function csCumsum(ptr, c, n) {
|
||||
// variables
|
||||
var i;
|
||||
var nz = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
// initialize ptr @ i
|
||||
ptr[i] = nz;
|
||||
// increment number of nonzeros
|
||||
nz += c[i];
|
||||
// also copy p[0..n-1] back into c[0..n-1]
|
||||
c[i] = ptr[i];
|
||||
}
|
||||
// finalize ptr
|
||||
ptr[n] = nz;
|
||||
// return sum (c [0..n-1])
|
||||
return nz;
|
||||
}
|
||||
76
node_modules/mathjs/lib/esm/function/algebra/sparse/csDfs.js
generated
vendored
Normal file
76
node_modules/mathjs/lib/esm/function/algebra/sparse/csDfs.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csMarked } from './csMarked.js';
|
||||
import { csMark } from './csMark.js';
|
||||
import { csUnflip } from './csUnflip.js';
|
||||
|
||||
/**
|
||||
* Depth-first search computes the nonzero pattern xi of the directed graph G (Matrix) starting
|
||||
* at nodes in B (see csReach()).
|
||||
*
|
||||
* @param {Number} j The starting node for the DFS algorithm
|
||||
* @param {Matrix} g The G matrix to search, ptr array modified, then restored
|
||||
* @param {Number} top Start index in stack xi[top..n-1]
|
||||
* @param {Number} k The kth column in B
|
||||
* @param {Array} xi The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
|
||||
* The first n entries is the nonzero pattern, the last n entries is the stack
|
||||
* @param {Array} pinv The inverse row permutation vector, must be null for L * x = b
|
||||
*
|
||||
* @return {Number} New value of top
|
||||
*/
|
||||
export function csDfs(j, g, top, xi, pinv) {
|
||||
// g arrays
|
||||
var index = g._index;
|
||||
var ptr = g._ptr;
|
||||
var size = g._size;
|
||||
// columns
|
||||
var n = size[1];
|
||||
// vars
|
||||
var i, p, p2;
|
||||
// initialize head
|
||||
var head = 0;
|
||||
// initialize the recursion stack
|
||||
xi[0] = j;
|
||||
// loop
|
||||
while (head >= 0) {
|
||||
// get j from the top of the recursion stack
|
||||
j = xi[head];
|
||||
// apply permutation vector
|
||||
var jnew = pinv ? pinv[j] : j;
|
||||
// check node j is marked
|
||||
if (!csMarked(ptr, j)) {
|
||||
// mark node j as visited
|
||||
csMark(ptr, j);
|
||||
// update stack (last n entries in xi)
|
||||
xi[n + head] = jnew < 0 ? 0 : csUnflip(ptr[jnew]);
|
||||
}
|
||||
// node j done if no unvisited neighbors
|
||||
var done = 1;
|
||||
// examine all neighbors of j, stack (last n entries in xi)
|
||||
for (p = xi[n + head], p2 = jnew < 0 ? 0 : csUnflip(ptr[jnew + 1]); p < p2; p++) {
|
||||
// consider neighbor node i
|
||||
i = index[p];
|
||||
// check we have visited node i, skip it
|
||||
if (csMarked(ptr, i)) {
|
||||
continue;
|
||||
}
|
||||
// pause depth-first search of node j, update stack (last n entries in xi)
|
||||
xi[n + head] = p;
|
||||
// start dfs at node i
|
||||
xi[++head] = i;
|
||||
// node j is not done
|
||||
done = 0;
|
||||
// break, to start dfs(i)
|
||||
break;
|
||||
}
|
||||
// check depth-first search at node j is done
|
||||
if (done) {
|
||||
// remove j from the recursion stack
|
||||
head--;
|
||||
// and place in the output stack
|
||||
xi[--top] = j;
|
||||
}
|
||||
}
|
||||
return top;
|
||||
}
|
||||
63
node_modules/mathjs/lib/esm/function/algebra/sparse/csEreach.js
generated
vendored
Normal file
63
node_modules/mathjs/lib/esm/function/algebra/sparse/csEreach.js
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csMark } from './csMark.js';
|
||||
import { csMarked } from './csMarked.js';
|
||||
|
||||
/**
|
||||
* Find nonzero pattern of Cholesky L(k,1:k-1) using etree and triu(A(:,k))
|
||||
*
|
||||
* @param {Matrix} a The A matrix
|
||||
* @param {Number} k The kth column in A
|
||||
* @param {Array} parent The parent vector from the symbolic analysis result
|
||||
* @param {Array} w The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
|
||||
* The first n entries is the nonzero pattern, the last n entries is the stack
|
||||
*
|
||||
* @return {Number} The index for the nonzero pattern
|
||||
*/
|
||||
export function csEreach(a, k, parent, w) {
|
||||
// a arrays
|
||||
var aindex = a._index;
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
// columns
|
||||
var n = asize[1];
|
||||
// initialize top
|
||||
var top = n;
|
||||
// vars
|
||||
var p, p0, p1, len;
|
||||
// mark node k as visited
|
||||
csMark(w, k);
|
||||
// loop values & index for column k
|
||||
for (p0 = aptr[k], p1 = aptr[k + 1], p = p0; p < p1; p++) {
|
||||
// A(i,k) is nonzero
|
||||
var i = aindex[p];
|
||||
// only use upper triangular part of A
|
||||
if (i > k) {
|
||||
continue;
|
||||
}
|
||||
// traverse up etree
|
||||
for (len = 0; !csMarked(w, i); i = parent[i]) {
|
||||
// L(k,i) is nonzero, last n entries in w
|
||||
w[n + len++] = i;
|
||||
// mark i as visited
|
||||
csMark(w, i);
|
||||
}
|
||||
while (len > 0) {
|
||||
// decrement top & len
|
||||
--top;
|
||||
--len;
|
||||
// push path onto stack, last n entries in w
|
||||
w[n + top] = w[n + len];
|
||||
}
|
||||
}
|
||||
// unmark all nodes
|
||||
for (p = top; p < n; p++) {
|
||||
// use stack value, last n entries in w
|
||||
csMark(w, w[n + p]);
|
||||
}
|
||||
// unmark node k
|
||||
csMark(w, k);
|
||||
// s[top..n-1] contains pattern of L(k,:)
|
||||
return top;
|
||||
}
|
||||
71
node_modules/mathjs/lib/esm/function/algebra/sparse/csEtree.js
generated
vendored
Normal file
71
node_modules/mathjs/lib/esm/function/algebra/sparse/csEtree.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Computes the elimination tree of Matrix A (using triu(A)) or the
|
||||
* elimination tree of A'A without forming A'A.
|
||||
*
|
||||
* @param {Matrix} a The A Matrix
|
||||
* @param {boolean} ata A value of true the function computes the etree of A'A
|
||||
*/
|
||||
export function csEtree(a, ata) {
|
||||
// check inputs
|
||||
if (!a) {
|
||||
return null;
|
||||
}
|
||||
// a arrays
|
||||
var aindex = a._index;
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
// rows & columns
|
||||
var m = asize[0];
|
||||
var n = asize[1];
|
||||
|
||||
// allocate result
|
||||
var parent = []; // (n)
|
||||
|
||||
// allocate workspace
|
||||
var w = []; // (n + (ata ? m : 0))
|
||||
var ancestor = 0; // first n entries in w
|
||||
var prev = n; // last m entries (ata = true)
|
||||
|
||||
var i, inext;
|
||||
|
||||
// check we are calculating A'A
|
||||
if (ata) {
|
||||
// initialize workspace
|
||||
for (i = 0; i < m; i++) {
|
||||
w[prev + i] = -1;
|
||||
}
|
||||
}
|
||||
// loop columns
|
||||
for (var k = 0; k < n; k++) {
|
||||
// node k has no parent yet
|
||||
parent[k] = -1;
|
||||
// nor does k have an ancestor
|
||||
w[ancestor + k] = -1;
|
||||
// values in column k
|
||||
for (var p0 = aptr[k], p1 = aptr[k + 1], p = p0; p < p1; p++) {
|
||||
// row
|
||||
var r = aindex[p];
|
||||
// node
|
||||
i = ata ? w[prev + r] : r;
|
||||
// traverse from i to k
|
||||
for (; i !== -1 && i < k; i = inext) {
|
||||
// inext = ancestor of i
|
||||
inext = w[ancestor + i];
|
||||
// path compression
|
||||
w[ancestor + i] = k;
|
||||
// check no anc., parent is k
|
||||
if (inext === -1) {
|
||||
parent[i] = k;
|
||||
}
|
||||
}
|
||||
if (ata) {
|
||||
w[prev + r] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
58
node_modules/mathjs/lib/esm/function/algebra/sparse/csFkeep.js
generated
vendored
Normal file
58
node_modules/mathjs/lib/esm/function/algebra/sparse/csFkeep.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Keeps entries in the matrix when the callback function returns true, removes the entry otherwise
|
||||
*
|
||||
* @param {Matrix} a The sparse matrix
|
||||
* @param {function} callback The callback function, function will be invoked with the following args:
|
||||
* - The entry row
|
||||
* - The entry column
|
||||
* - The entry value
|
||||
* - The state parameter
|
||||
* @param {any} other The state
|
||||
*
|
||||
* @return The number of nonzero elements in the matrix
|
||||
*/
|
||||
export function csFkeep(a, callback, other) {
|
||||
// a arrays
|
||||
var avalues = a._values;
|
||||
var aindex = a._index;
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
// columns
|
||||
var n = asize[1];
|
||||
// nonzero items
|
||||
var nz = 0;
|
||||
// loop columns
|
||||
for (var j = 0; j < n; j++) {
|
||||
// get current location of col j
|
||||
var p = aptr[j];
|
||||
// record new location of col j
|
||||
aptr[j] = nz;
|
||||
for (; p < aptr[j + 1]; p++) {
|
||||
// check we need to keep this item
|
||||
if (callback(aindex[p], j, avalues ? avalues[p] : 1, other)) {
|
||||
// keep A(i,j)
|
||||
aindex[nz] = aindex[p];
|
||||
// check we need to process values (pattern only)
|
||||
if (avalues) {
|
||||
avalues[nz] = avalues[p];
|
||||
}
|
||||
// increment nonzero items
|
||||
nz++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// finalize A
|
||||
aptr[n] = nz;
|
||||
// trim arrays
|
||||
aindex.splice(nz, aindex.length - nz);
|
||||
// check we need to process values (pattern only)
|
||||
if (avalues) {
|
||||
avalues.splice(nz, avalues.length - nz);
|
||||
}
|
||||
// return number of nonzero items
|
||||
return nz;
|
||||
}
|
||||
13
node_modules/mathjs/lib/esm/function/algebra/sparse/csFlip.js
generated
vendored
Normal file
13
node_modules/mathjs/lib/esm/function/algebra/sparse/csFlip.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* This function "flips" its input about the integer -1.
|
||||
*
|
||||
* @param {Number} i The value to flip
|
||||
*/
|
||||
export function csFlip(i) {
|
||||
// flip the value
|
||||
return -i - 2;
|
||||
}
|
||||
33
node_modules/mathjs/lib/esm/function/algebra/sparse/csIpvec.js
generated
vendored
Normal file
33
node_modules/mathjs/lib/esm/function/algebra/sparse/csIpvec.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Permutes a vector; x = P'b. In MATLAB notation, x(p)=b.
|
||||
*
|
||||
* @param {Array} p The permutation vector of length n. null value denotes identity
|
||||
* @param {Array} b The input vector
|
||||
*
|
||||
* @return {Array} The output vector x = P'b
|
||||
*/
|
||||
export function csIpvec(p, b) {
|
||||
// vars
|
||||
var k;
|
||||
var n = b.length;
|
||||
var x = [];
|
||||
// check permutation vector was provided, p = null denotes identity
|
||||
if (p) {
|
||||
// loop vector
|
||||
for (k = 0; k < n; k++) {
|
||||
// apply permutation
|
||||
x[p[k]] = b[k];
|
||||
}
|
||||
} else {
|
||||
// loop vector
|
||||
for (k = 0; k < n; k++) {
|
||||
// x[i] = b[i]
|
||||
x[k] = b[k];
|
||||
}
|
||||
}
|
||||
return x;
|
||||
}
|
||||
56
node_modules/mathjs/lib/esm/function/algebra/sparse/csLeaf.js
generated
vendored
Normal file
56
node_modules/mathjs/lib/esm/function/algebra/sparse/csLeaf.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* This function determines if j is a leaf of the ith row subtree.
|
||||
* Consider A(i,j), node j in ith row subtree and return lca(jprev,j)
|
||||
*
|
||||
* @param {Number} i The ith row subtree
|
||||
* @param {Number} j The node to test
|
||||
* @param {Array} w The workspace array
|
||||
* @param {Number} first The index offset within the workspace for the first array
|
||||
* @param {Number} maxfirst The index offset within the workspace for the maxfirst array
|
||||
* @param {Number} prevleaf The index offset within the workspace for the prevleaf array
|
||||
* @param {Number} ancestor The index offset within the workspace for the ancestor array
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
export function csLeaf(i, j, w, first, maxfirst, prevleaf, ancestor) {
|
||||
var s, sparent;
|
||||
|
||||
// our result
|
||||
var jleaf = 0;
|
||||
var q;
|
||||
|
||||
// check j is a leaf
|
||||
if (i <= j || w[first + j] <= w[maxfirst + i]) {
|
||||
return -1;
|
||||
}
|
||||
// update max first[j] seen so far
|
||||
w[maxfirst + i] = w[first + j];
|
||||
// jprev = previous leaf of ith subtree
|
||||
var jprev = w[prevleaf + i];
|
||||
w[prevleaf + i] = j;
|
||||
|
||||
// check j is first or subsequent leaf
|
||||
if (jprev === -1) {
|
||||
// 1st leaf, q = root of ith subtree
|
||||
jleaf = 1;
|
||||
q = i;
|
||||
} else {
|
||||
// update jleaf
|
||||
jleaf = 2;
|
||||
// q = least common ancester (jprev,j)
|
||||
for (q = jprev; q !== w[ancestor + q]; q = w[ancestor + q]);
|
||||
for (s = jprev; s !== q; s = sparent) {
|
||||
// path compression
|
||||
sparent = w[ancestor + s];
|
||||
w[ancestor + s] = q;
|
||||
}
|
||||
}
|
||||
return {
|
||||
jleaf,
|
||||
q
|
||||
};
|
||||
}
|
||||
182
node_modules/mathjs/lib/esm/function/algebra/sparse/csLu.js
generated
vendored
Normal file
182
node_modules/mathjs/lib/esm/function/algebra/sparse/csLu.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
import { createCsSpsolve } from './csSpsolve.js';
|
||||
var name = 'csLu';
|
||||
var dependencies = ['abs', 'divideScalar', 'multiply', 'subtract', 'larger', 'largerEq', 'SparseMatrix'];
|
||||
export var createCsLu = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
abs,
|
||||
divideScalar,
|
||||
multiply,
|
||||
subtract,
|
||||
larger,
|
||||
largerEq,
|
||||
SparseMatrix
|
||||
} = _ref;
|
||||
var csSpsolve = createCsSpsolve({
|
||||
divideScalar,
|
||||
multiply,
|
||||
subtract
|
||||
});
|
||||
|
||||
/**
|
||||
* Computes the numeric LU factorization of the sparse matrix A. Implements a Left-looking LU factorization
|
||||
* algorithm that computes L and U one column at a tume. At the kth step, it access columns 1 to k-1 of L
|
||||
* and column k of A. Given the fill-reducing column ordering q (see parameter s) computes L, U and pinv so
|
||||
* L * U = A(p, q), where p is the inverse of pinv.
|
||||
*
|
||||
* @param {Matrix} m The A Matrix to factorize
|
||||
* @param {Object} s The symbolic analysis from csSqr(). Provides the fill-reducing
|
||||
* column ordering q
|
||||
* @param {Number} tol Partial pivoting threshold (1 for partial pivoting)
|
||||
*
|
||||
* @return {Number} The numeric LU factorization of A or null
|
||||
*/
|
||||
return function csLu(m, s, tol) {
|
||||
// validate input
|
||||
if (!m) {
|
||||
return null;
|
||||
}
|
||||
// m arrays
|
||||
var size = m._size;
|
||||
// columns
|
||||
var n = size[1];
|
||||
// symbolic analysis result
|
||||
var q;
|
||||
var lnz = 100;
|
||||
var unz = 100;
|
||||
// update symbolic analysis parameters
|
||||
if (s) {
|
||||
q = s.q;
|
||||
lnz = s.lnz || lnz;
|
||||
unz = s.unz || unz;
|
||||
}
|
||||
// L arrays
|
||||
var lvalues = []; // (lnz)
|
||||
var lindex = []; // (lnz)
|
||||
var lptr = []; // (n + 1)
|
||||
// L
|
||||
var L = new SparseMatrix({
|
||||
values: lvalues,
|
||||
index: lindex,
|
||||
ptr: lptr,
|
||||
size: [n, n]
|
||||
});
|
||||
// U arrays
|
||||
var uvalues = []; // (unz)
|
||||
var uindex = []; // (unz)
|
||||
var uptr = []; // (n + 1)
|
||||
// U
|
||||
var U = new SparseMatrix({
|
||||
values: uvalues,
|
||||
index: uindex,
|
||||
ptr: uptr,
|
||||
size: [n, n]
|
||||
});
|
||||
// inverse of permutation vector
|
||||
var pinv = []; // (n)
|
||||
// vars
|
||||
var i, p;
|
||||
// allocate arrays
|
||||
var x = []; // (n)
|
||||
var xi = []; // (2 * n)
|
||||
// initialize variables
|
||||
for (i = 0; i < n; i++) {
|
||||
// clear workspace
|
||||
x[i] = 0;
|
||||
// no rows pivotal yet
|
||||
pinv[i] = -1;
|
||||
// no cols of L yet
|
||||
lptr[i + 1] = 0;
|
||||
}
|
||||
// reset number of nonzero elements in L and U
|
||||
lnz = 0;
|
||||
unz = 0;
|
||||
// compute L(:,k) and U(:,k)
|
||||
for (var k = 0; k < n; k++) {
|
||||
// update ptr
|
||||
lptr[k] = lnz;
|
||||
uptr[k] = unz;
|
||||
// apply column permutations if needed
|
||||
var col = q ? q[k] : k;
|
||||
// solve triangular system, x = L\A(:,col)
|
||||
var top = csSpsolve(L, m, col, xi, x, pinv, 1);
|
||||
// find pivot
|
||||
var ipiv = -1;
|
||||
var a = -1;
|
||||
// loop xi[] from top -> n
|
||||
for (p = top; p < n; p++) {
|
||||
// x[i] is nonzero
|
||||
i = xi[p];
|
||||
// check row i is not yet pivotal
|
||||
if (pinv[i] < 0) {
|
||||
// absolute value of x[i]
|
||||
var xabs = abs(x[i]);
|
||||
// check absoulte value is greater than pivot value
|
||||
if (larger(xabs, a)) {
|
||||
// largest pivot candidate so far
|
||||
a = xabs;
|
||||
ipiv = i;
|
||||
}
|
||||
} else {
|
||||
// x(i) is the entry U(pinv[i],k)
|
||||
uindex[unz] = pinv[i];
|
||||
uvalues[unz++] = x[i];
|
||||
}
|
||||
}
|
||||
// validate we found a valid pivot
|
||||
if (ipiv === -1 || a <= 0) {
|
||||
return null;
|
||||
}
|
||||
// update actual pivot column, give preference to diagonal value
|
||||
if (pinv[col] < 0 && largerEq(abs(x[col]), multiply(a, tol))) {
|
||||
ipiv = col;
|
||||
}
|
||||
// the chosen pivot
|
||||
var pivot = x[ipiv];
|
||||
// last entry in U(:,k) is U(k,k)
|
||||
uindex[unz] = k;
|
||||
uvalues[unz++] = pivot;
|
||||
// ipiv is the kth pivot row
|
||||
pinv[ipiv] = k;
|
||||
// first entry in L(:,k) is L(k,k) = 1
|
||||
lindex[lnz] = ipiv;
|
||||
lvalues[lnz++] = 1;
|
||||
// L(k+1:n,k) = x / pivot
|
||||
for (p = top; p < n; p++) {
|
||||
// row
|
||||
i = xi[p];
|
||||
// check x(i) is an entry in L(:,k)
|
||||
if (pinv[i] < 0) {
|
||||
// save unpermuted row in L
|
||||
lindex[lnz] = i;
|
||||
// scale pivot column
|
||||
lvalues[lnz++] = divideScalar(x[i], pivot);
|
||||
}
|
||||
// x[0..n-1] = 0 for next k
|
||||
x[i] = 0;
|
||||
}
|
||||
}
|
||||
// update ptr
|
||||
lptr[n] = lnz;
|
||||
uptr[n] = unz;
|
||||
// fix row indices of L for final pinv
|
||||
for (p = 0; p < lnz; p++) {
|
||||
lindex[p] = pinv[lindex[p]];
|
||||
}
|
||||
// trim arrays
|
||||
lvalues.splice(lnz, lvalues.length - lnz);
|
||||
lindex.splice(lnz, lindex.length - lnz);
|
||||
uvalues.splice(unz, uvalues.length - unz);
|
||||
uindex.splice(unz, uindex.length - unz);
|
||||
// return LU factor
|
||||
return {
|
||||
L,
|
||||
U,
|
||||
pinv
|
||||
};
|
||||
};
|
||||
});
|
||||
16
node_modules/mathjs/lib/esm/function/algebra/sparse/csMark.js
generated
vendored
Normal file
16
node_modules/mathjs/lib/esm/function/algebra/sparse/csMark.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
import { csFlip } from './csFlip.js';
|
||||
|
||||
/**
|
||||
* Marks the node at w[j]
|
||||
*
|
||||
* @param {Array} w The array
|
||||
* @param {Number} j The array index
|
||||
*/
|
||||
export function csMark(w, j) {
|
||||
// mark w[j]
|
||||
w[j] = csFlip(w[j]);
|
||||
}
|
||||
14
node_modules/mathjs/lib/esm/function/algebra/sparse/csMarked.js
generated
vendored
Normal file
14
node_modules/mathjs/lib/esm/function/algebra/sparse/csMarked.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Checks if the node at w[j] is marked
|
||||
*
|
||||
* @param {Array} w The array
|
||||
* @param {Number} j The array index
|
||||
*/
|
||||
export function csMarked(w, j) {
|
||||
// check node is marked
|
||||
return w[j] < 0;
|
||||
}
|
||||
61
node_modules/mathjs/lib/esm/function/algebra/sparse/csPermute.js
generated
vendored
Normal file
61
node_modules/mathjs/lib/esm/function/algebra/sparse/csPermute.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Permutes a sparse matrix C = P * A * Q
|
||||
*
|
||||
* @param {SparseMatrix} a The Matrix A
|
||||
* @param {Array} pinv The row permutation vector
|
||||
* @param {Array} q The column permutation vector
|
||||
* @param {boolean} values Create a pattern matrix (false), values and pattern otherwise
|
||||
*
|
||||
* @return {Matrix} C = P * A * Q, null on error
|
||||
*/
|
||||
export function csPermute(a, pinv, q, values) {
|
||||
// a arrays
|
||||
var avalues = a._values;
|
||||
var aindex = a._index;
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
var adt = a._datatype;
|
||||
// rows & columns
|
||||
var m = asize[0];
|
||||
var n = asize[1];
|
||||
// c arrays
|
||||
var cvalues = values && a._values ? [] : null;
|
||||
var cindex = []; // (aptr[n])
|
||||
var cptr = []; // (n + 1)
|
||||
// initialize vars
|
||||
var nz = 0;
|
||||
// loop columns
|
||||
for (var k = 0; k < n; k++) {
|
||||
// column k of C is column q[k] of A
|
||||
cptr[k] = nz;
|
||||
// apply column permutation
|
||||
var j = q ? q[k] : k;
|
||||
// loop values in column j of A
|
||||
for (var t0 = aptr[j], t1 = aptr[j + 1], t = t0; t < t1; t++) {
|
||||
// row i of A is row pinv[i] of C
|
||||
var r = pinv ? pinv[aindex[t]] : aindex[t];
|
||||
// index
|
||||
cindex[nz] = r;
|
||||
// check we need to populate values
|
||||
if (cvalues) {
|
||||
cvalues[nz] = avalues[t];
|
||||
}
|
||||
// increment number of nonzero elements
|
||||
nz++;
|
||||
}
|
||||
}
|
||||
// finalize the last column of C
|
||||
cptr[n] = nz;
|
||||
// return C matrix
|
||||
return a.createSparseMatrix({
|
||||
values: cvalues,
|
||||
index: cindex,
|
||||
ptr: cptr,
|
||||
size: [m, n],
|
||||
datatype: adt
|
||||
});
|
||||
}
|
||||
52
node_modules/mathjs/lib/esm/function/algebra/sparse/csPost.js
generated
vendored
Normal file
52
node_modules/mathjs/lib/esm/function/algebra/sparse/csPost.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csTdfs } from './csTdfs.js';
|
||||
|
||||
/**
|
||||
* Post order a tree of forest
|
||||
*
|
||||
* @param {Array} parent The tree or forest
|
||||
* @param {Number} n Number of columns
|
||||
*/
|
||||
export function csPost(parent, n) {
|
||||
// check inputs
|
||||
if (!parent) {
|
||||
return null;
|
||||
}
|
||||
// vars
|
||||
var k = 0;
|
||||
var j;
|
||||
// allocate result
|
||||
var post = []; // (n)
|
||||
// workspace, head: first n entries, next: next n entries, stack: last n entries
|
||||
var w = []; // (3 * n)
|
||||
var head = 0;
|
||||
var next = n;
|
||||
var stack = 2 * n;
|
||||
// initialize workspace
|
||||
for (j = 0; j < n; j++) {
|
||||
// empty linked lists
|
||||
w[head + j] = -1;
|
||||
}
|
||||
// traverse nodes in reverse order
|
||||
for (j = n - 1; j >= 0; j--) {
|
||||
// check j is a root
|
||||
if (parent[j] === -1) {
|
||||
continue;
|
||||
}
|
||||
// add j to list of its parent
|
||||
w[next + j] = w[head + parent[j]];
|
||||
w[head + parent[j]] = j;
|
||||
}
|
||||
// loop nodes
|
||||
for (j = 0; j < n; j++) {
|
||||
// skip j if it is not a root
|
||||
if (parent[j] !== -1) {
|
||||
continue;
|
||||
}
|
||||
// depth-first search
|
||||
k = csTdfs(j, k, w, head, next, post, stack);
|
||||
}
|
||||
return post;
|
||||
}
|
||||
52
node_modules/mathjs/lib/esm/function/algebra/sparse/csReach.js
generated
vendored
Normal file
52
node_modules/mathjs/lib/esm/function/algebra/sparse/csReach.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
import { csMarked } from './csMarked.js';
|
||||
import { csMark } from './csMark.js';
|
||||
import { csDfs } from './csDfs.js';
|
||||
|
||||
/**
|
||||
* The csReach function computes X = Reach(B), where B is the nonzero pattern of the n-by-1
|
||||
* sparse column of vector b. The function returns the set of nodes reachable from any node in B. The
|
||||
* nonzero pattern xi of the solution x to the sparse linear system Lx=b is given by X=Reach(B).
|
||||
*
|
||||
* @param {Matrix} g The G matrix
|
||||
* @param {Matrix} b The B matrix
|
||||
* @param {Number} k The kth column in B
|
||||
* @param {Array} xi The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
|
||||
* The first n entries is the nonzero pattern, the last n entries is the stack
|
||||
* @param {Array} pinv The inverse row permutation vector
|
||||
*
|
||||
* @return {Number} The index for the nonzero pattern
|
||||
*/
|
||||
export function csReach(g, b, k, xi, pinv) {
|
||||
// g arrays
|
||||
var gptr = g._ptr;
|
||||
var gsize = g._size;
|
||||
// b arrays
|
||||
var bindex = b._index;
|
||||
var bptr = b._ptr;
|
||||
// columns
|
||||
var n = gsize[1];
|
||||
// vars
|
||||
var p, p0, p1;
|
||||
// initialize top
|
||||
var top = n;
|
||||
// loop column indeces in B
|
||||
for (p0 = bptr[k], p1 = bptr[k + 1], p = p0; p < p1; p++) {
|
||||
// node i
|
||||
var i = bindex[p];
|
||||
// check node i is marked
|
||||
if (!csMarked(gptr, i)) {
|
||||
// start a dfs at unmarked node i
|
||||
top = csDfs(i, g, top, xi, pinv);
|
||||
}
|
||||
}
|
||||
// loop columns from top -> n - 1
|
||||
for (p = top; p < n; p++) {
|
||||
// restore G
|
||||
csMark(gptr, xi[p]);
|
||||
}
|
||||
return top;
|
||||
}
|
||||
84
node_modules/mathjs/lib/esm/function/algebra/sparse/csSpsolve.js
generated
vendored
Normal file
84
node_modules/mathjs/lib/esm/function/algebra/sparse/csSpsolve.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csReach } from './csReach.js';
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
var name = 'csSpsolve';
|
||||
var dependencies = ['divideScalar', 'multiply', 'subtract'];
|
||||
export var createCsSpsolve = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
divideScalar,
|
||||
multiply,
|
||||
subtract
|
||||
} = _ref;
|
||||
/**
|
||||
* The function csSpsolve() computes the solution to G * x = bk, where bk is the
|
||||
* kth column of B. When lo is true, the function assumes G = L is lower triangular with the
|
||||
* diagonal entry as the first entry in each column. When lo is true, the function assumes G = U
|
||||
* is upper triangular with the diagonal entry as the last entry in each column.
|
||||
*
|
||||
* @param {Matrix} g The G matrix
|
||||
* @param {Matrix} b The B matrix
|
||||
* @param {Number} k The kth column in B
|
||||
* @param {Array} xi The nonzero pattern xi[top] .. xi[n - 1], an array of size = 2 * n
|
||||
* The first n entries is the nonzero pattern, the last n entries is the stack
|
||||
* @param {Array} x The soluton to the linear system G * x = b
|
||||
* @param {Array} pinv The inverse row permutation vector, must be null for L * x = b
|
||||
* @param {boolean} lo The lower (true) upper triangular (false) flag
|
||||
*
|
||||
* @return {Number} The index for the nonzero pattern
|
||||
*/
|
||||
return function csSpsolve(g, b, k, xi, x, pinv, lo) {
|
||||
// g arrays
|
||||
var gvalues = g._values;
|
||||
var gindex = g._index;
|
||||
var gptr = g._ptr;
|
||||
var gsize = g._size;
|
||||
// columns
|
||||
var n = gsize[1];
|
||||
// b arrays
|
||||
var bvalues = b._values;
|
||||
var bindex = b._index;
|
||||
var bptr = b._ptr;
|
||||
// vars
|
||||
var p, p0, p1, q;
|
||||
// xi[top..n-1] = csReach(B(:,k))
|
||||
var top = csReach(g, b, k, xi, pinv);
|
||||
// clear x
|
||||
for (p = top; p < n; p++) {
|
||||
x[xi[p]] = 0;
|
||||
}
|
||||
// scatter b
|
||||
for (p0 = bptr[k], p1 = bptr[k + 1], p = p0; p < p1; p++) {
|
||||
x[bindex[p]] = bvalues[p];
|
||||
}
|
||||
// loop columns
|
||||
for (var px = top; px < n; px++) {
|
||||
// x array index for px
|
||||
var j = xi[px];
|
||||
// apply permutation vector (U x = b), j maps to column J of G
|
||||
var J = pinv ? pinv[j] : j;
|
||||
// check column J is empty
|
||||
if (J < 0) {
|
||||
continue;
|
||||
}
|
||||
// column value indeces in G, p0 <= p < p1
|
||||
p0 = gptr[J];
|
||||
p1 = gptr[J + 1];
|
||||
// x(j) /= G(j,j)
|
||||
x[j] = divideScalar(x[j], gvalues[lo ? p0 : p1 - 1]);
|
||||
// first entry L(j,j)
|
||||
p = lo ? p0 + 1 : p0;
|
||||
q = lo ? p1 : p1 - 1;
|
||||
// loop
|
||||
for (; p < q; p++) {
|
||||
// row
|
||||
var i = gindex[p];
|
||||
// x(i) -= G(i,j) * x(j)
|
||||
x[i] = subtract(x[i], multiply(gvalues[p], x[j]));
|
||||
}
|
||||
}
|
||||
// return top of stack
|
||||
return top;
|
||||
};
|
||||
});
|
||||
179
node_modules/mathjs/lib/esm/function/algebra/sparse/csSqr.js
generated
vendored
Normal file
179
node_modules/mathjs/lib/esm/function/algebra/sparse/csSqr.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csPermute } from './csPermute.js';
|
||||
import { csPost } from './csPost.js';
|
||||
import { csEtree } from './csEtree.js';
|
||||
import { createCsAmd } from './csAmd.js';
|
||||
import { createCsCounts } from './csCounts.js';
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
var name = 'csSqr';
|
||||
var dependencies = ['add', 'multiply', 'transpose'];
|
||||
export var createCsSqr = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
add,
|
||||
multiply,
|
||||
transpose
|
||||
} = _ref;
|
||||
var csAmd = createCsAmd({
|
||||
add,
|
||||
multiply,
|
||||
transpose
|
||||
});
|
||||
var csCounts = createCsCounts({
|
||||
transpose
|
||||
});
|
||||
|
||||
/**
|
||||
* Symbolic ordering and analysis for QR and LU decompositions.
|
||||
*
|
||||
* @param {Number} order The ordering strategy (see csAmd for more details)
|
||||
* @param {Matrix} a The A matrix
|
||||
* @param {boolean} qr Symbolic ordering and analysis for QR decomposition (true) or
|
||||
* symbolic ordering and analysis for LU decomposition (false)
|
||||
*
|
||||
* @return {Object} The Symbolic ordering and analysis for matrix A
|
||||
*/
|
||||
return function csSqr(order, a, qr) {
|
||||
// a arrays
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
// columns
|
||||
var n = asize[1];
|
||||
// vars
|
||||
var k;
|
||||
// symbolic analysis result
|
||||
var s = {};
|
||||
// fill-reducing ordering
|
||||
s.q = csAmd(order, a);
|
||||
// validate results
|
||||
if (order && !s.q) {
|
||||
return null;
|
||||
}
|
||||
// QR symbolic analysis
|
||||
if (qr) {
|
||||
// apply permutations if needed
|
||||
var c = order ? csPermute(a, null, s.q, 0) : a;
|
||||
// etree of C'*C, where C=A(:,q)
|
||||
s.parent = csEtree(c, 1);
|
||||
// post order elimination tree
|
||||
var post = csPost(s.parent, n);
|
||||
// col counts chol(C'*C)
|
||||
s.cp = csCounts(c, s.parent, post, 1);
|
||||
// check we have everything needed to calculate number of nonzero elements
|
||||
if (c && s.parent && s.cp && _vcount(c, s)) {
|
||||
// calculate number of nonzero elements
|
||||
for (s.unz = 0, k = 0; k < n; k++) {
|
||||
s.unz += s.cp[k];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// for LU factorization only, guess nnz(L) and nnz(U)
|
||||
s.unz = 4 * aptr[n] + n;
|
||||
s.lnz = s.unz;
|
||||
}
|
||||
// return result S
|
||||
return s;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute nnz(V) = s.lnz, s.pinv, s.leftmost, s.m2 from A and s.parent
|
||||
*/
|
||||
function _vcount(a, s) {
|
||||
// a arrays
|
||||
var aptr = a._ptr;
|
||||
var aindex = a._index;
|
||||
var asize = a._size;
|
||||
// rows & columns
|
||||
var m = asize[0];
|
||||
var n = asize[1];
|
||||
// initialize s arrays
|
||||
s.pinv = []; // (m + n)
|
||||
s.leftmost = []; // (m)
|
||||
// vars
|
||||
var parent = s.parent;
|
||||
var pinv = s.pinv;
|
||||
var leftmost = s.leftmost;
|
||||
// workspace, next: first m entries, head: next n entries, tail: next n entries, nque: next n entries
|
||||
var w = []; // (m + 3 * n)
|
||||
var next = 0;
|
||||
var head = m;
|
||||
var tail = m + n;
|
||||
var nque = m + 2 * n;
|
||||
// vars
|
||||
var i, k, p, p0, p1;
|
||||
// initialize w
|
||||
for (k = 0; k < n; k++) {
|
||||
// queue k is empty
|
||||
w[head + k] = -1;
|
||||
w[tail + k] = -1;
|
||||
w[nque + k] = 0;
|
||||
}
|
||||
// initialize row arrays
|
||||
for (i = 0; i < m; i++) {
|
||||
leftmost[i] = -1;
|
||||
}
|
||||
// loop columns backwards
|
||||
for (k = n - 1; k >= 0; k--) {
|
||||
// values & index for column k
|
||||
for (p0 = aptr[k], p1 = aptr[k + 1], p = p0; p < p1; p++) {
|
||||
// leftmost[i] = min(find(A(i,:)))
|
||||
leftmost[aindex[p]] = k;
|
||||
}
|
||||
}
|
||||
// scan rows in reverse order
|
||||
for (i = m - 1; i >= 0; i--) {
|
||||
// row i is not yet ordered
|
||||
pinv[i] = -1;
|
||||
k = leftmost[i];
|
||||
// check row i is empty
|
||||
if (k === -1) {
|
||||
continue;
|
||||
}
|
||||
// first row in queue k
|
||||
if (w[nque + k]++ === 0) {
|
||||
w[tail + k] = i;
|
||||
}
|
||||
// put i at head of queue k
|
||||
w[next + i] = w[head + k];
|
||||
w[head + k] = i;
|
||||
}
|
||||
s.lnz = 0;
|
||||
s.m2 = m;
|
||||
// find row permutation and nnz(V)
|
||||
for (k = 0; k < n; k++) {
|
||||
// remove row i from queue k
|
||||
i = w[head + k];
|
||||
// count V(k,k) as nonzero
|
||||
s.lnz++;
|
||||
// add a fictitious row
|
||||
if (i < 0) {
|
||||
i = s.m2++;
|
||||
}
|
||||
// associate row i with V(:,k)
|
||||
pinv[i] = k;
|
||||
// skip if V(k+1:m,k) is empty
|
||||
if (--nque[k] <= 0) {
|
||||
continue;
|
||||
}
|
||||
// nque[k] is nnz (V(k+1:m,k))
|
||||
s.lnz += w[nque + k];
|
||||
// move all rows to parent of k
|
||||
var pa = parent[k];
|
||||
if (pa !== -1) {
|
||||
if (w[nque + pa] === 0) {
|
||||
w[tail + pa] = w[tail + k];
|
||||
}
|
||||
w[next + w[tail + k]] = w[head + pa];
|
||||
w[head + pa] = w[next + i];
|
||||
w[nque + pa] += w[nque + k];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < m; i++) {
|
||||
if (pinv[i] < 0) {
|
||||
pinv[i] = k++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
93
node_modules/mathjs/lib/esm/function/algebra/sparse/csSymperm.js
generated
vendored
Normal file
93
node_modules/mathjs/lib/esm/function/algebra/sparse/csSymperm.js
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csCumsum } from './csCumsum.js';
|
||||
import { factory } from '../../../utils/factory.js';
|
||||
var name = 'csSymperm';
|
||||
var dependencies = ['conj', 'SparseMatrix'];
|
||||
export var createCsSymperm = /* #__PURE__ */factory(name, dependencies, _ref => {
|
||||
var {
|
||||
conj,
|
||||
SparseMatrix
|
||||
} = _ref;
|
||||
/**
|
||||
* Computes the symmetric permutation of matrix A accessing only
|
||||
* the upper triangular part of A.
|
||||
*
|
||||
* C = P * A * P'
|
||||
*
|
||||
* @param {Matrix} a The A matrix
|
||||
* @param {Array} pinv The inverse of permutation vector
|
||||
* @param {boolean} values Process matrix values (true)
|
||||
*
|
||||
* @return {Matrix} The C matrix, C = P * A * P'
|
||||
*/
|
||||
return function csSymperm(a, pinv, values) {
|
||||
// A matrix arrays
|
||||
var avalues = a._values;
|
||||
var aindex = a._index;
|
||||
var aptr = a._ptr;
|
||||
var asize = a._size;
|
||||
// columns
|
||||
var n = asize[1];
|
||||
// C matrix arrays
|
||||
var cvalues = values && avalues ? [] : null;
|
||||
var cindex = []; // (nz)
|
||||
var cptr = []; // (n + 1)
|
||||
// variables
|
||||
var i, i2, j, j2, p, p0, p1;
|
||||
// create workspace vector
|
||||
var w = []; // (n)
|
||||
// count entries in each column of C
|
||||
for (j = 0; j < n; j++) {
|
||||
// column j of A is column j2 of C
|
||||
j2 = pinv ? pinv[j] : j;
|
||||
// loop values in column j
|
||||
for (p0 = aptr[j], p1 = aptr[j + 1], p = p0; p < p1; p++) {
|
||||
// row
|
||||
i = aindex[p];
|
||||
// skip lower triangular part of A
|
||||
if (i > j) {
|
||||
continue;
|
||||
}
|
||||
// row i of A is row i2 of C
|
||||
i2 = pinv ? pinv[i] : i;
|
||||
// column count of C
|
||||
w[Math.max(i2, j2)]++;
|
||||
}
|
||||
}
|
||||
// compute column pointers of C
|
||||
csCumsum(cptr, w, n);
|
||||
// loop columns
|
||||
for (j = 0; j < n; j++) {
|
||||
// column j of A is column j2 of C
|
||||
j2 = pinv ? pinv[j] : j;
|
||||
// loop values in column j
|
||||
for (p0 = aptr[j], p1 = aptr[j + 1], p = p0; p < p1; p++) {
|
||||
// row
|
||||
i = aindex[p];
|
||||
// skip lower triangular part of A
|
||||
if (i > j) {
|
||||
continue;
|
||||
}
|
||||
// row i of A is row i2 of C
|
||||
i2 = pinv ? pinv[i] : i;
|
||||
// C index for column j2
|
||||
var q = w[Math.max(i2, j2)]++;
|
||||
// update C index for entry q
|
||||
cindex[q] = Math.min(i2, j2);
|
||||
// check we need to process values
|
||||
if (cvalues) {
|
||||
cvalues[q] = i2 <= j2 ? avalues[p] : conj(avalues[p]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// return C matrix
|
||||
return new SparseMatrix({
|
||||
values: cvalues,
|
||||
index: cindex,
|
||||
ptr: cptr,
|
||||
size: [n, n]
|
||||
});
|
||||
};
|
||||
});
|
||||
42
node_modules/mathjs/lib/esm/function/algebra/sparse/csTdfs.js
generated
vendored
Normal file
42
node_modules/mathjs/lib/esm/function/algebra/sparse/csTdfs.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
|
||||
/**
|
||||
* Depth-first search and postorder of a tree rooted at node j
|
||||
*
|
||||
* @param {Number} j The tree node
|
||||
* @param {Number} k
|
||||
* @param {Array} w The workspace array
|
||||
* @param {Number} head The index offset within the workspace for the head array
|
||||
* @param {Number} next The index offset within the workspace for the next array
|
||||
* @param {Array} post The post ordering array
|
||||
* @param {Number} stack The index offset within the workspace for the stack array
|
||||
*/
|
||||
export function csTdfs(j, k, w, head, next, post, stack) {
|
||||
// variables
|
||||
var top = 0;
|
||||
// place j on the stack
|
||||
w[stack] = j;
|
||||
// while (stack is not empty)
|
||||
while (top >= 0) {
|
||||
// p = top of stack
|
||||
var p = w[stack + top];
|
||||
// i = youngest child of p
|
||||
var i = w[head + p];
|
||||
if (i === -1) {
|
||||
// p has no unordered children left
|
||||
top--;
|
||||
// node p is the kth postordered node
|
||||
post[k++] = p;
|
||||
} else {
|
||||
// remove i from children of p
|
||||
w[head + p] = w[next + i];
|
||||
// increment top
|
||||
++top;
|
||||
// start dfs on child node i
|
||||
w[stack + top] = i;
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
14
node_modules/mathjs/lib/esm/function/algebra/sparse/csUnflip.js
generated
vendored
Normal file
14
node_modules/mathjs/lib/esm/function/algebra/sparse/csUnflip.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) 2006-2024, Timothy A. Davis, All Rights Reserved.
|
||||
// SPDX-License-Identifier: LGPL-2.1+
|
||||
// https://github.com/DrTimothyAldenDavis/SuiteSparse/tree/dev/CSparse/Source
|
||||
import { csFlip } from './csFlip.js';
|
||||
|
||||
/**
|
||||
* Flips the value if it is negative of returns the same value otherwise.
|
||||
*
|
||||
* @param {Number} i The value to flip
|
||||
*/
|
||||
export function csUnflip(i) {
|
||||
// flip the value if it is negative
|
||||
return i < 0 ? csFlip(i) : i;
|
||||
}
|
||||
Reference in New Issue
Block a user