ml-sparse-matrix
Advanced tools
Comparing version 1.0.0 to 2.0.0
@@ -0,1 +1,15 @@ | ||
# [2.0.0](https://github.com/mljs/sparse-matrix/compare/v1.0.0...v2.0.0) (2019-06-29) | ||
### chore | ||
* update dependencies and remove support for Node.js 6 ([4daad75](https://github.com/mljs/sparse-matrix/commit/4daad75)) | ||
### BREAKING CHANGES | ||
* Node.js 6 is no longer supported. | ||
<a name="1.0.0"></a> | ||
@@ -2,0 +16,0 @@ # [1.0.0](https://github.com/mljs/sparse-matrix/compare/v0.2.1...v1.0.0) (2017-12-11) |
507
lib/index.js
@@ -10,222 +10,232 @@ 'use strict'; | ||
class SparseMatrix { | ||
constructor(rows, columns, options = {}) { | ||
if (rows instanceof SparseMatrix) { // clone | ||
const other = rows; | ||
this._init(other.rows, other.columns, other.elements.clone(), other.threshold); | ||
return; | ||
} | ||
constructor(rows, columns, options = {}) { | ||
if (rows instanceof SparseMatrix) { | ||
// clone | ||
const other = rows; | ||
this._init( | ||
other.rows, | ||
other.columns, | ||
other.elements.clone(), | ||
other.threshold | ||
); | ||
return; | ||
} | ||
if (Array.isArray(rows)) { | ||
const matrix = rows; | ||
rows = matrix.length; | ||
options = columns || {}; | ||
columns = matrix[0].length; | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
for (var i = 0; i < rows; i++) { | ||
for (var j = 0; j < columns; j++) { | ||
var value = matrix[i][j]; | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value !== 0) { | ||
this.elements.set(i * columns + j, matrix[i][j]); | ||
} | ||
} | ||
} | ||
} else { | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
if (Array.isArray(rows)) { | ||
const matrix = rows; | ||
rows = matrix.length; | ||
options = columns || {}; | ||
columns = matrix[0].length; | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
for (var i = 0; i < rows; i++) { | ||
for (var j = 0; j < columns; j++) { | ||
var value = matrix[i][j]; | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value !== 0) { | ||
this.elements.set(i * columns + j, matrix[i][j]); | ||
} | ||
} | ||
} | ||
} else { | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
} | ||
} | ||
_init(rows, columns, elements, threshold) { | ||
this.rows = rows; | ||
this.columns = columns; | ||
this.elements = elements; | ||
this.threshold = threshold || 0; | ||
} | ||
_init(rows, columns, elements, threshold) { | ||
this.rows = rows; | ||
this.columns = columns; | ||
this.elements = elements; | ||
this.threshold = threshold || 0; | ||
} | ||
static eye(rows = 1, columns = rows) { | ||
const min = Math.min(rows, columns); | ||
const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); | ||
for (var i = 0; i < min; i++) { | ||
matrix.set(i, i, 1); | ||
} | ||
return matrix; | ||
static eye(rows = 1, columns = rows) { | ||
const min = Math.min(rows, columns); | ||
const matrix = new SparseMatrix(rows, columns, { initialCapacity: min }); | ||
for (var i = 0; i < min; i++) { | ||
matrix.set(i, i, 1); | ||
} | ||
return matrix; | ||
} | ||
clone() { | ||
return new SparseMatrix(this); | ||
} | ||
clone() { | ||
return new SparseMatrix(this); | ||
} | ||
to2DArray() { | ||
const copy = new Array(this.rows); | ||
for (var i = 0; i < this.rows; i++) { | ||
copy[i] = new Array(this.columns); | ||
for (var j = 0; j < this.columns; j++) { | ||
copy[i][j] = this.get(i, j); | ||
} | ||
} | ||
return copy; | ||
to2DArray() { | ||
const copy = new Array(this.rows); | ||
for (var i = 0; i < this.rows; i++) { | ||
copy[i] = new Array(this.columns); | ||
for (var j = 0; j < this.columns; j++) { | ||
copy[i][j] = this.get(i, j); | ||
} | ||
} | ||
return copy; | ||
} | ||
isSquare() { | ||
return this.rows === this.columns; | ||
} | ||
isSquare() { | ||
return this.rows === this.columns; | ||
} | ||
isSymmetric() { | ||
if (!this.isSquare()) return false; | ||
isSymmetric() { | ||
if (!this.isSquare()) return false; | ||
var symmetric = true; | ||
this.forEachNonZero((i, j, v) => { | ||
if (this.get(j, i) !== v) { | ||
symmetric = false; | ||
return false; | ||
} | ||
return v; | ||
}); | ||
return symmetric; | ||
} | ||
var symmetric = true; | ||
this.forEachNonZero((i, j, v) => { | ||
if (this.get(j, i) !== v) { | ||
symmetric = false; | ||
return false; | ||
} | ||
return v; | ||
}); | ||
return symmetric; | ||
} | ||
/** | ||
* Search for the wither band in the main diagonals | ||
* @return {number} | ||
*/ | ||
bandWidth() { | ||
let min = this.columns; | ||
let max = -1; | ||
this.forEachNonZero((i, j, v) => { | ||
let diff = i - j; | ||
min = Math.min(min, diff); | ||
max = Math.max(max, diff); | ||
return v; | ||
}); | ||
return max - min; | ||
} | ||
/** | ||
* Search for the wither band in the main diagonals | ||
* @return {number} | ||
*/ | ||
bandWidth() { | ||
let min = this.columns; | ||
let max = -1; | ||
this.forEachNonZero((i, j, v) => { | ||
let diff = i - j; | ||
min = Math.min(min, diff); | ||
max = Math.max(max, diff); | ||
return v; | ||
}); | ||
return max - min; | ||
} | ||
/** | ||
* Test if a matrix is consider banded using a threshold | ||
* @param {number} width | ||
* @return {boolean} | ||
*/ | ||
isBanded(width) { | ||
let bandWidth = this.bandWidth(); | ||
return bandWidth <= width; | ||
} | ||
/** | ||
* Test if a matrix is consider banded using a threshold | ||
* @param {number} width | ||
* @return {boolean} | ||
*/ | ||
isBanded(width) { | ||
let bandWidth = this.bandWidth(); | ||
return bandWidth <= width; | ||
} | ||
get cardinality() { | ||
return this.elements.size; | ||
} | ||
get cardinality() { | ||
return this.elements.size; | ||
} | ||
get size() { | ||
return this.rows * this.columns; | ||
} | ||
get size() { | ||
return this.rows * this.columns; | ||
} | ||
get(row, column) { | ||
return this.elements.get(row * this.columns + column); | ||
get(row, column) { | ||
return this.elements.get(row * this.columns + column); | ||
} | ||
set(row, column, value) { | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value === 0) { | ||
this.elements.remove(row * this.columns + column); | ||
} else { | ||
this.elements.set(row * this.columns + column, value); | ||
} | ||
return this; | ||
} | ||
set(row, column, value) { | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value === 0) { | ||
this.elements.remove(row * this.columns + column); | ||
} else { | ||
this.elements.set(row * this.columns + column, value); | ||
} | ||
return this; | ||
mmul(other) { | ||
if (this.columns !== other.rows) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
'Number of columns of left matrix are not equal to number of rows of right matrix.' | ||
); | ||
} | ||
mmul(other) { | ||
if (this.columns !== other.rows) { | ||
// eslint-disable-next-line no-console | ||
console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); | ||
const m = this.rows; | ||
const p = other.columns; | ||
const result = new SparseMatrix(m, p); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
if (j === k) { | ||
result.set(i, l, result.get(i, l) + v1 * v2); | ||
} | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
const m = this.rows; | ||
const p = other.columns; | ||
kroneckerProduct(other) { | ||
const m = this.rows; | ||
const n = this.columns; | ||
const p = other.rows; | ||
const q = other.columns; | ||
const result = new SparseMatrix(m, p); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
if (j === k) { | ||
result.set(i, l, result.get(i, l) + v1 * v2); | ||
} | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
const result = new SparseMatrix(m * p, n * q, { | ||
initialCapacity: this.cardinality * other.cardinality | ||
}); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
result.set(p * i + k, q * j + l, v1 * v2); | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
kroneckerProduct(other) { | ||
const m = this.rows; | ||
const n = this.columns; | ||
const p = other.rows; | ||
const q = other.columns; | ||
forEachNonZero(callback) { | ||
this.elements.forEachPair((key, value) => { | ||
const i = (key / this.columns) | 0; | ||
const j = key % this.columns; | ||
let r = callback(i, j, value); | ||
if (r === false) return false; // stop iteration | ||
if (this.threshold && Math.abs(r) < this.threshold) r = 0; | ||
if (r !== value) { | ||
if (r === 0) { | ||
this.elements.remove(key, true); | ||
} else { | ||
this.elements.set(key, r); | ||
} | ||
} | ||
return true; | ||
}); | ||
this.elements.maybeShrinkCapacity(); | ||
return this; | ||
} | ||
const result = new SparseMatrix(m * p, n * q, { | ||
initialCapacity: this.cardinality * other.cardinality | ||
}); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
result.set(p * i + k, q * j + l, v1 * v2); | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
getNonZeros() { | ||
const cardinality = this.cardinality; | ||
const rows = new Array(cardinality); | ||
const columns = new Array(cardinality); | ||
const values = new Array(cardinality); | ||
var idx = 0; | ||
this.forEachNonZero((i, j, value) => { | ||
rows[idx] = i; | ||
columns[idx] = j; | ||
values[idx] = value; | ||
idx++; | ||
return value; | ||
}); | ||
return { rows, columns, values }; | ||
} | ||
forEachNonZero(callback) { | ||
this.elements.forEachPair((key, value) => { | ||
const i = (key / this.columns) | 0; | ||
const j = key % this.columns; | ||
let r = callback(i, j, value); | ||
if (r === false) return false; // stop iteration | ||
if (this.threshold && Math.abs(r) < this.threshold) r = 0; | ||
if (r !== value) { | ||
if (r === 0) { | ||
this.elements.remove(key, true); | ||
} else { | ||
this.elements.set(key, r); | ||
} | ||
} | ||
return true; | ||
}); | ||
this.elements.maybeShrinkCapacity(); | ||
return this; | ||
setThreshold(newThreshold) { | ||
if (newThreshold !== 0 && newThreshold !== this.threshold) { | ||
this.threshold = newThreshold; | ||
this.forEachNonZero((i, j, v) => v); | ||
} | ||
return this; | ||
} | ||
getNonZeros() { | ||
const cardinality = this.cardinality; | ||
const rows = new Array(cardinality); | ||
const columns = new Array(cardinality); | ||
const values = new Array(cardinality); | ||
var idx = 0; | ||
this.forEachNonZero((i, j, value) => { | ||
rows[idx] = i; | ||
columns[idx] = j; | ||
values[idx] = value; | ||
idx++; | ||
return value; | ||
}); | ||
return {rows, columns, values}; | ||
} | ||
setThreshold(newThreshold) { | ||
if (newThreshold !== 0 && newThreshold !== this.threshold) { | ||
this.threshold = newThreshold; | ||
this.forEachNonZero((i, j, v) => v); | ||
} | ||
return this; | ||
} | ||
/** | ||
* @return {SparseMatrix} - New transposed sparse matrix | ||
*/ | ||
transpose() { | ||
let trans = new SparseMatrix(this.columns, this.rows, {initialCapacity: this.cardinality}); | ||
this.forEachNonZero((i, j, value) => { | ||
trans.set(j, i, value); | ||
return value; | ||
}); | ||
return trans; | ||
} | ||
/** | ||
* @return {SparseMatrix} - New transposed sparse matrix | ||
*/ | ||
transpose() { | ||
let trans = new SparseMatrix(this.columns, this.rows, { | ||
initialCapacity: this.cardinality | ||
}); | ||
this.forEachNonZero((i, j, value) => { | ||
trans.set(j, i, value); | ||
return value; | ||
}); | ||
return trans; | ||
} | ||
} | ||
@@ -288,53 +298,100 @@ | ||
const operators = [ | ||
// Arithmetic operators | ||
['+', 'add'], | ||
['-', 'sub', 'subtract'], | ||
['*', 'mul', 'multiply'], | ||
['/', 'div', 'divide'], | ||
['%', 'mod', 'modulus'], | ||
// Bitwise operators | ||
['&', 'and'], | ||
['|', 'or'], | ||
['^', 'xor'], | ||
['<<', 'leftShift'], | ||
['>>', 'signPropagatingRightShift'], | ||
['>>>', 'rightShift', 'zeroFillRightShift'] | ||
// Arithmetic operators | ||
['+', 'add'], | ||
['-', 'sub', 'subtract'], | ||
['*', 'mul', 'multiply'], | ||
['/', 'div', 'divide'], | ||
['%', 'mod', 'modulus'], | ||
// Bitwise operators | ||
['&', 'and'], | ||
['|', 'or'], | ||
['^', 'xor'], | ||
['<<', 'leftShift'], | ||
['>>', 'signPropagatingRightShift'], | ||
['>>>', 'rightShift', 'zeroFillRightShift'] | ||
]; | ||
for (const operator of operators) { | ||
for (let i = 1; i < operator.length; i++) { | ||
SparseMatrix.prototype[operator[i]] = eval(fillTemplateFunction(inplaceOperator, {name: operator[i], op: operator[0]})); | ||
SparseMatrix.prototype[operator[i] + 'S'] = eval(fillTemplateFunction(inplaceOperatorScalar, {name: operator[i] + 'S', op: operator[0]})); | ||
SparseMatrix.prototype[operator[i] + 'M'] = eval(fillTemplateFunction(inplaceOperatorMatrix, {name: operator[i] + 'M', op: operator[0]})); | ||
for (let i = 1; i < operator.length; i++) { | ||
SparseMatrix.prototype[operator[i]] = eval( | ||
fillTemplateFunction(inplaceOperator, { | ||
name: operator[i], | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix.prototype[`${operator[i]}S`] = eval( | ||
fillTemplateFunction(inplaceOperatorScalar, { | ||
name: `${operator[i]}S`, | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix.prototype[`${operator[i]}M`] = eval( | ||
fillTemplateFunction(inplaceOperatorMatrix, { | ||
name: `${operator[i]}M`, | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix[operator[i]] = eval(fillTemplateFunction(staticOperator, {name: operator[i]})); | ||
} | ||
SparseMatrix[operator[i]] = eval( | ||
fillTemplateFunction(staticOperator, { name: operator[i] }) | ||
); | ||
} | ||
} | ||
var methods = [ | ||
['~', 'not'] | ||
]; | ||
var methods = [['~', 'not']]; | ||
[ | ||
'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil', | ||
'clz32', 'cos', 'cosh', 'exp', 'expm1', 'floor', 'fround', 'log', 'log1p', | ||
'log10', 'log2', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc' | ||
'abs', | ||
'acos', | ||
'acosh', | ||
'asin', | ||
'asinh', | ||
'atan', | ||
'atanh', | ||
'cbrt', | ||
'ceil', | ||
'clz32', | ||
'cos', | ||
'cosh', | ||
'exp', | ||
'expm1', | ||
'floor', | ||
'fround', | ||
'log', | ||
'log1p', | ||
'log10', | ||
'log2', | ||
'round', | ||
'sign', | ||
'sin', | ||
'sinh', | ||
'sqrt', | ||
'tan', | ||
'tanh', | ||
'trunc' | ||
].forEach(function (mathMethod) { | ||
methods.push(['Math.' + mathMethod, mathMethod]); | ||
methods.push([`Math.${mathMethod}`, mathMethod]); | ||
}); | ||
for (const method of methods) { | ||
for (let i = 1; i < method.length; i++) { | ||
SparseMatrix.prototype[method[i]] = eval(fillTemplateFunction(inplaceMethod, {name: method[i], method: method[0]})); | ||
SparseMatrix[method[i]] = eval(fillTemplateFunction(staticMethod, {name: method[i]})); | ||
} | ||
for (let i = 1; i < method.length; i++) { | ||
SparseMatrix.prototype[method[i]] = eval( | ||
fillTemplateFunction(inplaceMethod, { | ||
name: method[i], | ||
method: method[0] | ||
}) | ||
); | ||
SparseMatrix[method[i]] = eval( | ||
fillTemplateFunction(staticMethod, { name: method[i] }) | ||
); | ||
} | ||
} | ||
function fillTemplateFunction(template, values) { | ||
for (const i in values) { | ||
template = template.replace(new RegExp('%' + i + '%', 'g'), values[i]); | ||
} | ||
return template; | ||
for (const i in values) { | ||
template = template.replace(new RegExp(`%${i}%`, 'g'), values[i]); | ||
} | ||
return template; | ||
} | ||
exports.SparseMatrix = SparseMatrix; |
{ | ||
"name": "ml-sparse-matrix", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Sparse matrix library", | ||
@@ -12,8 +12,9 @@ "main": "lib/index.js", | ||
"scripts": { | ||
"compile": "rollup -c", | ||
"eslint": "eslint src", | ||
"eslint-fix": "npm run eslint -- --fix", | ||
"prepublish": "rollup -c", | ||
"test": "run-s testonly eslint", | ||
"testonly": "jest", | ||
"test-travis": "jest --coverage && codecov" | ||
"prepublishOnly": "npm run compile", | ||
"test": "npm run test-coverage && npm run eslint", | ||
"test-only": "jest", | ||
"test-coverage": "jest --coverage" | ||
}, | ||
@@ -35,14 +36,13 @@ "repository": { | ||
"dependencies": { | ||
"ml-hash-table": "^0.2.1" | ||
"ml-hash-table": "^1.0.0" | ||
}, | ||
"devDependencies": { | ||
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", | ||
"codecov": "^3.0.0", | ||
"eslint": "^4.13.0", | ||
"eslint-config-cheminfo": "^1.8.0", | ||
"eslint-plugin-no-only-tests": "^2.0.0", | ||
"jest": "^21.2.1", | ||
"npm-run-all": "^4.0.2", | ||
"rollup": "^0.52.1" | ||
"@babel/plugin-transform-modules-commonjs": "^7.4.4", | ||
"eslint": "^6.0.1", | ||
"eslint-config-cheminfo": "^1.20.1", | ||
"eslint-plugin-import": "^2.18.0", | ||
"eslint-plugin-jest": "^22.7.1", | ||
"jest": "^24.8.0", | ||
"rollup": "^1.16.3" | ||
} | ||
} |
# sparse-matrix | ||
[![NPM version][npm-image]][npm-url] | ||
[![build status][travis-image]][travis-url] | ||
[![coverage status][codecov-image]][codecov-url] | ||
[![npm download][download-image]][download-url] | ||
[![NPM version][npm-image]][npm-url] | ||
[![build status][travis-image]][travis-url] | ||
[![coverage status][codecov-image]][codecov-url] | ||
[![npm download][download-image]][download-url] | ||
@@ -12,3 +12,3 @@ Sparse matrix library. | ||
`$ npm install --save ml-sparse-matrix` | ||
`$ npm i ml-sparse-matrix` | ||
@@ -18,3 +18,3 @@ ## Usage | ||
```js | ||
import {SparseMatrix} from 'ml-sparse-matrix'; | ||
import { SparseMatrix } from 'ml-sparse-matrix'; | ||
@@ -30,3 +30,3 @@ const matrix1 = new SparseMatrix([[1, 2], [3, 4]]); | ||
[MIT](./LICENSE) | ||
[MIT](./LICENSE) | ||
@@ -33,0 +33,0 @@ [npm-image]: https://img.shields.io/npm/v/ml-sparse-matrix.svg?style=flat-square |
507
src/index.js
import HashTable from 'ml-hash-table'; | ||
export class SparseMatrix { | ||
constructor(rows, columns, options = {}) { | ||
if (rows instanceof SparseMatrix) { // clone | ||
const other = rows; | ||
this._init(other.rows, other.columns, other.elements.clone(), other.threshold); | ||
return; | ||
} | ||
constructor(rows, columns, options = {}) { | ||
if (rows instanceof SparseMatrix) { | ||
// clone | ||
const other = rows; | ||
this._init( | ||
other.rows, | ||
other.columns, | ||
other.elements.clone(), | ||
other.threshold | ||
); | ||
return; | ||
} | ||
if (Array.isArray(rows)) { | ||
const matrix = rows; | ||
rows = matrix.length; | ||
options = columns || {}; | ||
columns = matrix[0].length; | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
for (var i = 0; i < rows; i++) { | ||
for (var j = 0; j < columns; j++) { | ||
var value = matrix[i][j]; | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value !== 0) { | ||
this.elements.set(i * columns + j, matrix[i][j]); | ||
} | ||
} | ||
} | ||
} else { | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
if (Array.isArray(rows)) { | ||
const matrix = rows; | ||
rows = matrix.length; | ||
options = columns || {}; | ||
columns = matrix[0].length; | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
for (var i = 0; i < rows; i++) { | ||
for (var j = 0; j < columns; j++) { | ||
var value = matrix[i][j]; | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value !== 0) { | ||
this.elements.set(i * columns + j, matrix[i][j]); | ||
} | ||
} | ||
} | ||
} else { | ||
this._init(rows, columns, new HashTable(options), options.threshold); | ||
} | ||
} | ||
_init(rows, columns, elements, threshold) { | ||
this.rows = rows; | ||
this.columns = columns; | ||
this.elements = elements; | ||
this.threshold = threshold || 0; | ||
} | ||
_init(rows, columns, elements, threshold) { | ||
this.rows = rows; | ||
this.columns = columns; | ||
this.elements = elements; | ||
this.threshold = threshold || 0; | ||
} | ||
static eye(rows = 1, columns = rows) { | ||
const min = Math.min(rows, columns); | ||
const matrix = new SparseMatrix(rows, columns, {initialCapacity: min}); | ||
for (var i = 0; i < min; i++) { | ||
matrix.set(i, i, 1); | ||
} | ||
return matrix; | ||
static eye(rows = 1, columns = rows) { | ||
const min = Math.min(rows, columns); | ||
const matrix = new SparseMatrix(rows, columns, { initialCapacity: min }); | ||
for (var i = 0; i < min; i++) { | ||
matrix.set(i, i, 1); | ||
} | ||
return matrix; | ||
} | ||
clone() { | ||
return new SparseMatrix(this); | ||
} | ||
clone() { | ||
return new SparseMatrix(this); | ||
} | ||
to2DArray() { | ||
const copy = new Array(this.rows); | ||
for (var i = 0; i < this.rows; i++) { | ||
copy[i] = new Array(this.columns); | ||
for (var j = 0; j < this.columns; j++) { | ||
copy[i][j] = this.get(i, j); | ||
} | ||
} | ||
return copy; | ||
to2DArray() { | ||
const copy = new Array(this.rows); | ||
for (var i = 0; i < this.rows; i++) { | ||
copy[i] = new Array(this.columns); | ||
for (var j = 0; j < this.columns; j++) { | ||
copy[i][j] = this.get(i, j); | ||
} | ||
} | ||
return copy; | ||
} | ||
isSquare() { | ||
return this.rows === this.columns; | ||
} | ||
isSquare() { | ||
return this.rows === this.columns; | ||
} | ||
isSymmetric() { | ||
if (!this.isSquare()) return false; | ||
isSymmetric() { | ||
if (!this.isSquare()) return false; | ||
var symmetric = true; | ||
this.forEachNonZero((i, j, v) => { | ||
if (this.get(j, i) !== v) { | ||
symmetric = false; | ||
return false; | ||
} | ||
return v; | ||
}); | ||
return symmetric; | ||
} | ||
var symmetric = true; | ||
this.forEachNonZero((i, j, v) => { | ||
if (this.get(j, i) !== v) { | ||
symmetric = false; | ||
return false; | ||
} | ||
return v; | ||
}); | ||
return symmetric; | ||
} | ||
/** | ||
* Search for the wither band in the main diagonals | ||
* @return {number} | ||
*/ | ||
bandWidth() { | ||
let min = this.columns; | ||
let max = -1; | ||
this.forEachNonZero((i, j, v) => { | ||
let diff = i - j; | ||
min = Math.min(min, diff); | ||
max = Math.max(max, diff); | ||
return v; | ||
}); | ||
return max - min; | ||
} | ||
/** | ||
* Search for the wither band in the main diagonals | ||
* @return {number} | ||
*/ | ||
bandWidth() { | ||
let min = this.columns; | ||
let max = -1; | ||
this.forEachNonZero((i, j, v) => { | ||
let diff = i - j; | ||
min = Math.min(min, diff); | ||
max = Math.max(max, diff); | ||
return v; | ||
}); | ||
return max - min; | ||
} | ||
/** | ||
* Test if a matrix is consider banded using a threshold | ||
* @param {number} width | ||
* @return {boolean} | ||
*/ | ||
isBanded(width) { | ||
let bandWidth = this.bandWidth(); | ||
return bandWidth <= width; | ||
} | ||
/** | ||
* Test if a matrix is consider banded using a threshold | ||
* @param {number} width | ||
* @return {boolean} | ||
*/ | ||
isBanded(width) { | ||
let bandWidth = this.bandWidth(); | ||
return bandWidth <= width; | ||
} | ||
get cardinality() { | ||
return this.elements.size; | ||
} | ||
get cardinality() { | ||
return this.elements.size; | ||
} | ||
get size() { | ||
return this.rows * this.columns; | ||
} | ||
get size() { | ||
return this.rows * this.columns; | ||
} | ||
get(row, column) { | ||
return this.elements.get(row * this.columns + column); | ||
get(row, column) { | ||
return this.elements.get(row * this.columns + column); | ||
} | ||
set(row, column, value) { | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value === 0) { | ||
this.elements.remove(row * this.columns + column); | ||
} else { | ||
this.elements.set(row * this.columns + column, value); | ||
} | ||
return this; | ||
} | ||
set(row, column, value) { | ||
if (this.threshold && Math.abs(value) < this.threshold) value = 0; | ||
if (value === 0) { | ||
this.elements.remove(row * this.columns + column); | ||
} else { | ||
this.elements.set(row * this.columns + column, value); | ||
} | ||
return this; | ||
mmul(other) { | ||
if (this.columns !== other.rows) { | ||
// eslint-disable-next-line no-console | ||
console.warn( | ||
'Number of columns of left matrix are not equal to number of rows of right matrix.' | ||
); | ||
} | ||
mmul(other) { | ||
if (this.columns !== other.rows) { | ||
// eslint-disable-next-line no-console | ||
console.warn('Number of columns of left matrix are not equal to number of rows of right matrix.'); | ||
const m = this.rows; | ||
const p = other.columns; | ||
const result = new SparseMatrix(m, p); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
if (j === k) { | ||
result.set(i, l, result.get(i, l) + v1 * v2); | ||
} | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
const m = this.rows; | ||
const p = other.columns; | ||
kroneckerProduct(other) { | ||
const m = this.rows; | ||
const n = this.columns; | ||
const p = other.rows; | ||
const q = other.columns; | ||
const result = new SparseMatrix(m, p); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
if (j === k) { | ||
result.set(i, l, result.get(i, l) + v1 * v2); | ||
} | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
const result = new SparseMatrix(m * p, n * q, { | ||
initialCapacity: this.cardinality * other.cardinality | ||
}); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
result.set(p * i + k, q * j + l, v1 * v2); | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
kroneckerProduct(other) { | ||
const m = this.rows; | ||
const n = this.columns; | ||
const p = other.rows; | ||
const q = other.columns; | ||
forEachNonZero(callback) { | ||
this.elements.forEachPair((key, value) => { | ||
const i = (key / this.columns) | 0; | ||
const j = key % this.columns; | ||
let r = callback(i, j, value); | ||
if (r === false) return false; // stop iteration | ||
if (this.threshold && Math.abs(r) < this.threshold) r = 0; | ||
if (r !== value) { | ||
if (r === 0) { | ||
this.elements.remove(key, true); | ||
} else { | ||
this.elements.set(key, r); | ||
} | ||
} | ||
return true; | ||
}); | ||
this.elements.maybeShrinkCapacity(); | ||
return this; | ||
} | ||
const result = new SparseMatrix(m * p, n * q, { | ||
initialCapacity: this.cardinality * other.cardinality | ||
}); | ||
this.forEachNonZero((i, j, v1) => { | ||
other.forEachNonZero((k, l, v2) => { | ||
result.set(p * i + k, q * j + l, v1 * v2); | ||
return v2; | ||
}); | ||
return v1; | ||
}); | ||
return result; | ||
} | ||
getNonZeros() { | ||
const cardinality = this.cardinality; | ||
const rows = new Array(cardinality); | ||
const columns = new Array(cardinality); | ||
const values = new Array(cardinality); | ||
var idx = 0; | ||
this.forEachNonZero((i, j, value) => { | ||
rows[idx] = i; | ||
columns[idx] = j; | ||
values[idx] = value; | ||
idx++; | ||
return value; | ||
}); | ||
return { rows, columns, values }; | ||
} | ||
forEachNonZero(callback) { | ||
this.elements.forEachPair((key, value) => { | ||
const i = (key / this.columns) | 0; | ||
const j = key % this.columns; | ||
let r = callback(i, j, value); | ||
if (r === false) return false; // stop iteration | ||
if (this.threshold && Math.abs(r) < this.threshold) r = 0; | ||
if (r !== value) { | ||
if (r === 0) { | ||
this.elements.remove(key, true); | ||
} else { | ||
this.elements.set(key, r); | ||
} | ||
} | ||
return true; | ||
}); | ||
this.elements.maybeShrinkCapacity(); | ||
return this; | ||
setThreshold(newThreshold) { | ||
if (newThreshold !== 0 && newThreshold !== this.threshold) { | ||
this.threshold = newThreshold; | ||
this.forEachNonZero((i, j, v) => v); | ||
} | ||
return this; | ||
} | ||
getNonZeros() { | ||
const cardinality = this.cardinality; | ||
const rows = new Array(cardinality); | ||
const columns = new Array(cardinality); | ||
const values = new Array(cardinality); | ||
var idx = 0; | ||
this.forEachNonZero((i, j, value) => { | ||
rows[idx] = i; | ||
columns[idx] = j; | ||
values[idx] = value; | ||
idx++; | ||
return value; | ||
}); | ||
return {rows, columns, values}; | ||
} | ||
setThreshold(newThreshold) { | ||
if (newThreshold !== 0 && newThreshold !== this.threshold) { | ||
this.threshold = newThreshold; | ||
this.forEachNonZero((i, j, v) => v); | ||
} | ||
return this; | ||
} | ||
/** | ||
* @return {SparseMatrix} - New transposed sparse matrix | ||
*/ | ||
transpose() { | ||
let trans = new SparseMatrix(this.columns, this.rows, {initialCapacity: this.cardinality}); | ||
this.forEachNonZero((i, j, value) => { | ||
trans.set(j, i, value); | ||
return value; | ||
}); | ||
return trans; | ||
} | ||
/** | ||
* @return {SparseMatrix} - New transposed sparse matrix | ||
*/ | ||
transpose() { | ||
let trans = new SparseMatrix(this.columns, this.rows, { | ||
initialCapacity: this.cardinality | ||
}); | ||
this.forEachNonZero((i, j, value) => { | ||
trans.set(j, i, value); | ||
return value; | ||
}); | ||
return trans; | ||
} | ||
} | ||
@@ -281,51 +291,98 @@ | ||
const operators = [ | ||
// Arithmetic operators | ||
['+', 'add'], | ||
['-', 'sub', 'subtract'], | ||
['*', 'mul', 'multiply'], | ||
['/', 'div', 'divide'], | ||
['%', 'mod', 'modulus'], | ||
// Bitwise operators | ||
['&', 'and'], | ||
['|', 'or'], | ||
['^', 'xor'], | ||
['<<', 'leftShift'], | ||
['>>', 'signPropagatingRightShift'], | ||
['>>>', 'rightShift', 'zeroFillRightShift'] | ||
// Arithmetic operators | ||
['+', 'add'], | ||
['-', 'sub', 'subtract'], | ||
['*', 'mul', 'multiply'], | ||
['/', 'div', 'divide'], | ||
['%', 'mod', 'modulus'], | ||
// Bitwise operators | ||
['&', 'and'], | ||
['|', 'or'], | ||
['^', 'xor'], | ||
['<<', 'leftShift'], | ||
['>>', 'signPropagatingRightShift'], | ||
['>>>', 'rightShift', 'zeroFillRightShift'] | ||
]; | ||
for (const operator of operators) { | ||
for (let i = 1; i < operator.length; i++) { | ||
SparseMatrix.prototype[operator[i]] = eval(fillTemplateFunction(inplaceOperator, {name: operator[i], op: operator[0]})); | ||
SparseMatrix.prototype[operator[i] + 'S'] = eval(fillTemplateFunction(inplaceOperatorScalar, {name: operator[i] + 'S', op: operator[0]})); | ||
SparseMatrix.prototype[operator[i] + 'M'] = eval(fillTemplateFunction(inplaceOperatorMatrix, {name: operator[i] + 'M', op: operator[0]})); | ||
for (let i = 1; i < operator.length; i++) { | ||
SparseMatrix.prototype[operator[i]] = eval( | ||
fillTemplateFunction(inplaceOperator, { | ||
name: operator[i], | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix.prototype[`${operator[i]}S`] = eval( | ||
fillTemplateFunction(inplaceOperatorScalar, { | ||
name: `${operator[i]}S`, | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix.prototype[`${operator[i]}M`] = eval( | ||
fillTemplateFunction(inplaceOperatorMatrix, { | ||
name: `${operator[i]}M`, | ||
op: operator[0] | ||
}) | ||
); | ||
SparseMatrix[operator[i]] = eval(fillTemplateFunction(staticOperator, {name: operator[i]})); | ||
} | ||
SparseMatrix[operator[i]] = eval( | ||
fillTemplateFunction(staticOperator, { name: operator[i] }) | ||
); | ||
} | ||
} | ||
var methods = [ | ||
['~', 'not'] | ||
]; | ||
var methods = [['~', 'not']]; | ||
[ | ||
'abs', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cbrt', 'ceil', | ||
'clz32', 'cos', 'cosh', 'exp', 'expm1', 'floor', 'fround', 'log', 'log1p', | ||
'log10', 'log2', 'round', 'sign', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc' | ||
'abs', | ||
'acos', | ||
'acosh', | ||
'asin', | ||
'asinh', | ||
'atan', | ||
'atanh', | ||
'cbrt', | ||
'ceil', | ||
'clz32', | ||
'cos', | ||
'cosh', | ||
'exp', | ||
'expm1', | ||
'floor', | ||
'fround', | ||
'log', | ||
'log1p', | ||
'log10', | ||
'log2', | ||
'round', | ||
'sign', | ||
'sin', | ||
'sinh', | ||
'sqrt', | ||
'tan', | ||
'tanh', | ||
'trunc' | ||
].forEach(function (mathMethod) { | ||
methods.push(['Math.' + mathMethod, mathMethod]); | ||
methods.push([`Math.${mathMethod}`, mathMethod]); | ||
}); | ||
for (const method of methods) { | ||
for (let i = 1; i < method.length; i++) { | ||
SparseMatrix.prototype[method[i]] = eval(fillTemplateFunction(inplaceMethod, {name: method[i], method: method[0]})); | ||
SparseMatrix[method[i]] = eval(fillTemplateFunction(staticMethod, {name: method[i]})); | ||
} | ||
for (let i = 1; i < method.length; i++) { | ||
SparseMatrix.prototype[method[i]] = eval( | ||
fillTemplateFunction(inplaceMethod, { | ||
name: method[i], | ||
method: method[0] | ||
}) | ||
); | ||
SparseMatrix[method[i]] = eval( | ||
fillTemplateFunction(staticMethod, { name: method[i] }) | ||
); | ||
} | ||
} | ||
function fillTemplateFunction(template, values) { | ||
for (const i in values) { | ||
template = template.replace(new RegExp('%' + i + '%', 'g'), values[i]); | ||
} | ||
return template; | ||
for (const i in values) { | ||
template = template.replace(new RegExp(`%${i}%`, 'g'), values[i]); | ||
} | ||
return template; | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
7
698
12
22060
6
+ Addedml-hash-table@1.0.0(transitive)
+ Addednum-sort@2.1.0(transitive)
- Removedml-hash-table@0.2.1(transitive)
- Removednew-array@1.0.0(transitive)
- Removednum-sort@1.0.0(transitive)
- Removednumber-is-nan@1.0.1(transitive)
Updatedml-hash-table@^1.0.0