"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createRealSymmetric = createRealSymmetric; var _object = require("../../../utils/object.js"); function createRealSymmetric(_ref) { let { config, addScalar, subtract, abs, atan, cos, sin, multiplyScalar, inv, bignumber, multiply, add } = _ref; /** * @param {number[] | BigNumber[]} arr * @param {number} N * @param {number} prec * @param {'number' | 'BigNumber'} type */ function main(arr, N) { let prec = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : config.relTol; let type = arguments.length > 3 ? arguments[3] : undefined; let computeVectors = arguments.length > 4 ? arguments[4] : undefined; if (type === 'number') { return diag(arr, prec, computeVectors); } if (type === 'BigNumber') { return diagBig(arr, prec, computeVectors); } throw TypeError('Unsupported data type: ' + type); } // diagonalization implementation for number (efficient) function diag(x, precision, computeVectors) { const N = x.length; const e0 = Math.abs(precision / N); let psi; let Sij; if (computeVectors) { Sij = new Array(N); // Sij is Identity Matrix for (let i = 0; i < N; i++) { Sij[i] = Array(N).fill(0); Sij[i][i] = 1.0; } } // initial error let Vab = getAij(x); while (Math.abs(Vab[1]) >= Math.abs(e0)) { const i = Vab[0][0]; const j = Vab[0][1]; psi = getTheta(x[i][i], x[j][j], x[i][j]); x = x1(x, psi, i, j); if (computeVectors) Sij = Sij1(Sij, psi, i, j); Vab = getAij(x); } const Ei = Array(N).fill(0); // eigenvalues for (let i = 0; i < N; i++) { Ei[i] = x[i][i]; } return sorting((0, _object.clone)(Ei), Sij, computeVectors); } // diagonalization implementation for bigNumber function diagBig(x, precision, computeVectors) { const N = x.length; const e0 = abs(precision / N); let psi; let Sij; if (computeVectors) { Sij = new Array(N); // Sij is Identity Matrix for (let i = 0; i < N; i++) { Sij[i] = Array(N).fill(0); Sij[i][i] = 1.0; } } // initial error let Vab = getAijBig(x); while (abs(Vab[1]) >= abs(e0)) { const i = Vab[0][0]; const j = Vab[0][1]; psi = getThetaBig(x[i][i], x[j][j], x[i][j]); x = x1Big(x, psi, i, j); if (computeVectors) Sij = Sij1Big(Sij, psi, i, j); Vab = getAijBig(x); } const Ei = Array(N).fill(0); // eigenvalues for (let i = 0; i < N; i++) { Ei[i] = x[i][i]; } // return [clone(Ei), clone(Sij)] return sorting((0, _object.clone)(Ei), Sij, computeVectors); } // get angle function getTheta(aii, ajj, aij) { const denom = ajj - aii; if (Math.abs(denom) <= config.relTol) { return Math.PI / 4.0; } else { return 0.5 * Math.atan(2.0 * aij / (ajj - aii)); } } // get angle function getThetaBig(aii, ajj, aij) { const denom = subtract(ajj, aii); if (abs(denom) <= config.relTol) { return bignumber(-1).acos().div(4); } else { return multiplyScalar(0.5, atan(multiply(2.0, aij, inv(denom)))); } } // update eigvec function Sij1(Sij, theta, i, j) { const N = Sij.length; const c = Math.cos(theta); const s = Math.sin(theta); const Ski = Array(N).fill(0); const Skj = Array(N).fill(0); for (let k = 0; k < N; k++) { Ski[k] = c * Sij[k][i] - s * Sij[k][j]; Skj[k] = s * Sij[k][i] + c * Sij[k][j]; } for (let k = 0; k < N; k++) { Sij[k][i] = Ski[k]; Sij[k][j] = Skj[k]; } return Sij; } // update eigvec for overlap function Sij1Big(Sij, theta, i, j) { const N = Sij.length; const c = cos(theta); const s = sin(theta); const Ski = Array(N).fill(bignumber(0)); const Skj = Array(N).fill(bignumber(0)); for (let k = 0; k < N; k++) { Ski[k] = subtract(multiplyScalar(c, Sij[k][i]), multiplyScalar(s, Sij[k][j])); Skj[k] = addScalar(multiplyScalar(s, Sij[k][i]), multiplyScalar(c, Sij[k][j])); } for (let k = 0; k < N; k++) { Sij[k][i] = Ski[k]; Sij[k][j] = Skj[k]; } return Sij; } // update matrix function x1Big(Hij, theta, i, j) { const N = Hij.length; const c = bignumber(cos(theta)); const s = bignumber(sin(theta)); const c2 = multiplyScalar(c, c); const s2 = multiplyScalar(s, s); const Aki = Array(N).fill(bignumber(0)); const Akj = Array(N).fill(bignumber(0)); // 2cs Hij const csHij = multiply(bignumber(2), c, s, Hij[i][j]); // Aii const Aii = addScalar(subtract(multiplyScalar(c2, Hij[i][i]), csHij), multiplyScalar(s2, Hij[j][j])); const Ajj = add(multiplyScalar(s2, Hij[i][i]), csHij, multiplyScalar(c2, Hij[j][j])); // 0 to i for (let k = 0; k < N; k++) { Aki[k] = subtract(multiplyScalar(c, Hij[i][k]), multiplyScalar(s, Hij[j][k])); Akj[k] = addScalar(multiplyScalar(s, Hij[i][k]), multiplyScalar(c, Hij[j][k])); } // Modify Hij Hij[i][i] = Aii; Hij[j][j] = Ajj; Hij[i][j] = bignumber(0); Hij[j][i] = bignumber(0); // 0 to i for (let k = 0; k < N; k++) { if (k !== i && k !== j) { Hij[i][k] = Aki[k]; Hij[k][i] = Aki[k]; Hij[j][k] = Akj[k]; Hij[k][j] = Akj[k]; } } return Hij; } // update matrix function x1(Hij, theta, i, j) { const N = Hij.length; const c = Math.cos(theta); const s = Math.sin(theta); const c2 = c * c; const s2 = s * s; const Aki = Array(N).fill(0); const Akj = Array(N).fill(0); // Aii const Aii = c2 * Hij[i][i] - 2 * c * s * Hij[i][j] + s2 * Hij[j][j]; const Ajj = s2 * Hij[i][i] + 2 * c * s * Hij[i][j] + c2 * Hij[j][j]; // 0 to i for (let k = 0; k < N; k++) { Aki[k] = c * Hij[i][k] - s * Hij[j][k]; Akj[k] = s * Hij[i][k] + c * Hij[j][k]; } // Modify Hij Hij[i][i] = Aii; Hij[j][j] = Ajj; Hij[i][j] = 0; Hij[j][i] = 0; // 0 to i for (let k = 0; k < N; k++) { if (k !== i && k !== j) { Hij[i][k] = Aki[k]; Hij[k][i] = Aki[k]; Hij[j][k] = Akj[k]; Hij[k][j] = Akj[k]; } } return Hij; } // get max off-diagonal value from Upper Diagonal function getAij(Mij) { const N = Mij.length; let maxMij = 0; let maxIJ = [0, 1]; for (let i = 0; i < N; i++) { for (let j = i + 1; j < N; j++) { if (Math.abs(maxMij) < Math.abs(Mij[i][j])) { maxMij = Math.abs(Mij[i][j]); maxIJ = [i, j]; } } } return [maxIJ, maxMij]; } // get max off-diagonal value from Upper Diagonal function getAijBig(Mij) { const N = Mij.length; let maxMij = 0; let maxIJ = [0, 1]; for (let i = 0; i < N; i++) { for (let j = i + 1; j < N; j++) { if (abs(maxMij) < abs(Mij[i][j])) { maxMij = abs(Mij[i][j]); maxIJ = [i, j]; } } } return [maxIJ, maxMij]; } // sort results function sorting(E, S, computeVectors) { const N = E.length; const values = Array(N); let vecs; if (computeVectors) { vecs = Array(N); for (let k = 0; k < N; k++) { vecs[k] = Array(N); } } for (let i = 0; i < N; i++) { let minID = 0; let minE = E[0]; for (let j = 0; j < E.length; j++) { if (abs(E[j]) < abs(minE)) { minID = j; minE = E[minID]; } } values[i] = E.splice(minID, 1)[0]; if (computeVectors) { for (let k = 0; k < N; k++) { vecs[i][k] = S[k][minID]; S[k].splice(minID, 1); } } } if (!computeVectors) return { values }; const eigenvectors = vecs.map((vector, i) => ({ value: values[i], vector })); return { values, eigenvectors }; } return main; }