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.
- package/HISTORY.md +34 -0
- package/dist/math.js +3421 -2476
- package/dist/math.min.js +5 -5
- package/dist/math.min.map +1 -1
- package/docs/expressions/syntax.md +30 -4
- package/docs/reference/functions/bin.md +38 -0
- package/docs/reference/functions/ceil.md +10 -1
- package/docs/reference/functions/fix.md +10 -2
- package/docs/reference/functions/floor.md +12 -3
- package/docs/reference/functions/hex.md +38 -0
- package/docs/reference/functions/lsolve.md +2 -1
- package/docs/reference/functions/lsolveAll.md +45 -0
- package/docs/reference/functions/oct.md +38 -0
- package/docs/reference/functions/rotationMatrix.md +51 -0
- package/docs/reference/functions/round.md +6 -2
- package/docs/reference/functions/usolve.md +2 -1
- package/docs/reference/functions/usolveAll.md +45 -0
- package/docs/reference/functions.md +8 -2
- package/es/entry/dependenciesAny/dependenciesBin.generated.js +10 -0
- package/es/entry/dependenciesAny/dependenciesCeil.generated.js +4 -0
- package/es/entry/dependenciesAny/dependenciesFix.generated.js +2 -0
- package/es/entry/dependenciesAny/dependenciesFloor.generated.js +4 -0
- package/es/entry/dependenciesAny/dependenciesHex.generated.js +10 -0
- package/es/entry/dependenciesAny/dependenciesLsolveAll.generated.js +22 -0
- package/es/entry/dependenciesAny/dependenciesOct.generated.js +10 -0
- package/es/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +30 -0
- package/es/entry/dependenciesAny/dependenciesUsolveAll.generated.js +22 -0
- package/es/entry/dependenciesAny.generated.js +6 -0
- package/es/entry/impureFunctionsAny.generated.js +63 -57
- package/es/entry/pureFunctionsAny.generated.js +323 -277
- package/es/expression/embeddedDocs/embeddedDocs.js +12 -0
- package/es/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
- package/es/expression/embeddedDocs/function/algebra/lsolveAll.js +8 -0
- package/es/expression/embeddedDocs/function/algebra/usolve.js +2 -2
- package/es/expression/embeddedDocs/function/algebra/usolveAll.js +8 -0
- package/es/expression/embeddedDocs/function/matrix/rotationMatrix.js +8 -0
- package/es/expression/embeddedDocs/function/utils/bin.js +8 -0
- package/es/expression/embeddedDocs/function/utils/hex.js +8 -0
- package/es/expression/embeddedDocs/function/utils/oct.js +8 -0
- package/es/expression/parse.js +28 -1
- package/es/factoriesAny.js +6 -0
- package/es/function/algebra/solver/lsolve.js +42 -69
- package/es/function/algebra/solver/lsolveAll.js +213 -0
- package/es/function/algebra/solver/lusolve.js +12 -27
- package/es/function/algebra/solver/usolve.js +41 -64
- package/es/function/algebra/solver/usolveAll.js +213 -0
- package/es/function/algebra/solver/utils/solveValidation.js +66 -107
- package/es/function/arithmetic/ceil.js +88 -4
- package/es/function/arithmetic/fix.js +43 -6
- package/es/function/arithmetic/floor.js +90 -6
- package/es/function/arithmetic/mod.js +10 -1
- package/es/function/arithmetic/round.js +6 -2
- package/es/function/matrix/rotationMatrix.js +175 -0
- package/es/function/matrix/sqrtm.js +4 -0
- package/es/function/probability/pickRandom.js +2 -6
- package/es/function/statistics/variance.js +4 -4
- package/es/function/string/baseUtils.js +36 -0
- package/es/function/string/bin.js +23 -0
- package/es/function/string/hex.js +23 -0
- package/es/function/string/oct.js +23 -0
- package/es/type/bignumber/BigNumber.js +4 -1
- package/es/type/number.js +10 -0
- package/es/utils/object.js +3 -1
- package/es/version.js +1 -1
- package/examples/advanced/web_server/math_worker.js +1 -1
- package/lib/entry/dependenciesAny/dependenciesBin.generated.js +20 -0
- package/lib/entry/dependenciesAny/dependenciesCeil.generated.js +6 -0
- package/lib/entry/dependenciesAny/dependenciesFix.generated.js +3 -0
- package/lib/entry/dependenciesAny/dependenciesFloor.generated.js +6 -0
- package/lib/entry/dependenciesAny/dependenciesHex.generated.js +20 -0
- package/lib/entry/dependenciesAny/dependenciesLsolveAll.generated.js +38 -0
- package/lib/entry/dependenciesAny/dependenciesOct.generated.js +20 -0
- package/lib/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +50 -0
- package/lib/entry/dependenciesAny/dependenciesUsolveAll.generated.js +38 -0
- package/lib/entry/dependenciesAny.generated.js +48 -0
- package/lib/entry/impureFunctionsAny.generated.js +65 -59
- package/lib/entry/pureFunctionsAny.generated.js +373 -321
- package/lib/expression/embeddedDocs/embeddedDocs.js +18 -0
- package/lib/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
- package/lib/expression/embeddedDocs/function/algebra/lsolveAll.js +15 -0
- package/lib/expression/embeddedDocs/function/algebra/usolve.js +2 -2
- package/lib/expression/embeddedDocs/function/algebra/usolveAll.js +15 -0
- package/lib/expression/embeddedDocs/function/matrix/rotationMatrix.js +15 -0
- package/lib/expression/embeddedDocs/function/utils/bin.js +15 -0
- package/lib/expression/embeddedDocs/function/utils/hex.js +15 -0
- package/lib/expression/embeddedDocs/function/utils/oct.js +15 -0
- package/lib/expression/parse.js +28 -1
- package/lib/factoriesAny.js +48 -0
- package/lib/function/algebra/solver/lsolve.js +42 -69
- package/lib/function/algebra/solver/lsolveAll.js +223 -0
- package/lib/function/algebra/solver/lusolve.js +12 -27
- package/lib/function/algebra/solver/usolve.js +41 -64
- package/lib/function/algebra/solver/usolveAll.js +223 -0
- package/lib/function/algebra/solver/utils/solveValidation.js +65 -106
- package/lib/function/arithmetic/ceil.js +91 -4
- package/lib/function/arithmetic/fix.js +44 -6
- package/lib/function/arithmetic/floor.js +93 -6
- package/lib/function/arithmetic/mod.js +10 -1
- package/lib/function/arithmetic/round.js +6 -2
- package/lib/function/matrix/rotationMatrix.js +185 -0
- package/lib/function/matrix/sqrtm.js +4 -0
- package/lib/function/probability/pickRandom.js +3 -7
- package/lib/function/statistics/variance.js +4 -4
- package/lib/function/string/baseUtils.js +45 -0
- package/lib/function/string/bin.js +31 -0
- package/lib/function/string/hex.js +31 -0
- package/lib/function/string/oct.js +31 -0
- package/lib/header.js +2 -2
- package/lib/type/bignumber/BigNumber.js +3 -1
- package/lib/type/number.js +10 -0
- package/lib/utils/object.js +3 -1
- package/lib/version.js +1 -1
- package/package.json +12 -12
- package/src/entry/dependenciesAny/dependenciesBin.generated.js +11 -0
- package/src/entry/dependenciesAny/dependenciesCeil.generated.js +4 -0
- package/src/entry/dependenciesAny/dependenciesFix.generated.js +2 -0
- package/src/entry/dependenciesAny/dependenciesFloor.generated.js +4 -0
- package/src/entry/dependenciesAny/dependenciesHex.generated.js +11 -0
- package/src/entry/dependenciesAny/dependenciesLsolveAll.generated.js +23 -0
- package/src/entry/dependenciesAny/dependenciesOct.generated.js +11 -0
- package/src/entry/dependenciesAny/dependenciesRotationMatrix.generated.js +31 -0
- package/src/entry/dependenciesAny/dependenciesUsolveAll.generated.js +23 -0
- package/src/entry/dependenciesAny.generated.js +6 -0
- package/src/entry/impureFunctionsAny.generated.js +104 -92
- package/src/entry/pureFunctionsAny.generated.js +94 -82
- package/src/expression/embeddedDocs/embeddedDocs.js +12 -0
- package/src/expression/embeddedDocs/function/algebra/lsolve.js +2 -2
- package/src/expression/embeddedDocs/function/algebra/lsolveAll.js +17 -0
- package/src/expression/embeddedDocs/function/algebra/usolve.js +2 -2
- package/src/expression/embeddedDocs/function/algebra/usolveAll.js +15 -0
- package/src/expression/embeddedDocs/function/matrix/rotationMatrix.js +19 -0
- package/src/expression/embeddedDocs/function/utils/bin.js +12 -0
- package/src/expression/embeddedDocs/function/utils/hex.js +12 -0
- package/src/expression/embeddedDocs/function/utils/oct.js +12 -0
- package/src/expression/parse.js +25 -0
- package/src/factoriesAny.js +6 -0
- package/src/function/algebra/solver/lsolve.js +52 -58
- package/src/function/algebra/solver/lsolveAll.js +197 -0
- package/src/function/algebra/solver/lusolve.js +9 -19
- package/src/function/algebra/solver/usolve.js +52 -55
- package/src/function/algebra/solver/usolveAll.js +199 -0
- package/src/function/algebra/solver/utils/solveValidation.js +78 -86
- package/src/function/arithmetic/ceil.js +63 -3
- package/src/function/arithmetic/fix.js +45 -6
- package/src/function/arithmetic/floor.js +65 -5
- package/src/function/arithmetic/mod.js +8 -1
- package/src/function/arithmetic/round.js +6 -2
- package/src/function/matrix/rotationMatrix.js +185 -0
- package/src/function/matrix/sqrtm.js +4 -0
- package/src/function/probability/pickRandom.js +2 -6
- package/src/function/statistics/variance.js +4 -4
- package/src/function/string/baseUtils.js +29 -0
- package/src/function/string/bin.js +23 -0
- package/src/function/string/hex.js +23 -0
- package/src/function/string/oct.js +24 -0
- package/src/type/bignumber/BigNumber.js +2 -1
- package/src/type/number.js +9 -1
- package/src/utils/object.js +3 -1
- 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
|
|
89
|
+
// verify decomposition
|
|
104
90
|
l = _toMatrix(l)
|
|
105
91
|
u = _toMatrix(u)
|
|
106
|
-
|
|
107
|
-
b = solveValidation(l, b, false)
|
|
92
|
+
|
|
108
93
|
// apply row permutations if needed (b is a DenseMatrix)
|
|
109
|
-
if (p) {
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
//
|
|
60
|
+
// make b into a column vector
|
|
66
61
|
b = solveValidation(m, b, true)
|
|
67
|
-
|
|
62
|
+
|
|
68
63
|
const bdata = b._data
|
|
69
|
-
|
|
64
|
+
|
|
70
65
|
const rows = m._size[0]
|
|
71
66
|
const columns = m._size[1]
|
|
67
|
+
|
|
72
68
|
// result
|
|
73
69
|
const x = []
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
//
|
|
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
|
-
|
|
78
|
+
|
|
83
79
|
if (!equalScalar(bj, 0)) {
|
|
84
|
-
// value
|
|
85
|
-
const vjj =
|
|
86
|
-
|
|
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
|
-
|
|
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,
|
|
93
|
+
bdata[i] = [subtract(bdata[i][0] || 0, multiplyScalar(xj, mdata[i][j]))]
|
|
97
94
|
}
|
|
98
95
|
} else {
|
|
99
|
-
// zero value
|
|
96
|
+
// zero value at j
|
|
100
97
|
xj = 0
|
|
101
98
|
}
|
|
102
99
|
// update x
|
|
103
100
|
x[j] = [xj]
|
|
104
101
|
}
|
|
105
|
-
|
|
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
|
-
//
|
|
110
|
+
// make b into a column vector
|
|
114
111
|
b = solveValidation(m, b, true)
|
|
115
|
-
|
|
112
|
+
|
|
116
113
|
const bdata = b._data
|
|
117
|
-
|
|
114
|
+
|
|
118
115
|
const rows = m._size[0]
|
|
119
116
|
const columns = m._size[1]
|
|
120
|
-
|
|
117
|
+
|
|
121
118
|
const values = m._values
|
|
122
119
|
const index = m._index
|
|
123
120
|
const ptr = m._ptr
|
|
124
|
-
|
|
125
|
-
let i, k
|
|
121
|
+
|
|
126
122
|
// result
|
|
127
123
|
const x = []
|
|
128
|
-
|
|
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
|
-
|
|
128
|
+
|
|
133
129
|
if (!equalScalar(bj, 0)) {
|
|
134
|
-
//
|
|
130
|
+
// non-degenerate row, find solution
|
|
131
|
+
|
|
135
132
|
let vjj = 0
|
|
133
|
+
|
|
136
134
|
// upper triangular matrix values & index (column j)
|
|
137
|
-
const
|
|
138
|
-
const
|
|
135
|
+
const jValues = []
|
|
136
|
+
const jIndices = []
|
|
137
|
+
|
|
139
138
|
// first & last indeces in column
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
i = index[k]
|
|
146
|
-
|
|
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
|
-
|
|
153
|
-
|
|
151
|
+
jValues.push(values[k])
|
|
152
|
+
jIndices.push(i)
|
|
154
153
|
}
|
|
155
154
|
}
|
|
156
|
-
|
|
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
|
-
|
|
160
|
+
|
|
162
161
|
const xj = divideScalar(bj, vjj)
|
|
163
|
-
|
|
164
|
-
for (k = 0,
|
|
165
|
-
|
|
166
|
-
i =
|
|
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
|
-
|
|
167
|
+
|
|
171
168
|
x[j] = [xj]
|
|
172
169
|
} else {
|
|
173
|
-
//
|
|
170
|
+
// degenerate row, we can choose any value
|
|
174
171
|
x[j] = [0]
|
|
175
172
|
}
|
|
176
173
|
}
|
|
177
|
-
|
|
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
|
+
})
|