All files / engine/Source/Core TridiagonalSystemSolver.js

100% Statements 36/36
100% Branches 22/22
100% Functions 1/1
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                    1x                                                               1x   21x 1x   20x 1x   19x 1x   18x 1x   17x 1x   16x 1x 15x 1x           14x 14x 14x     14x 54x 54x     14x 14x     14x 26x 26x 26x         26x     14x 14x         14x   14x 14x 40x             14x      
import Cartesian3 from "./Cartesian3.js";
import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
 
/**
 * Uses the Tridiagonal Matrix Algorithm, also known as the Thomas Algorithm, to solve
 * a system of linear equations where the coefficient matrix is a tridiagonal matrix.
 *
 * @namespace TridiagonalSystemSolver
 */
const TridiagonalSystemSolver = {};
 
/**
 * Solves a tridiagonal system of linear equations.
 *
 * @param {number[]} diagonal An array with length <code>n</code> that contains the diagonal of the coefficient matrix.
 * @param {number[]} lower An array with length <code>n - 1</code> that contains the lower diagonal of the coefficient matrix.
 * @param {number[]} upper An array with length <code>n - 1</code> that contains the upper diagonal of the coefficient matrix.
 * @param {Cartesian3[]} right An array of Cartesians with length <code>n</code> that is the right side of the system of equations.
 *
 * @exception {DeveloperError} diagonal and right must have the same lengths.
 * @exception {DeveloperError} lower and upper must have the same lengths.
 * @exception {DeveloperError} lower and upper must be one less than the length of diagonal.
 *
 * @performance Linear time.
 *
 * @example
 * const lowerDiagonal = [1.0, 1.0, 1.0, 1.0];
 * const diagonal = [2.0, 4.0, 4.0, 4.0, 2.0];
 * const upperDiagonal = [1.0, 1.0, 1.0, 1.0];
 * const rightHandSide = [
 *     new Cesium.Cartesian3(410757.0, -1595711.0, 1375302.0),
 *     new Cesium.Cartesian3(-5986705.0, -2190640.0, 1099600.0),
 *     new Cesium.Cartesian3(-12593180.0, 288588.0, -1755549.0),
 *     new Cesium.Cartesian3(-5349898.0, 2457005.0, -2685438.0),
 *     new Cesium.Cartesian3(845820.0, 1573488.0, -1205591.0)
 * ];
 *
 * const solution = Cesium.TridiagonalSystemSolver.solve(lowerDiagonal, diagonal, upperDiagonal, rightHandSide);
 *
 * @returns {Cartesian3[]} An array of Cartesians with length <code>n</code> that is the solution to the tridiagonal system of equations.
 */
TridiagonalSystemSolver.solve = function (lower, diagonal, upper, right) {
  //>>includeStart('debug', pragmas.debug);
  if (!defined(lower) || !(lower instanceof Array)) {
    throw new DeveloperError("The array lower is required.");
  }
  if (!defined(diagonal) || !(diagonal instanceof Array)) {
    throw new DeveloperError("The array diagonal is required.");
  }
  if (!defined(upper) || !(upper instanceof Array)) {
    throw new DeveloperError("The array upper is required.");
  }
  if (!defined(right) || !(right instanceof Array)) {
    throw new DeveloperError("The array right is required.");
  }
  if (diagonal.length !== right.length) {
    throw new DeveloperError("diagonal and right must have the same lengths.");
  }
  if (lower.length !== upper.length) {
    throw new DeveloperError("lower and upper must have the same lengths.");
  } else if (lower.length !== diagonal.length - 1) {
    throw new DeveloperError(
      "lower and upper must be one less than the length of diagonal.",
    );
  }
  //>>includeEnd('debug');
 
  const c = new Array(upper.length);
  const d = new Array(right.length);
  const x = new Array(right.length);
 
  let i;
  for (i = 0; i < d.length; i++) {
    d[i] = new Cartesian3();
    x[i] = new Cartesian3();
  }
 
  c[0] = upper[0] / diagonal[0];
  d[0] = Cartesian3.multiplyByScalar(right[0], 1.0 / diagonal[0], d[0]);
 
  let scalar;
  for (i = 1; i < c.length; ++i) {
    scalar = 1.0 / (diagonal[i] - c[i - 1] * lower[i - 1]);
    c[i] = upper[i] * scalar;
    d[i] = Cartesian3.subtract(
      right[i],
      Cartesian3.multiplyByScalar(d[i - 1], lower[i - 1], d[i]),
      d[i],
    );
    d[i] = Cartesian3.multiplyByScalar(d[i], scalar, d[i]);
  }
 
  scalar = 1.0 / (diagonal[i] - c[i - 1] * lower[i - 1]);
  d[i] = Cartesian3.subtract(
    right[i],
    Cartesian3.multiplyByScalar(d[i - 1], lower[i - 1], d[i]),
    d[i],
  );
  d[i] = Cartesian3.multiplyByScalar(d[i], scalar, d[i]);
 
  x[x.length - 1] = d[d.length - 1];
  for (i = x.length - 2; i >= 0; --i) {
    x[i] = Cartesian3.subtract(
      d[i],
      Cartesian3.multiplyByScalar(x[i + 1], c[i], x[i]),
      x[i],
    );
  }
 
  return x;
};
export default TridiagonalSystemSolver;