mathjs 7.2.0 → 7.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ })