node-red-contrib-prib-functions 0.17.0 → 0.19.2
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/README.md +50 -18
- package/dataAnalysis/pca.js +399 -0
- package/documentation/loadInjector.png +0 -0
- package/matrix/icons/icons8-matrix-desktop-80.png +0 -0
- package/matrix/matrix.js +660 -0
- package/matrix/matrixNode.html +214 -0
- package/matrix/matrixNode.js +162 -0
- package/package.json +33 -6
- package/test/01-base.js +88 -0
- package/test/data/.flow.json.backup +3192 -0
- package/test/data/flow.json +3212 -0
- package/test/data/settings.js +544 -0
- package/test/dataAnalysis.js +1 -1
- package/test/matrix/01base.js +338 -0
- package/test/matrix/02base.js +36 -0
- package/test/matrix/10flowMatrices.js +68 -0
- package/testing/data/countries.csv +250 -0
- package/testing/hostAvailable.html +0 -2
- package/testing/load-injector.html +76 -21
- package/testing/load-injector.js +35 -54
- package/testing/test.js +1 -0
- package/transform/transform.html +61 -19
- package/transform/transform.js +110 -6
- package/documentation/LoadInjector.JPG +0 -0
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
[Node-Red][1] nodes for various functions:
|
|
4
4
|
|
|
5
5
|
* Data Analysis - statistical metrics that has real time option
|
|
6
|
+
* Matrix
|
|
6
7
|
* Transform
|
|
7
8
|
* Test
|
|
8
9
|
* Load Injector
|
|
@@ -66,6 +67,36 @@ example:
|
|
|
66
67
|
|
|
67
68
|

|
|
68
69
|
|
|
70
|
+
|
|
71
|
+
------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
## Matrix
|
|
74
|
+
|
|
75
|
+
Define a matrix and perform various functions
|
|
76
|
+
|
|
77
|
+
* Define / Define Empty / Create / Create Like/ clone"
|
|
78
|
+
* Add / Add Row to Row / Add to Cell / Add Row / Subtract Cell
|
|
79
|
+
* Multiple / Multiple Cell / Divide Cell / Divide Row
|
|
80
|
+
* Transpose
|
|
81
|
+
* Adjoint
|
|
82
|
+
* Cofactor
|
|
83
|
+
* Complement Minor
|
|
84
|
+
* Identity
|
|
85
|
+
* Inverse
|
|
86
|
+
* Determinant
|
|
87
|
+
* Backward Substitution
|
|
88
|
+
* Forward Elimination
|
|
89
|
+
* Gaussian Elimination
|
|
90
|
+
* Reduced Row EchelonForm
|
|
91
|
+
* Row Echelon Form
|
|
92
|
+
* Nearly Equals / Is Square / Get Cell
|
|
93
|
+
* Sum Row
|
|
94
|
+
* Swap Rows
|
|
95
|
+
* To Array Object
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+

|
|
99
|
+
|
|
69
100
|
------------------------------------------------------------
|
|
70
101
|
|
|
71
102
|
## Transform
|
|
@@ -80,8 +111,12 @@ Transformations:
|
|
|
80
111
|
* Array to ISO8385
|
|
81
112
|
* Array to Messages
|
|
82
113
|
* Array to xlsx / xlsx object (excel uses [xlsx][7])
|
|
83
|
-
* AVRO to JSON (uses [avsc][6])
|
|
114
|
+
* AVRO to JSON (uses [avsc][6])
|
|
115
|
+
* Buffer to comprossed
|
|
84
116
|
* Confluence to JSON
|
|
117
|
+
* Compressed to Buffer
|
|
118
|
+
* Compressed to String
|
|
119
|
+
* COmpressed to JSON
|
|
85
120
|
* CSV to Array
|
|
86
121
|
* CSV to HTML
|
|
87
122
|
* CSV to Messages
|
|
@@ -120,7 +155,7 @@ With xlsx object one can use the function in [xlsx][7] against the object in fun
|
|
|
120
155
|
|
|
121
156
|
Example AVRO with schema
|
|
122
157
|
|
|
123
|
-

