/**
* @license
* Copyright 2020 Roberto Luiz Souza Monteiro,
* Renata Souza Barreto,
* Hernane Borges de Barros Pereira.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* MaiaScript matrix library.
* @class
*/
function Matrix() {
init();
/**
* Creates the attributes of the class.
*/
function init() {
// Class attributes goes here.
}
/**
* Returns the mean and standard deviation of the values contained in a matrix.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} Mean and standard deviation of the values contained in a matrix.
*/
this.avg = function(mtx, r1, c1, r2, c2) {
var res = {
'avg': 0,
'dev': 0
};
var sx;
var sx2;
var n;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
sx = 0;
sx2 = 0;
n = 0;
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
sx += mtx[i][j];
sx2 += mtx[i][j] * mtx[i][j];
n++;
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function avg. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
sx = 0;
sx2 = 0;
n = 0;
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
sx += mtx[j];
sx2 += mtx[j] * mtx[j];
n++;
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function avg. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function avg. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function avg. Argument must be a matrix.');
}
res.avg = sx / n;
res.dev = Math.sqrt((sx2 - (sx * sx) / n) / (n - 1));
return res;
}
/**
* Returns the number of non-zero elements in the matrix.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} The number of non-zero elements in the matrix.
*/
this.count = function(mtx, r1, c1, r2, c2) {
var res;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
res = 0;
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
if (mtx[i][j] != 0) {
res++;
}
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function count. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
res = 0;
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
if (mtx[j] != 0) {
res++;
}
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function count. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function count. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function count. Argument must be a matrix.');
}
return res;
}
/**
* Calculates the cross product of two vectors A and B.
* @param {object} a - The matrix A.
* @param {object} b - The matrix B.
* @return {array} A (rows x columns) matrix.
*/
this.cross = function(a, b) {
var mtx;
if ((core.type(a) == 'matrix') && (core.type(b) == 'matrix')) {
var dimA = core.dim(a);
var dimB = core.dim(b);
if ((dimA[0] == dimB[0]) && (dimA[1] == dimB[1])) {
var m = dimA[0];
var mtx = core.matrix(0, 1, m);
if (m == 2) {
mtx[0] = a[0] * b[1];
mtx[1] = a[1] * b[0];
} else if (m == 3) {
mtx[0] = a[1] * b[2] - b[1] * a[2];
mtx[1] = a[2] * b[0] - b[2] * a[0];
mtx[2] = a[0] * b[1] - b[0] * a[1];
}
} else {
throw new Error('The matrices must have equal dimensions for function cross(), in the expression cross(' + core.toString(a) + "," + core.toString(b) + ').');
}
} else {
throw new Error('The arguments for function cross() must be matrices, in the expression cross(' + core.toString(a) + "," + core.toString(b) + ').');
}
return mtx;
}
/**
* Calculates the dot product of two vectors A and B.
* @param {object} a - The matrix A.
* @param {object} b - The matrix B.
* @return {array} A (rows x columns) matrix.
*/
this.dot = function(a, b) {
var res;
if ((core.type(a) == 'matrix') && (core.type(b) == 'matrix')) {
var dimA = core.dim(a);
var dimB = core.dim(b);
if ((dimA[0] == dimB[0]) && (dimA[1] == dimB[1])) {
var m = dimA[0];
if (m == 2) {
res = a[0] * b[0] + a[1] * b[1];
} else if (m == 3) {
res = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
}
} else {
throw new Error('The matrices must have equal dimensions for function cross(), in the expression cross(' + core.toString(a) + "," + core.toString(b) + ').');
}
} else {
throw new Error('The arguments for function dot() must be matrices, in the expression dot(' + core.toString(a) + "," + core.toString(b) + ').');
}
return res;
}
/**
* Returns the largest value in an array.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} The smallest value in an array.
*/
this.max = function(mtx, r1, c1, r2, c2) {
var res;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
res = 0;
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
if (typeof res == 'undefined') {
res = mtx[i][j];
} else {
if (mtx[i][j] > res) {
res = mtx[i][j];
}
}
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function max. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
res = 0;
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
if (typeof res == 'undefined') {
res = mtx[j];
} else {
if (mtx[j] > res) {
res = mtx[j];
}
}
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function max. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function max. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function max. Argument must be a matrix.');
}
return res;
}
/**
* Returns the smallest value in an array.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} The smallest value in an array.
*/
this.min = function(mtx, r1, c1, r2, c2) {
var res;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
if (typeof res == 'undefined') {
res = mtx[i][j];
} else {
if (mtx[i][j] < res) {
res = mtx[i][j];
}
}
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function min. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
res = 0;
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
if (typeof res == 'undefined') {
res = mtx[j];
} else {
if (mtx[j] < res) {
res = mtx[j];
}
}
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function min. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function min. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function min. Argument must be a matrix.');
}
return res;
}
/**
* Calculates the sum of all cells in the matrix.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} Sum of the values contained in a matrix.
*/
this.sum = function(mtx, r1, c1, r2, c2) {
var res;
var sx;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
sx = 0;
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
sx += mtx[i][j];
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function sum. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
sx = 0;
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
sx += mtx[j];
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function sum. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function sum. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function sum. Argument must be a matrix.');
}
res = sx;
return res;
}
/**
* Calculates the squared sum of all cells in the matrix.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} Sum of the values contained in a matrix.
*/
this.sum2 = function(mtx, r1, c1, r2, c2) {
var res;
var sx;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
sx = 0;
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
sx += mtx[i][j] * mtx[i][j];
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function sum. All elements must be numeric.');
}
}
}
} else {
if (dimMatrix.length == 1) {
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[0] - 1;
}
sx = 0;
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[j]) == 'number') {
sx += mtx[j] * mtx[j];
} else {
throw new Error('Invalid element ' + mtx[j] + ' in matrix for function sum. All elements must be numeric.');
}
}
} else {
throw new Error('Invalid argument for function sum. The matrix must be one or two-dimensional.');
}
}
} else {
throw new Error('Invalid argument for function sum. Argument must be a matrix.');
}
res = sx;
return res;
}
/**
* Returns the transpose of an array.
* @param {object} mtx - The matrix.
* @param {number} r1 - First row.
* @param {number} c1 - First column.
* @param {number} r2 - Last row.
* @param {number} c2 - Last column.
* @return {number} The transpose of an array.
*/
this.trans = function(mtx, r1, c1, r2, c2) {
var res;
if (core.type(mtx) == 'matrix') {
dimMatrix = core.dim(mtx);
if (dimMatrix.length == 2) {
res = 0;
if (typeof r1 == 'undefined') {
r1 = 0;
}
if (typeof c1 == 'undefined') {
c1 = 0;
}
if (typeof r2 == 'undefined') {
r2 = dimMatrix[0] - 1;
}
if (typeof c2 == 'undefined') {
c2 = dimMatrix[1] - 1;
}
res = core.matrix(0, dimMatrix[0], dimMatrix[1]);
for (var i = r1; i <= r2; i++) {
for (var j = c1; j <= c2; j++) {
if (core.type(mtx[i][j]) == 'number') {
res[j][i] = mtx[i][j];
} else {
throw new Error('Invalid element ' + mtx[i][j] + ' in matrix for function trans. All elements must be numeric.');
}
}
}
} else {
throw new Error('Invalid argument for function trans. The matrix must be two-dimensional.');
}
} else {
throw new Error('Invalid argument for function trans. Argument must be a matrix.');
}
return res;
}
/**
* Calculates the triangular equivalent matrix.
* @param {object} mtx - The matrix to calculate the triangular equivalent matrix.
* @return {array} A (rows x columns) matrix.
*/
this.triang = function(mtx) {
if (core.type(mtx) == 'matrix') {
var dim = core.dim(mtx);
var m = dim[0];
var n = dim[1];
// Convert to the triangular equivalent matrix.
var cpy = core.copyMatrix(mtx);
for (k = 0; k < m - 1; k++) {
for (i = k + 1; i < m; i++) {
var scale = -cpy[i][k] / cpy[k][k]
for (j = 0; j < n; j++) {
cpy[i][j] = cpy[i][j] + scale * cpy[k][j];
}
}
}
// Calculates the determinant of the matrix.
var det = 1;
for (i = 0; i < m; i++) {
det = det * cpy[i][i];
}
if (det == 0) {
throw new Error('The matrix is singular, in the expression triang(' + core.toString(mtx) + ').');
}
} else {
throw new Error('The argument for function triang() must be a matrix, in the expression triang(' + core.toString(mtx) + ').');
}
return cpy;
}
}
matrix = new Matrix();