"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCsSqr = void 0; var _csPermute = require("./csPermute.js"); var _csPost = require("./csPost.js"); var _csEtree = require("./csEtree.js"); var _csAmd = require("./csAmd.js"); var _csCounts = require("./csCounts.js"); var _factory = require("../../../utils/factory.js"); // 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 const name = 'csSqr'; const dependencies = ['add', 'multiply', 'transpose']; const createCsSqr = exports.createCsSqr = /* #__PURE__ */(0, _factory.factory)(name, dependencies, _ref => { let { add, multiply, transpose } = _ref; const csAmd = (0, _csAmd.createCsAmd)({ add, multiply, transpose }); const csCounts = (0, _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 const aptr = a._ptr; const asize = a._size; // columns const n = asize[1]; // vars let k; // symbolic analysis result const 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 const c = order ? (0, _csPermute.csPermute)(a, null, s.q, 0) : a; // etree of C'*C, where C=A(:,q) s.parent = (0, _csEtree.csEtree)(c, 1); // post order elimination tree const post = (0, _csPost.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 const aptr = a._ptr; const aindex = a._index; const asize = a._size; // rows & columns const m = asize[0]; const n = asize[1]; // initialize s arrays s.pinv = []; // (m + n) s.leftmost = []; // (m) // vars const parent = s.parent; const pinv = s.pinv; const leftmost = s.leftmost; // workspace, next: first m entries, head: next n entries, tail: next n entries, nque: next n entries const w = []; // (m + 3 * n) const next = 0; const head = m; const tail = m + n; const nque = m + 2 * n; // vars let 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 const 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; } });