Advertisement
Guest User

Matrix.mjs

a guest
Jun 19th, 2019
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. const range = (from, to) =>
  2.   Array.from(Array(to - from), (...[, i]) => i + from);
  3.  
  4. const sum = (array) => array.reduce((a, b) => a + b, 0);
  5.  
  6. export default class Matrix {
  7.   constructor(entry, height, width) {
  8.     const A = this;
  9.     const isArray = Array.isArray(entry);
  10.  
  11.     if (isArray) {
  12.       A.entry = (i, j) => entry[i][j];
  13.       A.rows = entry;
  14.       A.columns = { length: entry[0].length };
  15.     } else {
  16.       A.entry = entry;
  17.       A.rows = { length: height };
  18.       A.columns = { length: width };
  19.     }
  20.  
  21.     const ToUint32 = (x) => String(x) >>> 0;
  22.  
  23.     const isArrayIndex = (p) =>
  24.       String(ToUint32(p)) === p && ToUint32(p) !== 0xffffffff;
  25.  
  26.     return new Proxy(A, {
  27.       get: (...[, i]) => {
  28.         if (!isArrayIndex(i)) return A[i];
  29.  
  30.         if (isArray) return A.rows[i];
  31.  
  32.         const row = {
  33.           get: (...[, j]) => {
  34.             if (!isArrayIndex(j)) return row[j];
  35.  
  36.             return A.entry(+i, +j);
  37.           },
  38.         };
  39.  
  40.         return new Proxy(row, row);
  41.       },
  42.     });
  43.   }
  44.  
  45.   add(B) {
  46.     const A = this;
  47.  
  48.     if (
  49.       !(
  50.         A.rows.length === B.rows.length && A.columns.length === B.columns.length
  51.       )
  52.     ) {
  53.       return;
  54.     }
  55.  
  56.     return new Matrix(
  57.       (i, j) => A[i][j] + B[i][j],
  58.       A.rows.length,
  59.       A.columns.length,
  60.     );
  61.   }
  62.  
  63.   sub(B) {
  64.     const A = this;
  65.     return A.add(B.mul(-1));
  66.   }
  67.  
  68.   mul(B) {
  69.     const A = this;
  70.  
  71.     if (typeof B === 'number') {
  72.       return new Matrix((i, j) => A[i][j] * B, A.rows.length, A.columns.length);
  73.     }
  74.  
  75.     if (!(A.columns.length === B.rows.length)) return;
  76.  
  77.     return new Matrix(
  78.       (i, j) => sum(range(0, A.columns.length).map((k) => A[i][k] * B[k][j])),
  79.       A.rows.length,
  80.       B.columns.length,
  81.     );
  82.   }
  83.  
  84.   div(B) {
  85.     const A = this;
  86.  
  87.     if (typeof B === 'number') {
  88.       return A.mul(1 / B);
  89.     }
  90.  
  91.     return A.mul(B.inverse());
  92.   }
  93.  
  94.   pow(n) {
  95.     const A = this;
  96.     if (n === 0) return Matrix.I(A.rows.length);
  97.     return A.mul(A.pow(n - 1));
  98.   }
  99.  
  100.   trace() {
  101.     const A = this;
  102.     return sum(range(0, A.rows.length).map((i) => A[i][i]));
  103.   }
  104.  
  105.   transpose() {
  106.     const A = this;
  107.     return new Matrix((i, j) => A[j][i], A.columns.length, A.rows.length);
  108.   }
  109.  
  110.   inverse() {
  111.     const A = this;
  112.     return A.adjugate().div(A.determinant());
  113.   }
  114.  
  115.   adjugate() {
  116.     const A = this;
  117.     return A.cofactor().transpose();
  118.   }
  119.  
  120.   determinant() {
  121.     const A = this;
  122.  
  123.     if (A.rows.length === 0) return 1;
  124.  
  125.     return sum(
  126.       range(0, A.columns.length).map((j) => A[0][j] * A.cofactor(0, j)),
  127.     );
  128.   }
  129.  
  130.   cofactor(i, j) {
  131.     const A = this;
  132.  
  133.     if (!arguments.length) {
  134.       return new Matrix(
  135.         (i, j) => A.cofactor(i, j),
  136.         A.rows.length,
  137.         A.columns.length,
  138.       );
  139.     }
  140.  
  141.     return (-1)**(i + j) * A.minor(i, j);
  142.   }
  143.  
  144.   minor(i, j) {
  145.     const A = this;
  146.     return A.submatrix(i, j).determinant();
  147.   }
  148.  
  149.   submatrix(row, column) {
  150.     const A = this;
  151.  
  152.     return new Matrix(
  153.       (i, j) => A[i < row ? i : i + 1][j < column ? j : j + 1],
  154.       A.rows.length - 1,
  155.       A.columns.length - 1,
  156.     );
  157.   }
  158.  
  159.   eigenvalues() {
  160.     const A = this;
  161.     const trA = A.trace();
  162.  
  163.     switch (A.rows.length) {
  164.       case 2: {
  165.         const detA = A.determinant();
  166.         const gap = Math.sqrt(trA * trA - 4 * detA);
  167.         return [(trA + gap) / 2, (trA - gap) / 2];
  168.       }
  169.       case 3: {
  170.         const q = trA / 3;
  171.         const A_qI = A.sub(Matrix.I(3).mul(q));
  172.         const p = Math.sqrt(A_qI.pow(2).trace() / 6);
  173.  
  174.         const B = A_qI.div(p);
  175.         const detB = B.determinant();
  176.  
  177.         return range(0, 3)
  178.           .map(
  179.             (k) =>
  180.               2 *
  181.               Math.cos((1 / 3) * Math.acos(detB / 2) + (2 * k * Math.PI) / 3),
  182.           )
  183.           .map((beta) => p * beta + q);
  184.       }
  185.     }
  186.   }
  187.  
  188.   toArray() {
  189.     const A = this;
  190.  
  191.     if (0 in A.rows) return A.rows;
  192.  
  193.     return range(0, A.rows.length).map((i) =>
  194.       range(0, A.columns.length).map((j) => A[i][j]),
  195.     );
  196.   }
  197.  
  198.   toString() {
  199.     const A = this;
  200.     return JSON.stringify(A.toArray());
  201.   }
  202. }
  203.  
  204. Matrix.O = (n) => new Matrix(() => 0, n, n);
  205.  
  206. Matrix.I = (n) => new Matrix((i, j) => +(i === j), n, n);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement