mathjs 7.2.0 → 7.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. package/HISTORY.md +34 -0
  2. package/dist/math.js +3421 -2476
  3. package/dist/math.min.js +5 -5
  4. package/dist/math.min.map +1 -1
  5. package/docs/expressions/syntax.md +30 -4
  6. package/docs/reference/functions/bin.md +38 -0
  7. package/docs/reference/functions/ceil.md +10 -1
  8. package/docs/reference/functions/fix.md +10 -2
  9. package/docs/reference/functions/floor.md +12 -3
  10. package/docs/reference/functions/hex.md +38 -0
  11. package/docs/reference/functions/lsolve.md +2 -1
  12. package/docs/reference/functions/lsolveAll.md +45 -0
  13. package/docs/reference/functions/oct.md +38 -0
  14. package/docs/reference/functions/rotationMatrix.md +51 -0
  15. package/docs/reference/functions/round.md +6 -2
  16. package/docs/reference/functions/usolve.md +2 -1
  17. package/docs/reference/functions/usolveAll.md +45 -0
  18. package/docs/reference/functions.md +8 -2
  19. package/es/entry/dependenciesAny/dependenciesBin.generated.js +10 -0
  20. package/es/entry/dependenciesAny/dependenciesCeil.generated.js +4 -0
  21. package/es/entry/dependenciesAny/dependenciesFix.generated.js +2 -0
  22. package/es/entry/dependenciesAny/dependenciesFloor.generated.js +4 -0
  23. package/es/entry/dependenciesAny/dependenciesHex.generated.js +10 -0
  24. package/es/entry/dependenciesAny/dependenciesLsolveAll.generated.js +22 -0
  25. package/es/entry/dependenciesAny/dependenciesOct.generated.js +10 -0
  26. package/es/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +30 -0
  27. package/es/entry/dependenciesAny/dependenciesUsolveAll.generated.js +22 -0
  28. package/es/entry/dependenciesAny.generated.js +6 -0
  29. package/es/entry/impureFunctionsAny.generated.js +63 -57
  30. package/es/entry/pureFunctionsAny.generated.js +323 -277
  31. package/es/expression/embeddedDocs/embeddedDocs.js +12 -0
  32. package/es/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
  33. package/es/expression/embeddedDocs/function/algebra/lsolveAll.js +8 -0
  34. package/es/expression/embeddedDocs/function/algebra/usolve.js +2 -2
  35. package/es/expression/embeddedDocs/function/algebra/usolveAll.js +8 -0
  36. package/es/expression/embeddedDocs/function/matrix/rotationMatrix.js +8 -0
  37. package/es/expression/embeddedDocs/function/utils/bin.js +8 -0
  38. package/es/expression/embeddedDocs/function/utils/hex.js +8 -0
  39. package/es/expression/embeddedDocs/function/utils/oct.js +8 -0
  40. package/es/expression/parse.js +28 -1
  41. package/es/factoriesAny.js +6 -0
  42. package/es/function/algebra/solver/lsolve.js +42 -69
  43. package/es/function/algebra/solver/lsolveAll.js +213 -0
  44. package/es/function/algebra/solver/lusolve.js +12 -27
  45. package/es/function/algebra/solver/usolve.js +41 -64
  46. package/es/function/algebra/solver/usolveAll.js +213 -0
  47. package/es/function/algebra/solver/utils/solveValidation.js +66 -107
  48. package/es/function/arithmetic/ceil.js +88 -4
  49. package/es/function/arithmetic/fix.js +43 -6
  50. package/es/function/arithmetic/floor.js +90 -6
  51. package/es/function/arithmetic/mod.js +10 -1
  52. package/es/function/arithmetic/round.js +6 -2
  53. package/es/function/matrix/rotationMatrix.js +175 -0
  54. package/es/function/matrix/sqrtm.js +4 -0
  55. package/es/function/probability/pickRandom.js +2 -6
  56. package/es/function/statistics/variance.js +4 -4
  57. package/es/function/string/baseUtils.js +36 -0
  58. package/es/function/string/bin.js +23 -0
  59. package/es/function/string/hex.js +23 -0
  60. package/es/function/string/oct.js +23 -0
  61. package/es/type/bignumber/BigNumber.js +4 -1
  62. package/es/type/number.js +10 -0
  63. package/es/utils/object.js +3 -1
  64. package/es/version.js +1 -1
  65. package/examples/advanced/web_server/math_worker.js +1 -1
  66. package/lib/entry/dependenciesAny/dependenciesBin.generated.js +20 -0
  67. package/lib/entry/dependenciesAny/dependenciesCeil.generated.js +6 -0
  68. package/lib/entry/dependenciesAny/dependenciesFix.generated.js +3 -0
  69. package/lib/entry/dependenciesAny/dependenciesFloor.generated.js +6 -0
  70. package/lib/entry/dependenciesAny/dependenciesHex.generated.js +20 -0
  71. package/lib/entry/dependenciesAny/dependenciesLsolveAll.generated.js +38 -0
  72. package/lib/entry/dependenciesAny/dependenciesOct.generated.js +20 -0
  73. package/lib/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +50 -0
  74. package/lib/entry/dependenciesAny/dependenciesUsolveAll.generated.js +38 -0
  75. package/lib/entry/dependenciesAny.generated.js +48 -0
  76. package/lib/entry/impureFunctionsAny.generated.js +65 -59
  77. package/lib/entry/pureFunctionsAny.generated.js +373 -321
  78. package/lib/expression/embeddedDocs/embeddedDocs.js +18 -0
  79. package/lib/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
  80. package/lib/expression/embeddedDocs/function/algebra/lsolveAll.js +15 -0
  81. package/lib/expression/embeddedDocs/function/algebra/usolve.js +2 -2
  82. package/lib/expression/embeddedDocs/function/algebra/usolveAll.js +15 -0
  83. package/lib/expression/embeddedDocs/function/matrix/rotationMatrix.js +15 -0
  84. package/lib/expression/embeddedDocs/function/utils/bin.js +15 -0
  85. package/lib/expression/embeddedDocs/function/utils/hex.js +15 -0
  86. package/lib/expression/embeddedDocs/function/utils/oct.js +15 -0
  87. package/lib/expression/parse.js +28 -1
  88. package/lib/factoriesAny.js +48 -0
  89. package/lib/function/algebra/solver/lsolve.js +42 -69
  90. package/lib/function/algebra/solver/lsolveAll.js +223 -0
  91. package/lib/function/algebra/solver/lusolve.js +12 -27
  92. package/lib/function/algebra/solver/usolve.js +41 -64
  93. package/lib/function/algebra/solver/usolveAll.js +223 -0
  94. package/lib/function/algebra/solver/utils/solveValidation.js +65 -106
  95. package/lib/function/arithmetic/ceil.js +91 -4
  96. package/lib/function/arithmetic/fix.js +44 -6
  97. package/lib/function/arithmetic/floor.js +93 -6
  98. package/lib/function/arithmetic/mod.js +10 -1
  99. package/lib/function/arithmetic/round.js +6 -2
  100. package/lib/function/matrix/rotationMatrix.js +185 -0
  101. package/lib/function/matrix/sqrtm.js +4 -0
  102. package/lib/function/probability/pickRandom.js +3 -7
  103. package/lib/function/statistics/variance.js +4 -4
  104. package/lib/function/string/baseUtils.js +45 -0
  105. package/lib/function/string/bin.js +31 -0
  106. package/lib/function/string/hex.js +31 -0
  107. package/lib/function/string/oct.js +31 -0
  108. package/lib/header.js +2 -2
  109. package/lib/type/bignumber/BigNumber.js +3 -1
  110. package/lib/type/number.js +10 -0
  111. package/lib/utils/object.js +3 -1
  112. package/lib/version.js +1 -1
  113. package/package.json +12 -12
  114. package/src/entry/dependenciesAny/dependenciesBin.generated.js +11 -0
  115. package/src/entry/dependenciesAny/dependenciesCeil.generated.js +4 -0
  116. package/src/entry/dependenciesAny/dependenciesFix.generated.js +2 -0
  117. package/src/entry/dependenciesAny/dependenciesFloor.generated.js +4 -0
  118. package/src/entry/dependenciesAny/dependenciesHex.generated.js +11 -0
  119. package/src/entry/dependenciesAny/dependenciesLsolveAll.generated.js +23 -0
  120. package/src/entry/dependenciesAny/dependenciesOct.generated.js +11 -0
  121. package/src/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +31 -0
  122. package/src/entry/dependenciesAny/dependenciesUsolveAll.generated.js +23 -0
  123. package/src/entry/dependenciesAny.generated.js +6 -0
  124. package/src/entry/impureFunctionsAny.generated.js +104 -92
  125. package/src/entry/pureFunctionsAny.generated.js +94 -82
  126. package/src/expression/embeddedDocs/embeddedDocs.js +12 -0
  127. package/src/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
  128. package/src/expression/embeddedDocs/function/algebra/lsolveAll.js +17 -0
  129. package/src/expression/embeddedDocs/function/algebra/usolve.js +2 -2
  130. package/src/expression/embeddedDocs/function/algebra/usolveAll.js +15 -0
  131. package/src/expression/embeddedDocs/function/matrix/rotationMatrix.js +19 -0
  132. package/src/expression/embeddedDocs/function/utils/bin.js +12 -0
  133. package/src/expression/embeddedDocs/function/utils/hex.js +12 -0
  134. package/src/expression/embeddedDocs/function/utils/oct.js +12 -0
  135. package/src/expression/parse.js +25 -0
  136. package/src/factoriesAny.js +6 -0
  137. package/src/function/algebra/solver/lsolve.js +52 -58
  138. package/src/function/algebra/solver/lsolveAll.js +197 -0
  139. package/src/function/algebra/solver/lusolve.js +9 -19
  140. package/src/function/algebra/solver/usolve.js +52 -55
  141. package/src/function/algebra/solver/usolveAll.js +199 -0
  142. package/src/function/algebra/solver/utils/solveValidation.js +78 -86
  143. package/src/function/arithmetic/ceil.js +63 -3
  144. package/src/function/arithmetic/fix.js +45 -6
  145. package/src/function/arithmetic/floor.js +65 -5
  146. package/src/function/arithmetic/mod.js +8 -1
  147. package/src/function/arithmetic/round.js +6 -2
  148. package/src/function/matrix/rotationMatrix.js +185 -0
  149. package/src/function/matrix/sqrtm.js +4 -0
  150. package/src/function/probability/pickRandom.js +2 -6
  151. package/src/function/statistics/variance.js +4 -4
  152. package/src/function/string/baseUtils.js +29 -0
  153. package/src/function/string/bin.js +23 -0
  154. package/src/function/string/hex.js +23 -0
  155. package/src/function/string/oct.js +24 -0
  156. package/src/type/bignumber/BigNumber.js +2 -1
  157. package/src/type/number.js +9 -1
  158. package/src/utils/object.js +3 -1
  159. package/src/version.js +1 -1