|
|
124
159
|
|
|
125
160
|
For Confluence schema contains a list of schemas in form {"<schema id>",<schema>}
|
|
126
161
|
|
|
@@ -168,7 +203,13 @@ The levenshtein distance between two character strings.
|
|
|
168
203
|
Inject messages for a set period of time with varying think time.
|
|
169
204
|
Primary purpose is testing and useful for load/stress testing.
|
|
170
205
|
|
|
171
|
-
|
|
206
|
+
Has 3 extra data types
|
|
207
|
+
1. generated id - Unique id for each message
|
|
208
|
+
2. generated data - string text generated using [dummy-json][3]
|
|
209
|
+
3. generated json - json generated using [dummy-json][3]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+

|
|
172
213
|
|
|
173
214
|
Test example:
|
|
174
215
|
|
|
@@ -247,25 +288,14 @@ Test/example flow in test/generalTest.json
|
|
|
247
288
|
|
|
248
289
|
# Version
|
|
249
290
|
|
|
250
|
-
0.
|
|
251
|
-
|
|
252
|
-
0.16.10 data analysis add eulcidean distance functions. Add array pairs
|
|
291
|
+
0.19.0 Improve load injector, fix bug in test comparing buffers, add compression tranforms
|
|
253
292
|
|
|
254
|
-
0.
|
|
255
|
-
|
|
256
|
-
0.14.2 fix general test flows. Add icon for data analysis
|
|
257
|
-
|
|
258
|
-
0.14.1 fix capitalization issue with levenshtein Distance
|
|
259
|
-
|
|
260
|
-
0.14.0 add xlsx transformer
|
|
293
|
+
0.18.0 Add matrix node
|
|
261
294
|
|
|
262
|
-
0.
|
|
263
|
-
|
|
264
|
-
0.12.0 added xml to json and json to xml. Make snappy installed separately as can cause install issues
|
|
295
|
+
0.17.0 Add finished wire to load injector
|
|
265
296
|
|
|
266
|
-
0.
|
|
297
|
+
0.16.0 fix data analysis variance and stddev, add sample, add tests
|
|
267
298
|
|
|
268
|
-
0.11.0 Transform for AVRO and snappy. Add JSON to CSV
|
|
269
299
|
|
|
270
300
|
|
|
271
301
|
# Author
|
|
@@ -285,3 +315,5 @@ Test/example flow in test/generalTest.json
|
|
|
285
315
|
[6]: https://www.npmjs.com/package/avsc "avsc"
|
|
286
316
|
|
|
287
317
|
[7]: https://www.npmjs.com/package/xlsx "xlsx"
|
|
318
|
+
|
|
319
|
+
[8]: https://www.npmjs.com/package/dummy-json "dummy-json"
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
function PCA() {
|
|
2
|
+
}
|
|
3
|
+
PCA.prototype.computeDeviationMatrix=function(matrix) {
|
|
4
|
+
return this.subtract(matrix, this.scale(this.multiply(this.unitSquareMatrix(matrix.length), matrix), 1 / matrix.length));
|
|
5
|
+
}
|
|
6
|
+
PCA.prototype.computeDeviationScores=function(deviation) {
|
|
7
|
+
return this.multiply(this.transpose(deviation), deviation);
|
|
8
|
+
}
|
|
9
|
+
PCA.prototype.computeVarianceCovariance=function(devSumOfSquares, sample) {
|
|
10
|
+
return this.scale(devSumOfSquares, 1 / (devSumOfSquares.length - sample?1:0));
|
|
11
|
+
}
|
|
12
|
+
PCA.prototype.computeSVD=function((atrix){
|
|
13
|
+
const result = svd(matrix);
|
|
14
|
+
const eigenvectors = result.U;
|
|
15
|
+
const eigenvalues = result.S;
|
|
16
|
+
return eigenvalues.map((value,i)=>{
|
|
17
|
+
return {
|
|
18
|
+
eigenvalue:value,
|
|
19
|
+
vector:eigenvectors.map((vector,j)=>-vector[i]) //HACK prevent completely negative vectors
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Get reduced dataset after removing some dimensions
|
|
24
|
+
PCA.prototype.computeAdjustedData=function(data, ...vectorObjs){
|
|
25
|
+
const vectors = vectorObjs.map((v)=>v.vector);
|
|
26
|
+
const matrixMinusMean = this.computeDeviationMatrix(data);
|
|
27
|
+
const adjustedData = this.multiply(vectors, this.transpose(matrixMinusMean));
|
|
28
|
+
const unit = this.unitSquareMatrix(data.length);
|
|
29
|
+
const avgData = this.scale(multiply(unit, data), -1 / data.length); //NOTE get the averages to add back
|
|
30
|
+
return {
|
|
31
|
+
adjustedData: adjustedData,
|
|
32
|
+
formattedAdjustedData:formatData(adjustedData, 2),
|
|
33
|
+
avgData: avgData,
|
|
34
|
+
selectedVectors: vectors
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Get original data set from reduced data set (decompress)
|
|
38
|
+
PCA.prototype.computeOriginalData=function(adjustedData, vectors, avgData) {
|
|
39
|
+
const originalWithoutMean = this.transpose(multiply(transpose(vectors), adjustedData));
|
|
40
|
+
const originalWithMean = this.subtract(originalWithoutMean, avgData);
|
|
41
|
+
return {
|
|
42
|
+
originalData: originalWithMean,
|
|
43
|
+
formattedOriginalData: this.formatData(originalWithMean, 2)
|
|
44
|
+
}
|
|
45
|
+
PCA.prototype.computePercentageExplained=function(vectors, ...selected) {
|
|
46
|
+
const total = vectors.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
|
|
47
|
+
const explained = selected.map((v)=>v.eigenvalue).reduce((a,b)=>a+b);
|
|
48
|
+
return (explained / total);
|
|
49
|
+
}
|
|
50
|
+
PCA.prototype.getEigenVectors=function(data) {
|
|
51
|
+
return this.computeSVD(this.computeVarianceCovariance(this.computeDeviationScores(this.computeDeviationMatrix(data)), false));
|
|
52
|
+
}
|
|
53
|
+
PCA.prototype.analyseTopResult=function(data){
|
|
54
|
+
const eigenVectors = this.getEigenVectors(data);
|
|
55
|
+
const sorted = this.eigenVectors.sort((a, b)=>b.eigenvalue-a.eigenvalue);
|
|
56
|
+
const selected = sorted[0].vector;
|
|
57
|
+
return this.computeAdjustedData(data, selected);
|
|
58
|
+
}
|
|
59
|
+
PCA.prototype.formatData=function(data, precision) {
|
|
60
|
+
const factor= Math.pow(10, precision || 2);
|
|
61
|
+
return data.map((d,i)=>d.map((n)=>Math.round(n * factor) / factor))
|
|
62
|
+
}
|
|
63
|
+
PCA.prototype.testMatrix=function(a){
|
|
64
|
+
if(!a[0] || !a.length) throw Error("Not matrix")
|
|
65
|
+
}
|
|
66
|
+
PCA.prototype.multiply=function(a, b){
|
|
67
|
+
this.testMatrix(a);
|
|
68
|
+
this.testMatrix(b);
|
|
69
|
+
if(b.length !== a[0].length) throw new Error('Columns in A should be the same as the number of rows in B');
|
|
70
|
+
const product = [];
|
|
71
|
+
for(let i = 0; i < a.length; i++) {
|
|
72
|
+
product[i] = []; //initialize a new row
|
|
73
|
+
for (var j = 0; j < b[0].length; j++) {
|
|
74
|
+
for (var k = 0; k < a[0].length; k++) {
|
|
75
|
+
(product[i])[j] = !!(product[i])[j] ? (product[i])[j] + (a[i])[k] * (b[k])[j] : (a[i])[k] * (b[k])[j];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return product;
|
|
80
|
+
}
|
|
81
|
+
PCA.prototype.subtract=function(a,b) {
|
|
82
|
+
if(!(a.length === b.length && a[0].length === b[0].length)) throw Error('Both A and B should have the same dimensions');
|
|
83
|
+
const result=[];
|
|
84
|
+
for(let i=0;i< a.length;i++){
|
|
85
|
+
result[i]=[];
|
|
86
|
+
for (let j = 0; j < b[0].length; j++) {
|
|
87
|
+
(result[i])[j] = (a[i])[j] - (b[i])[j];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
PCA.prototype.scale=function(matrix, factor) {
|
|
93
|
+
const result = [];
|
|
94
|
+
for(let i = 0; i < matrix.length; i++) {
|
|
95
|
+
result[i] = [];
|
|
96
|
+
for(let j = 0; j < matrix[0].length; j++) {
|
|
97
|
+
(result[i])[j] = (matrix[i])[j] * factor;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
PCA.prototype.unitSquareMatrix=function(rows) {
|
|
103
|
+
const result = [];
|
|
104
|
+
for(let i = 0; i < rows; i++) {
|
|
105
|
+
result[i] = [];
|
|
106
|
+
for (var j = 0; j < rows; j++) {
|
|
107
|
+
(result[i])[j] = 1;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
PCA.prototype.transpose=function(matrix) {
|
|
113
|
+
const operated = this.clone(matrix);
|
|
114
|
+
return operated[0].map((m,c)=>matrix.map((r)=>r[c]));
|
|
115
|
+
}
|
|
116
|
+
PCA.prototype.clone=function(m) {
|
|
117
|
+
return m.map(r=>r.map(c=>c));
|
|
118
|
+
}
|
|
119
|
+
PCA.prototype.svd=function(A) {
|
|
120
|
+
let temp;
|
|
121
|
+
const prec = Math.pow(2, -52) // double presision
|
|
122
|
+
const tolerance = 1.e-64 // precision;
|
|
123
|
+
const itmax = 50;
|
|
124
|
+
let c = 0;
|
|
125
|
+
let i = 0;
|
|
126
|
+
let j = 0;
|
|
127
|
+
let k = 0;
|
|
128
|
+
let l = 0;
|
|
129
|
+
const u = this.clone(A);
|
|
130
|
+
const m = u.length;
|
|
131
|
+
const n = u[0].length;
|
|
132
|
+
if (m < n) throw "Need more rows than columns"
|
|
133
|
+
|
|
134
|
+
const e = new Array(n); //vector1
|
|
135
|
+
const q = new Array(n); //vector2
|
|
136
|
+
for (i = 0; i < n; i++) e[i] = q[i] = 0.0;
|
|
137
|
+
var v = rep([n, n], 0);
|
|
138
|
+
|
|
139
|
+
function pythag(a, b) {
|
|
140
|
+
a = Math.abs(a)
|
|
141
|
+
b = Math.abs(b)
|
|
142
|
+
if(a > b) return a * Math.sqrt(1.0 + (b * b / a / a))
|
|
143
|
+
if(b == 0.0) return a
|
|
144
|
+
return b * Math.sqrt(1.0 + (a * a / b / b))
|
|
145
|
+
}
|
|
146
|
+
function rep(s, v, k=0) {
|
|
147
|
+
const n=s[k],
|
|
148
|
+
ret=Array(n);
|
|
149
|
+
let i;
|
|
150
|
+
if(k === s.length - 1) {
|
|
151
|
+
for(i=n-2; i >= 0; i-=2) {
|
|
152
|
+
ret[i+1] = v;
|
|
153
|
+
ret[i] = v;
|
|
154
|
+
}
|
|
155
|
+
if(i === -1) ret[0] = v;
|
|
156
|
+
return ret;
|
|
157
|
+
}
|
|
158
|
+
const kPlusOne=k++;
|
|
159
|
+
for (i= n-1; i>=0; i--) {
|
|
160
|
+
ret[i] = rep(s, v, kPlusOne);
|
|
161
|
+
}
|
|
162
|
+
return ret;
|
|
163
|
+
}
|
|
164
|
+
let f = 0.0;
|
|
165
|
+
let g = 0.0;
|
|
166
|
+
let h = 0.0;
|
|
167
|
+
let x = 0.0;
|
|
168
|
+
let y = 0.0;
|
|
169
|
+
let z = 0.0;
|
|
170
|
+
let s = 0.0;
|
|
171
|
+
|
|
172
|
+
for(i=0; i<n; i++) {
|
|
173
|
+
e[i] = g; //vector
|
|
174
|
+
s = 0.0; //sum
|
|
175
|
+
l = i+1; //stays i+1
|
|
176
|
+
for(j=i; j<m; j++)
|
|
177
|
+
s += (u[j][i] * u[j][i]);
|
|
178
|
+
if(s <= tolerance)
|
|
179
|
+
g = 0.0;
|
|
180
|
+
else {
|
|
181
|
+
f = u[i][i];
|
|
182
|
+
g = Math.sqrt(s);
|
|
183
|
+
if(f >= 0.0) g = -g;
|
|
184
|
+
h = f * g - s
|
|
185
|
+
u[i][i] = f - g;
|
|
186
|
+
for(j=l; j<n; j++) {
|
|
187
|
+
s = 0.0
|
|
188
|
+
for(k=i; k < m; k++)
|
|
189
|
+
s += u[k][i] * u[k][j]
|
|
190
|
+
f = s / h
|
|
191
|
+
for(k=i; k<m; k++)
|
|
192
|
+
u[k][j] += f * u[k][i]
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
q[i] = g
|
|
196
|
+
s = 0.0
|
|
197
|
+
for(j=l; j<n; j++)
|
|
198
|
+
s = s + u[i][j] * u[i][j]
|
|
199
|
+
if (s <= tolerance)
|
|
200
|
+
g = 0.0
|
|
201
|
+
else {
|
|
202
|
+
f = u[i][i + 1]
|
|
203
|
+
g = Math.sqrt(s)
|
|
204
|
+
if (f >= 0.0) g = -g
|
|
205
|
+
h = f * g - s
|
|
206
|
+
u[i][i + 1] = f - g;
|
|
207
|
+
for(j=l; j < n; j++) e[j] = u[i][j] / h
|
|
208
|
+
for(j=l; j < m; j++) {
|
|
209
|
+
s = 0.0
|
|
210
|
+
for(k=l; k<n; k++)
|
|
211
|
+
s += (u[j][k] * u[i][k])
|
|
212
|
+
for(k=l; k<n; k++)
|
|
213
|
+
u[j][k] += s * e[k]
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
y = Math.abs(q[i]) + Math.abs(e[i])
|
|
217
|
+
if(y > x)
|
|
218
|
+
x = y
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// accumulation of right hand transformations
|
|
222
|
+
for(i = n-1; i!=-1; i--) {
|
|
223
|
+
if (g != 0.0) {
|
|
224
|
+
h = g * u[i][i + 1]
|
|
225
|
+
for (j = l; j < n; j++)
|
|
226
|
+
v[j][i] = u[i][j] / h //u is array, v is square of columns
|
|
227
|
+
for (j = l; j < n; j++) {
|
|
228
|
+
s = 0.0
|
|
229
|
+
for (k = l; k < n; k++)
|
|
230
|
+
s += u[i][k] * v[k][j]
|
|
231
|
+
for (k = l; k < n; k++)
|
|
232
|
+
v[k][j] += (s * v[k][i])
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
for (j = l; j < n; j++) {
|
|
236
|
+
v[i][j] = 0;
|
|
237
|
+
v[j][i] = 0;
|
|
238
|
+
}
|
|
239
|
+
v[i][i] = 1;
|
|
240
|
+
g = e[i]
|
|
241
|
+
l = i
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// accumulation of left hand transformations
|
|
245
|
+
for(i=n-1; i != -1; i += -1) {
|
|
246
|
+
l = i + 1
|
|
247
|
+
g = q[i]
|
|
248
|
+
for (j = l; j < n; j++)
|
|
249
|
+
u[i][j] = 0;
|
|
250
|
+
if (g != 0.0) {
|
|
251
|
+
h = u[i][i] * g
|
|
252
|
+
for (j = l; j < n; j++) {
|
|
253
|
+
s = 0.0
|
|
254
|
+
for (k = l; k < m; k++) s += u[k][i] * u[k][j];
|
|
255
|
+
f = s / h
|
|
256
|
+
for (k = i; k < m; k++) u[k][j] += f * u[k][i];
|
|
257
|
+
}
|
|
258
|
+
for (j = i; j < m; j++) u[j][i] = u[j][i] / g;
|
|
259
|
+
} else
|
|
260
|
+
for (j = i; j < m; j++) u[j][i] = 0;
|
|
261
|
+
u[i][i] += 1;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// diagonalization of the bidiagonal form
|
|
265
|
+
prec = prec * x
|
|
266
|
+
for(k=n-1; k != -1; k--) {
|
|
267
|
+
const kPlusOne=k+1;
|
|
268
|
+
const kMinusOne=k-1;
|
|
269
|
+
for(let iteration = 0; iteration < itmax; iteration++) { // test f splitting
|
|
270
|
+
let test_convergence = false
|
|
271
|
+
for(l=k; l != -1; l--) {
|
|
272
|
+
if(Math.abs(e[l]) <= prec) {
|
|
273
|
+
test_convergence = true
|
|
274
|
+
break
|
|
275
|
+
}
|
|
276
|
+
if (Math.abs(q[l - 1]) <= prec)
|
|
277
|
+
break
|
|
278
|
+
}
|
|
279
|
+
if (!test_convergence) { // cancellation of e[l] if l>0
|
|
280
|
+
c = 0.0
|
|
281
|
+
s = 1.0
|
|
282
|
+
const l1 = l - 1
|
|
283
|
+
for(i=l; i<kPlusOne; i++) {
|
|
284
|
+
f = s * e[i]
|
|
285
|
+
e[i] = c * e[i]
|
|
286
|
+
if (Math.abs(f) <= prec)
|
|
287
|
+
break
|
|
288
|
+
g = q[i]
|
|
289
|
+
h = pythag(f, g)
|
|
290
|
+
q[i] = h
|
|
291
|
+
c = g / h
|
|
292
|
+
s = -f / h
|
|
293
|
+
for(j = 0; j<m; j++) {
|
|
294
|
+
y = u[j][l1]
|
|
295
|
+
z = u[j][i]
|
|
296
|
+
u[j][l1] = y * c + (z * s)
|
|
297
|
+
u[j][i] = -y * s + (z * c)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// test f convergence
|
|
302
|
+
z = q[k]
|
|
303
|
+
if(l == k) { //convergence
|
|
304
|
+
if(z < 0.0) { //q[k] is made non-negative
|
|
305
|
+
q[k] = -z
|
|
306
|
+
for (j=0; j<n; j++)
|
|
307
|
+
v[j][k] = -v[j][k]
|
|
308
|
+
}
|
|
309
|
+
break //break out of iteration loop and move on to next k value
|
|
310
|
+
}
|
|
311
|
+
if (iteration >= itmax - 1)
|
|
312
|
+
throw 'Error: no convergence.'
|
|
313
|
+
// shift from bottom 2x2 minor
|
|
314
|
+
x = q[l]
|
|
315
|
+
y = q[kMinusOne]
|
|
316
|
+
g = e[kMinusOne]
|
|
317
|
+
h = e[k]
|
|
318
|
+
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y)
|
|
319
|
+
g = pythag(f, 1.0)
|
|
320
|
+
if(f < 0.0)
|
|
321
|
+
f = ((x - z) * (x + z) + h * (y / (f - g) - h)) / x
|
|
322
|
+
else
|
|
323
|
+
f = ((x - z) * (x + z) + h * (y / (f + g) - h)) / x
|
|
324
|
+
// next QR transformation
|
|
325
|
+
c = 1.0
|
|
326
|
+
s = 1.0
|
|
327
|
+
for(i=l+1; i<kPlusOne; i++) {
|
|
328
|
+
g = e[i]
|
|
329
|
+
y = q[i]
|
|
330
|
+
h = s * g
|
|
331
|
+
g = c * g
|
|
332
|
+
z = pythag(f, h)
|
|
333
|
+
e[i - 1] = z
|
|
334
|
+
c = f / z
|
|
335
|
+
s = h / z
|
|
336
|
+
f = x * c + g * s
|
|
337
|
+
g = -x * s + g * c
|
|
338
|
+
h = y * s
|
|
339
|
+
y = y * c
|
|
340
|
+
for (j = 0; j < n; j++) {
|
|
341
|
+
x = v[j][i - 1]
|
|
342
|
+
z = v[j][i]
|
|
343
|
+
v[j][i - 1] = x * c + z * s
|
|
344
|
+
v[j][i] = -x * s + z * c
|
|
345
|
+
}
|
|
346
|
+
z = pythag(f, h)
|
|
347
|
+
q[i - 1] = z
|
|
348
|
+
c = f / z
|
|
349
|
+
s = h / z
|
|
350
|
+
f = c * g + s * y
|
|
351
|
+
x = -s * g + c * y
|
|
352
|
+
for (j = 0; j < m; j++) {
|
|
353
|
+
y = u[j][i - 1]
|
|
354
|
+
z = u[j][i]
|
|
355
|
+
u[j][i - 1] = y * c + z * s
|
|
356
|
+
u[j][i] = -y * s + z * c
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
e[l] = 0.0
|
|
360
|
+
e[k] = f
|
|
361
|
+
q[k] = x
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
const ql=q.length;
|
|
365
|
+
for(i=0; i<ql; i++)
|
|
366
|
+
if (q[i] < prec) q[i] = 0
|
|
367
|
+
|
|
368
|
+
//sort eigenvalues
|
|
369
|
+
for(i=0; i<n; i++) {
|
|
370
|
+
for(j=i-1; j>=0; j--) {
|
|
371
|
+
if(q[j] < q[i]) {
|
|
372
|
+
c = q[j]
|
|
373
|
+
q[j] = q[i]
|
|
374
|
+
q[i] = c
|
|
375
|
+
const ul=u.length;
|
|
376
|
+
for(k = 0; k< ul; k++) {
|
|
377
|
+
temp = u[k][i];
|
|
378
|
+
u[k][i] = u[k][j];
|
|
379
|
+
u[k][j] = temp;
|
|
380
|
+
}
|
|
381
|
+
const vl=v.length;
|
|
382
|
+
for(k=0; k<vl; k++) {
|
|
383
|
+
temp = v[k][i];
|
|
384
|
+
v[k][i] = v[k][j];
|
|
385
|
+
v[k][j] = temp;
|
|
386
|
+
}
|
|
387
|
+
i = j
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
U: u,
|
|
393
|
+
S: q,
|
|
394
|
+
V: v
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
module.exports = PCA;
|
|
Binary file
|
|
Binary file
|