138 lines
3.2 KiB
JavaScript
138 lines
3.2 KiB
JavaScript
import { clone } from '../../utils/object.js';
|
|
import { format } from '../../utils/string.js';
|
|
import { factory } from '../../utils/factory.js';
|
|
var name = 'trace';
|
|
var dependencies = ['typed', 'matrix', 'add'];
|
|
export var createTrace = /* #__PURE__ */factory(name, dependencies, _ref => {
|
|
var {
|
|
typed,
|
|
matrix,
|
|
add
|
|
} = _ref;
|
|
|
|
/**
|
|
* Calculate the trace of a matrix: the sum of the elements on the main
|
|
* diagonal of a square matrix.
|
|
*
|
|
* Syntax:
|
|
*
|
|
* math.trace(x)
|
|
*
|
|
* Examples:
|
|
*
|
|
* math.trace([[1, 2], [3, 4]]) // returns 5
|
|
*
|
|
* const A = [
|
|
* [1, 2, 3],
|
|
* [-1, 2, 3],
|
|
* [2, 0, 3]
|
|
* ]
|
|
* math.trace(A) // returns 6
|
|
*
|
|
* See also:
|
|
*
|
|
* diag
|
|
*
|
|
* @param {Array | Matrix} x A matrix
|
|
*
|
|
* @return {number} The trace of `x`
|
|
*/
|
|
return typed('trace', {
|
|
Array: function _arrayTrace(x) {
|
|
// use dense matrix implementation
|
|
return _denseTrace(matrix(x));
|
|
},
|
|
SparseMatrix: _sparseTrace,
|
|
DenseMatrix: _denseTrace,
|
|
any: clone
|
|
});
|
|
|
|
function _denseTrace(m) {
|
|
// matrix size & data
|
|
var size = m._size;
|
|
var data = m._data; // process dimensions
|
|
|
|
switch (size.length) {
|
|
case 1:
|
|
// vector
|
|
if (size[0] === 1) {
|
|
// return data[0]
|
|
return clone(data[0]);
|
|
}
|
|
|
|
throw new RangeError('Matrix must be square (size: ' + format(size) + ')');
|
|
|
|
case 2:
|
|
{
|
|
// two dimensional
|
|
var rows = size[0];
|
|
var cols = size[1];
|
|
|
|
if (rows === cols) {
|
|
// calulate sum
|
|
var sum = 0; // loop diagonal
|
|
|
|
for (var i = 0; i < rows; i++) {
|
|
sum = add(sum, data[i][i]);
|
|
} // return trace
|
|
|
|
|
|
return sum;
|
|
} else {
|
|
throw new RangeError('Matrix must be square (size: ' + format(size) + ')');
|
|
}
|
|
}
|
|
|
|
default:
|
|
// multi dimensional
|
|
throw new RangeError('Matrix must be two dimensional (size: ' + format(size) + ')');
|
|
}
|
|
}
|
|
|
|
function _sparseTrace(m) {
|
|
// matrix arrays
|
|
var values = m._values;
|
|
var index = m._index;
|
|
var ptr = m._ptr;
|
|
var size = m._size; // check dimensions
|
|
|
|
var rows = size[0];
|
|
var columns = size[1]; // matrix must be square
|
|
|
|
if (rows === columns) {
|
|
// calulate sum
|
|
var sum = 0; // check we have data (avoid looping columns)
|
|
|
|
if (values.length > 0) {
|
|
// loop columns
|
|
for (var j = 0; j < columns; j++) {
|
|
// k0 <= k < k1 where k0 = _ptr[j] && k1 = _ptr[j+1]
|
|
var k0 = ptr[j];
|
|
var k1 = ptr[j + 1]; // loop k within [k0, k1[
|
|
|
|
for (var k = k0; k < k1; k++) {
|
|
// row index
|
|
var i = index[k]; // check row
|
|
|
|
if (i === j) {
|
|
// accumulate value
|
|
sum = add(sum, values[k]); // exit loop
|
|
|
|
break;
|
|
}
|
|
|
|
if (i > j) {
|
|
// exit loop, no value on the diagonal for column j
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} // return trace
|
|
|
|
|
|
return sum;
|
|
}
|
|
|
|
throw new RangeError('Matrix must be square (size: ' + format(size) + ')');
|
|
}
|
|
}); |