@@ -53,67 +53,57 @@ export const createLusolve = /* #__PURE__ */ factory(name, dependencies, ({ type
53
53
  return typed(name, {
54
54
 
55
55
  'Array, Array | Matrix': function (a, b) {
56
- // convert a to matrix
57
56
  a = matrix(a)
58
- // matrix lup decomposition
59
57
  const d = lup(a)
60
- // solve
61
58
  const x = _lusolve(d.L, d.U, d.p, null, b)
62
- // convert result to array
63
59
  return x.valueOf()
64
60
  },
65
61
 
66
62
  'DenseMatrix, Array | Matrix': function (a, b) {
67
- // matrix lup decomposition
68
63
  const d = lup(a)
69
- // solve
70
64
  return _lusolve(d.L, d.U, d.p, null, b)
71
65
  },
72
66
 
73
67
  'SparseMatrix, Array | Matrix': function (a, b) {
74
- // matrix lup decomposition
75
68
  const d = lup(a)
76
- // solve
77
69
  return _lusolve(d.L, d.U, d.p, null, b)
78
70
  },
79
71
 
80
72
  'SparseMatrix, Array | Matrix, number, number': function (a, b, order, threshold) {
81
- // matrix lu decomposition
82
73
  const d = slu(a, order, threshold)
83
- // solve
84
74
  return _lusolve(d.L, d.U, d.p, d.q, b)
85
75
  },
86
76
 
87
77
  'Object, Array | Matrix': function (d, b) {
88
- // solve
89
78
  return _lusolve(d.L, d.U, d.p, d.q, b)
90
79
  }
91
80
  })
92
81
 
93
82
  function _toMatrix (a) {
94
- // check it is a matrix
95
83
  if (isMatrix(a)) { return a }
96
- // check array
97
84
  if (isArray(a)) { return matrix(a) }
98
- // throw
99
85
  throw new TypeError('Invalid Matrix LU decomposition')
100
86
  }
101
87
 
102
88
  function _lusolve (l, u, p, q, b) {
103
- // verify L, U, P
89
+ // verify decomposition
104
90
  l = _toMatrix(l)
105
91
  u = _toMatrix(u)
106
- // validate matrix and vector
107
- b = solveValidation(l, b, false)
92
+
108
93
  // apply row permutations if needed (b is a DenseMatrix)
109
- if (p) { b._data = csIpvec(p, b._data) }
94
+ if (p) {
95
+ b = solveValidation(l, b, true)
96
+ b._data = csIpvec(p, b._data)
97
+ }
98
+
110
99
  // use forward substitution to resolve L * y = b
111
100
  const y = lsolve(l, b)
112
101
  // use backward substitution to resolve U * x = y
113
102
  const x = usolve(u, y)
103
+
114
104
  // apply column permutations if needed (x is a DenseMatrix)
115
105
  if (q) { x._data = csIpvec(q, x._data) }
116
- // return solution
106
+
117
107
  return x
118
108
  }
119
109
  })
@@ -16,7 +16,7 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed
16
16
  const solveValidation = createSolveValidation({ DenseMatrix })
17
17
 
18
18
  /**
19
- * Solves the linear equation system by backward substitution. Matrix must be an upper triangular matrix.
19
+ * Finds one solution of a linear equation system by backward substitution. Matrix must be an upper triangular matrix. Throws an error if there's no solution.
20
20
  *
21
21
  * `U * x = b`
22
22
  *
@@ -32,7 +32,7 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed
32
32
  *
33
33
  * See also:
34
34
  *
35
- * lup, slu, usolve, lusolve
35
+ * usolveAll, lup, slu, usolve, lusolve
36
36
  *
37
37
  * @param {Matrix, Array} U A N x N matrix or array (U)
38
38
  * @param {Matrix, Array} b A column vector with the b values
@@ -42,67 +42,64 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed
42
42
  return typed(name, {
43
43
 
44
44
  'SparseMatrix, Array | Matrix': function (m, b) {
45
- // process matrix
46
45
  return _sparseBackwardSubstitution(m, b)
47
46
  },
48
47
 
49
48
  'DenseMatrix, Array | Matrix': function (m, b) {
50
- // process matrix
51
49
  return _denseBackwardSubstitution(m, b)
52
50
  },
53
51
 
54
52
  'Array, Array | Matrix': function (a, b) {
55
- // create dense matrix from array
56
53
  const m = matrix(a)
57
- // use matrix implementation
58
54
  const r = _denseBackwardSubstitution(m, b)
59
- // result
60
55
  return r.valueOf()
61
56
  }
62
57
  })
63
58
 
64
59
  function _denseBackwardSubstitution (m, b) {
65
- // validate matrix and vector, return copy of column vector b
60
+ // make b into a column vector
66
61
  b = solveValidation(m, b, true)
67
- // column vector data
62
+
68
63
  const bdata = b._data
69
- // rows & columns
64
+
70
65
  const rows = m._size[0]
71
66
  const columns = m._size[1]
67
+
72
68
  // result
73
69
  const x = []
74
- // arrays
75
- const data = m._data
76
- // backward solve m * x = b, loop columns (backwards)
70
+
71
+ const mdata = m._data
72
+ // loop columns backwards
77
73
  for (let j = columns - 1; j >= 0; j--) {
78
74
  // b[j]
79
75
  const bj = bdata[j][0] || 0
80
76
  // x[j]
81
77
  let xj
82
- // backward substitution (outer product) avoids inner looping when bj === 0
78
+
83
79
  if (!equalScalar(bj, 0)) {
84
- // value @ [j, j]
85
- const vjj = data[j][j]
86
- // check vjj
80
+ // value at [j, j]
81
+ const vjj = mdata[j][j]
82
+
87
83
  if (equalScalar(vjj, 0)) {
88
84
  // system cannot be solved
89
85
  throw new Error('Linear system cannot be solved since matrix is singular')
90
86
  }
91
- // calculate xj
87
+
92
88
  xj = divideScalar(bj, vjj)
89
+
93
90
  // loop rows
94
91
  for (let i = j - 1; i >= 0; i--) {
95
92
  // update copy of b
96
- bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, data[i][j]))]
93
+ bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))]
97
94
  }
98
95
  } else {
99
- // zero value @ j
96
+ // zero value at j
100
97
  xj = 0
101
98
  }
102
99
  // update x
103
100
  x[j] = [xj]
104
101
  }
105
- // return column vector
102
+
106
103
  return new DenseMatrix({
107
104
  data: x,
108
105
  size: [rows, 1]
@@ -110,71 +107,71 @@ export const createUsolve = /* #__PURE__ */ factory(name, dependencies, ({ typed
110
107
  }
111
108
 
112
109
  function _sparseBackwardSubstitution (m, b) {
113
- // validate matrix and vector, return copy of column vector b
110
+ // make b into a column vector
114
111
  b = solveValidation(m, b, true)
115
- // column vector data
112
+
116
113
  const bdata = b._data
117
- // rows & columns
114
+
118
115
  const rows = m._size[0]
119
116
  const columns = m._size[1]
120
- // matrix arrays
117
+
121
118
  const values = m._values
122
119
  const index = m._index
123
120
  const ptr = m._ptr
124
- // vars
125
- let i, k
121
+
126
122
  // result
127
123
  const x = []
128
- // backward solve m * x = b, loop columns (backwards)
124
+
125
+ // loop columns backwards
129
126
  for (let j = columns - 1; j >= 0; j--) {
130
- // b[j]
131
127
  const bj = bdata[j][0] || 0
132
- // backward substitution (outer product) avoids inner looping when bj === 0
128
+
133
129
  if (!equalScalar(bj, 0)) {
134
- // value @ [j, j]
130
+ // non-degenerate row, find solution
131
+
135
132
  let vjj = 0
133
+
136
134
  // upper triangular matrix values & index (column j)
137
- const jvalues = []
138
- const jindex = []
135
+ const jValues = []
136
+ const jIndices = []
137
+
139
138
  // first & last indeces in column
140
- const f = ptr[j]
141
- let l = ptr[j + 1]
142
- // values in column, find value @ [j, j], loop backwards
143
- for (k = l - 1; k >= f; k--) {
144
- // row
145
- i = index[k]
146
- // check row
139
+ const firstIndex = ptr[j]
140
+ const lastIndex = ptr[j + 1]
141
+
142
+ // values in column, find value at [j, j], loop backwards
143
+ for (let k = lastIndex - 1; k >= firstIndex; k--) {
144
+ const i = index[k]
145
+
146
+ // check row (rows are not sorted!)
147
147
  if (i === j) {
148
- // update vjj
149
148
  vjj = values[k]
150
149
  } else if (i < j) {
151
150
  // store upper triangular
152
- jvalues.push(values[k])
153
- jindex.push(i)
151
+ jValues.push(values[k])
152
+ jIndices.push(i)
154
153
  }
155
154
  }
156
- // at this point we must have a value @ [j, j]
155
+
156
+ // at this point we must have a value in vjj
157
157
  if (equalScalar(vjj, 0)) {
158
- // system cannot be solved, there is no value @ [j, j]
159
158
  throw new Error('Linear system cannot be solved since matrix is singular')
160
159
  }
161
- // calculate xj
160
+
162
161
  const xj = divideScalar(bj, vjj)
163
- // loop upper triangular
164
- for (k = 0, l = jindex.length; k < l; k++) {
165
- // row
166
- i = jindex[k]
167
- // update copy of b
168
- bdata[i] = [subtract(bdata[i][0], multiplyScalar(xj, jvalues[k]))]
162
+
163
+ for (let k = 0, lastIndex = jIndices.length; k < lastIndex; k++) {
164
+ const i = jIndices[k]
165
+ bdata[i] = [subtract(bdata[i][0], multiplyScalar(xj, jValues[k]))]
169
166
  }
170
- // update x
167
+
171
168
  x[j] = [xj]
172
169
  } else {
173
- // update x
170
+ // degenerate row, we can choose any value
174
171
  x[j] = [0]
175
172
  }
176
173
  }
177
- // return vector
174
+
178
175
  return new DenseMatrix({
179
176
  data: x,
180
177
  size: [rows, 1]
@@ -0,0 +1,199 @@
1
+ import { factory } from '../../../utils/factory'
2
+ import { createSolveValidation } from './utils/solveValidation'
3
+
4
+ const name = 'usolveAll'
5
+ const dependencies = [
6
+ 'typed',
7
+ 'matrix',
8
+ 'divideScalar',
9
+ 'multiplyScalar',
10
+ 'subtract',
11
+ 'equalScalar',
12
+ 'DenseMatrix'
13
+ ]
14
+
15
+ export const createUsolveAll = /* #__PURE__ */ factory(name, dependencies, ({ typed, matrix, divideScalar, multiplyScalar, subtract, equalScalar, DenseMatrix }) => {
16
+ const solveValidation = createSolveValidation({ DenseMatrix })
17
+
18
+ /**
19
+ * Finds all solutions of a linear equation system by backward substitution. Matrix must be an upper triangular matrix.
20
+ *
21
+ * `U * x = b`
22
+ *
23
+ * Syntax:
24
+ *
25
+ * math.usolve(U, b)
26
+ *
27
+ * Examples:
28
+ *
29
+ * const a = [[-2, 3], [2, 1]]
30
+ * const b = [11, 9]
31
+ * const x = usolve(a, b) // [ [[8], [9]] ]
32
+ *
33
+ * See also:
34
+ *
35
+ * usolve, lup, slu, usolve, lusolve
36
+ *
37
+ * @param {Matrix, Array} U A N x N matrix or array (U)
38
+ * @param {Matrix, Array} b A column vector with the b values
39
+ *
40
+ * @return {DenseMatrix[] | Array[]} An array of affine-independent column vectors (x) that solve the linear system
41
+ */
42
+ return typed(name, {
43
+
44
+ 'SparseMatrix, Array | Matrix': function (m, b) {
45
+ return _sparseBackwardSubstitution(m, b)
46
+ },
47
+
48
+ 'DenseMatrix, Array | Matrix': function (m, b) {
49
+ return _denseBackwardSubstitution(m, b)
50
+ },
51
+
52
+ 'Array, Array | Matrix': function (a, b) {
53
+ const m = matrix(a)
54
+ const R = _denseBackwardSubstitution(m, b)
55
+ return R.map(r => r.valueOf())
56
+ }
57
+ })
58
+
59
+ function _denseBackwardSubstitution (m, b_) {
60
+ // the algorithm is derived from
61
+ // https://www.overleaf.com/project/5e6c87c554a3190001a3fc93
62
+
63
+ // array of right-hand sides
64
+ const B = [solveValidation(m, b_, true)._data.map(e => e[0])]
65
+
66
+ const M = m._data
67
+ const rows = m._size[0]
68
+ const columns = m._size[1]
69
+
70
+ // loop columns backwards
71
+ for (let i = columns - 1; i >= 0; i--) {
72
+ let L = B.length
73
+
74
+ // loop right-hand sides
75
+ for (let k = 0; k < L; k++) {
76
+ const b = B[k]
77
+
78
+ if (!equalScalar(M[i][i], 0)) {
79
+ // non-singular row
80
+
81
+ b[i] = divideScalar(b[i], M[i][i])
82
+
83
+ for (let j = i - 1; j >= 0; j--) {
84
+ // b[j] -= b[i] * M[j,i]
85
+ b[j] = subtract(b[j], multiplyScalar(b[i], M[j][i]))
86
+ }
87
+ } else if (!equalScalar(b[i], 0)) {
88
+ // singular row, nonzero RHS
89
+
90
+ if (k === 0) {
91
+ // There is no valid solution
92
+ return []
93
+ } else {
94
+ // This RHS is invalid but other solutions may still exist
95
+ B.splice(k, 1)
96
+ k -= 1
97
+ L -= 1
98
+ }
99
+ } else if (k === 0) {
100
+ // singular row, RHS is zero
101
+
102
+ const bNew = [...b]
103
+ bNew[i] = 1
104
+
105
+ for (let j = i - 1; j >= 0; j--) {
106
+ bNew[j] = subtract(bNew[j], M[j][i])
107
+ }
108
+
109
+ B.push(bNew)
110
+ }
111
+ }
112
+ }
113
+
114
+ return B.map(x => new DenseMatrix({ data: x.map(e => [e]), size: [rows, 1] }))
115
+ }
116
+
117
+ function _sparseBackwardSubstitution (m, b_) {
118
+ // array of right-hand sides
119
+ const B = [solveValidation(m, b_, true)._data.map(e => e[0])]
120
+
121
+ const rows = m._size[0]
122
+ const columns = m._size[1]
123
+
124
+ const values = m._values
125
+ const index = m._index
126
+ const ptr = m._ptr
127
+
128
+ // loop columns backwards
129
+ for (let i = columns - 1; i >= 0; i--) {
130
+ let L = B.length
131
+
132
+ // loop right-hand sides
133
+ for (let k = 0; k < L; k++) {
134
+ const b = B[k]
135
+
136
+ // values & indices (column i)
137
+ const iValues = []
138
+ const iIndices = []
139
+
140
+ // first & last indeces in column
141
+ const firstIndex = ptr[i]
142
+ const lastIndex = ptr[i + 1]
143
+
144
+ // find the value at [i, i]
145
+ let Mii = 0
146
+ for (let j = lastIndex - 1; j >= firstIndex; j--) {
147
+ const J = index[j]
148
+ // check row
149
+ if (J === i) {
150
+ Mii = values[j]
151
+ } else if (J < i) {
152
+ // store upper triangular
153
+ iValues.push(values[j])
154
+ iIndices.push(J)
155
+ }
156
+ }
157
+
158
+ if (!equalScalar(Mii, 0)) {
159
+ // non-singular row
160
+
161
+ b[i] = divideScalar(b[i], Mii)
162
+
163
+ // loop upper triangular
164
+ for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) {
165
+ const J = iIndices[j]
166
+ b[J] = subtract(b[J], multiplyScalar(b[i], iValues[j]))
167
+ }
168
+ } else if (!equalScalar(b[i], 0)) {
169
+ // singular row, nonzero RHS
170
+
171
+ if (k === 0) {
172
+ // There is no valid solution
173
+ return []
174
+ } else {
175
+ // This RHS is invalid but other solutions may still exist
176
+ B.splice(k, 1)
177
+ k -= 1
178
+ L -= 1
179
+ }
180
+ } else if (k === 0) {
181
+ // singular row, RHS is zero
182
+
183
+ const bNew = [...b]
184
+ bNew[i] = 1
185
+
186
+ // loop upper triangular
187
+ for (let j = 0, lastIndex = iIndices.length; j < lastIndex; j++) {
188
+ const J = iIndices[j]
189
+ bNew[J] = subtract(bNew[J], iValues[j])
190
+ }
191
+
192
+ B.push(bNew)
193
+ }
194
+ }
195
+ }
196
+
197
+ return B.map(x => new DenseMatrix({ data: x.map(e => [e]), size: [rows, 1] }))
198
+ }
199
+ })