@rayyamhk/matrix
Version:
A professional, comprehensive and high-performance library for you to manipulate matrices.
113 lines (86 loc) • 2.53 kB
JavaScript
var Matrix = require('../..');
var isNumber = require('../../util/isNumber');
var _require = require('../../Error'),
INVALID_ARRAY = _require.INVALID_ARRAY,
EXPECTED_ARRAY_OF_NUMBERS_OR_MATRICES = _require.EXPECTED_ARRAY_OF_NUMBERS_OR_MATRICES,
INVALID_SQUARE_MATRIX = _require.INVALID_SQUARE_MATRIX;
/**
* Generates diagonal Matrix if the argument is an array of numbers,
* generates block diagonal Matrix if the argument is an array of Matrices.
* @memberof Matrix
* @static
* @param {(number[]|Matrix[])} values - Array of numbers or Matrices
* @returns {Matrix} Block diagonal Matrix
*/
function diag(values) {
if (!Array.isArray(values)) {
throw new Error(INVALID_ARRAY);
}
var argsNum = values.length;
var variant;
for (var i = 0; i < argsNum; i++) {
var entry = values[i];
if (!isNumber(entry) && !(entry instanceof Matrix)) {
throw new Error(EXPECTED_ARRAY_OF_NUMBERS_OR_MATRICES);
}
if (isNumber(entry)) {
if (!variant) {
variant = 'number';
continue;
}
if (variant !== 'number') {
throw new Error(EXPECTED_ARRAY_OF_NUMBERS_OR_MATRICES);
}
} else {
if (!entry.isSquare()) {
throw new Error(INVALID_SQUARE_MATRIX);
}
if (!variant) {
variant = 'square';
continue;
}
if (variant !== 'square') {
throw new Error(EXPECTED_ARRAY_OF_NUMBERS_OR_MATRICES);
}
}
} // HERE: variant should be either 'number' or 'square'
if (variant === 'number') {
return Matrix.generate(argsNum, argsNum, function (i, j) {
if (i === j) {
return values[i];
}
return 0;
});
} // Guaranteed that [values] is a list of square matrices
var size = 0;
var temp = new Array(argsNum);
for (var _i = 0; _i < argsNum; _i++) {
var _len = values[_i].size()[0];
size += _len;
temp[_i] = _len;
}
var idx = 0;
var start = 0;
var len = temp[idx];
return Matrix.generate(size, size, function (i, j) {
if (i - start === len && j - start === len) {
start += len;
idx++;
}
var ith = i - start; // ith < 0 if below main diagonal
var jth = j - start; // jth < 0 if above main diagonal
// skip 0x0 matrices
len = temp[idx];
while (len === 0) {
idx++;
len = temp[idx];
}
if (ith < len && ith >= 0 && jth < len && jth >= 0) {
return values[idx]._matrix[ith][jth];
}
return 0;
});
}
;
module.exports = diag;
;