@datagrok/eda 1.0.3
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 +3 -0
- package/detectors.js +9 -0
- package/dist/111.js +2 -0
- package/dist/146.js +2 -0
- package/dist/155.js +2 -0
- package/dist/355.js +2 -0
- package/dist/584.js +2 -0
- package/dist/604.js +2 -0
- package/dist/632.js +2 -0
- package/dist/645.js +2 -0
- package/dist/93.js +2 -0
- package/dist/d711f70338306e5bddc4.wasm +0 -0
- package/dist/package-test.js +2 -0
- package/dist/package.js +2 -0
- package/package.json +49 -0
- package/package.png +0 -0
- package/scripts/command.txt +1 -0
- package/scripts/exportForTS.py +862 -0
- package/scripts/exportForTSConstants.py +93 -0
- package/scripts/func.json +1 -0
- package/scripts/module.json +11 -0
- package/src/EDAtools.ts +46 -0
- package/src/EDAui.ts +118 -0
- package/src/dataGenerators.ts +74 -0
- package/src/demos.ts +38 -0
- package/src/package-test.ts +12 -0
- package/src/package.ts +248 -0
- package/src/svm.ts +485 -0
- package/src/utils.ts +51 -0
- package/tsconfig.json +71 -0
- package/wasm/EDA.js +443 -0
- package/wasm/EDA.wasm +0 -0
- package/wasm/EDAAPI.js +131 -0
- package/wasm/EDAForWebWorker.js +21 -0
- package/wasm/PCA/PCA.cpp +151 -0
- package/wasm/PCA/PCA.h +48 -0
- package/wasm/PLS/PLS.h +64 -0
- package/wasm/PLS/pls.cpp +393 -0
- package/wasm/callWasm.js +475 -0
- package/wasm/callWasmForWebWorker.js +706 -0
- package/wasm/dataGenerators.h +169 -0
- package/wasm/dataMining.h +116 -0
- package/wasm/pcaExport.cpp +64 -0
- package/wasm/plsExport.cpp +75 -0
- package/wasm/svm.h +608 -0
- package/wasm/svmApi.cpp +323 -0
- package/wasm/workers/errorWorker.js +13 -0
- package/wasm/workers/generateDatasetWorker.js +13 -0
- package/wasm/workers/normalizeDatasetWorker.js +13 -0
- package/wasm/workers/partialLeastSquareRegressionWorker.js +13 -0
- package/wasm/workers/predictByLSSVMWorker.js +13 -0
- package/wasm/workers/principalComponentAnalysisWorker.js +13 -0
- package/wasm/workers/trainAndAnalyzeLSSVMWorker.js +13 -0
- package/wasm/workers/trainLSSVMWorker.js +13 -0
- package/webpack.config.js +37 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
// Utilities for calling wasm-functions via webworker.
|
|
2
|
+
|
|
3
|
+
// We use an approach that is well described here:
|
|
4
|
+
// https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97
|
|
5
|
+
// It has been modified for usage in DATAGROK.
|
|
6
|
+
|
|
7
|
+
// Constants for wasm-functions in webworkers runtime system
|
|
8
|
+
const TYPE = 'type';
|
|
9
|
+
const NUM_TYPE = 'num';
|
|
10
|
+
const FLOAT_COLUMN_TYPE = 'floatColumn';
|
|
11
|
+
const INT_COLUMN_TYPE = 'intColumn';
|
|
12
|
+
const FLOAT_COLUMNS_TYPE = 'floatColumns';
|
|
13
|
+
const NEW_FLOAT_COLUMNS_TYPE = 'newFloatColumns';
|
|
14
|
+
const INT_COLUMNS_TYPE = 'intColumns';
|
|
15
|
+
const NEW_INT_COLUMNS_TYPE = 'newIntColumns';
|
|
16
|
+
const NEW_FLOAT_COLUMN_TYPE = 'newFloatColumn';
|
|
17
|
+
const NEW_INT_COLUMN_TYPE = 'newIntColumn';
|
|
18
|
+
const COLUMN = 'column';
|
|
19
|
+
const CALL_RESULT = '_callResult';
|
|
20
|
+
const NUM_OF_ROWS = 'numOfRows';
|
|
21
|
+
const NUM_OF_COLUMNS = 'numOfColumns';
|
|
22
|
+
const REF = 'ref';
|
|
23
|
+
const VALUE = 'value';
|
|
24
|
+
const TABLE_OF_COLUMNS = 'tableFromColumns';
|
|
25
|
+
const OBJECTS = 'objects';
|
|
26
|
+
const INT_TYPE = 'int';
|
|
27
|
+
const DOUBLE_TYPE = 'double';
|
|
28
|
+
const NUMBER = 'number';
|
|
29
|
+
|
|
30
|
+
// Type-to-heap correspondence.
|
|
31
|
+
// It is required for JS-module generated by Emscripten,
|
|
32
|
+
// and it is used, when passing array data to/from wasm-functions.
|
|
33
|
+
// More info can be found at the following link:
|
|
34
|
+
// https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97
|
|
35
|
+
const heapMap = {
|
|
36
|
+
'intColumn': "HEAP32",
|
|
37
|
+
'floatColumn': "HEAPF32",
|
|
38
|
+
'floatColumns': "HEAPF32",
|
|
39
|
+
'newFloatColumns': "HEAPF32",
|
|
40
|
+
'intColumns': "HEAP32",
|
|
41
|
+
'newIntColumns': "HEAP32",
|
|
42
|
+
'newFloatColumn': "HEAPF32",
|
|
43
|
+
'newIntColumn': "HEAP32"
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Type signature to typed array map.
|
|
47
|
+
// It is used, when manipulating column(s).
|
|
48
|
+
const typeMap = {
|
|
49
|
+
'intColumn': Int32Array,
|
|
50
|
+
'floatColumn': Float32Array,
|
|
51
|
+
'floatColumns': Float32Array,
|
|
52
|
+
'newFloatColumns': Float32Array,
|
|
53
|
+
'intColumns': Int32Array,
|
|
54
|
+
'newIntColumns': Int32Array,
|
|
55
|
+
'newFloatColumn': Float32Array,
|
|
56
|
+
'newIntColumn': Int32Array
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Type-to-shift map.
|
|
60
|
+
// It is used, when passing array to/from wasm-functions.
|
|
61
|
+
// More info can be found at the following link:
|
|
62
|
+
// https://becominghuman.ai/passing-and-returning-webassembly-array-parameters-a0f572c65d97
|
|
63
|
+
const shiftMap = {'intColumn': 2,
|
|
64
|
+
'floatColumn': 2,
|
|
65
|
+
'floatColumns': 2,
|
|
66
|
+
'newFloatColumns': 2,
|
|
67
|
+
'intColumns': 2,
|
|
68
|
+
'newIntColumns': 2,
|
|
69
|
+
'newFloatColumn': 2,
|
|
70
|
+
'newIntColumn': 2
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Get input for C++-function.
|
|
74
|
+
// This function takes specification of arguments (argsSpecification) & input data (inputVals)
|
|
75
|
+
// and returns input that will be further used in cpp/wasm-function.
|
|
76
|
+
export function getCppInput(argsSpecification, inputVals) {
|
|
77
|
+
let cppFuncInput = [];
|
|
78
|
+
let ref;
|
|
79
|
+
|
|
80
|
+
// complete an input for cpp
|
|
81
|
+
let i = 0;
|
|
82
|
+
for(const key in argsSpecification) {
|
|
83
|
+
const arg = argsSpecification[key];
|
|
84
|
+
const type = arg.type;
|
|
85
|
+
|
|
86
|
+
// skip auxiliry element
|
|
87
|
+
if(key === CALL_RESULT)
|
|
88
|
+
continue;
|
|
89
|
+
|
|
90
|
+
// here, we consider each type of input
|
|
91
|
+
switch(type) {
|
|
92
|
+
|
|
93
|
+
// numbers
|
|
94
|
+
case NUM_TYPE:
|
|
95
|
+
case INT_TYPE:
|
|
96
|
+
case DOUBLE_TYPE:
|
|
97
|
+
arg.data = inputVals[i];
|
|
98
|
+
i++;
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
// column
|
|
102
|
+
case INT_COLUMN_TYPE:
|
|
103
|
+
case FLOAT_COLUMN_TYPE:
|
|
104
|
+
|
|
105
|
+
let array;
|
|
106
|
+
|
|
107
|
+
// this is OK if type of column and target type coinside
|
|
108
|
+
//array = inputVals[i].getRawData();
|
|
109
|
+
|
|
110
|
+
let col = inputVals[i];
|
|
111
|
+
|
|
112
|
+
// here, we check types and perform an appropriate transform
|
|
113
|
+
if( ( (col.type === INT_TYPE) && (type === INT_COLUMN_TYPE) )
|
|
114
|
+
|| ( (col.type === DOUBLE_TYPE) && (type === FLOAT_COLUMN_TYPE) ) )
|
|
115
|
+
array = col.getRawData();
|
|
116
|
+
else
|
|
117
|
+
array = new typeMap[type](col.getRawData());
|
|
118
|
+
|
|
119
|
+
/*if(((col.type == 'int') && (type == INT_COLUMN_TYPE))
|
|
120
|
+
|| ((col.type == 'double') && (type == FLOAT_COLUMN_TYPE)))
|
|
121
|
+
array = col.getRawData();
|
|
122
|
+
else
|
|
123
|
+
array = new typeMap[type](col.getRawData());*/
|
|
124
|
+
|
|
125
|
+
// check types
|
|
126
|
+
arg.data = { 'array': array,
|
|
127
|
+
'numOfRows': array.length};
|
|
128
|
+
|
|
129
|
+
i++;
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
// new column
|
|
133
|
+
case NEW_INT_COLUMN_TYPE:
|
|
134
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
135
|
+
let val = 0;
|
|
136
|
+
|
|
137
|
+
ref = arg[NUM_OF_ROWS][REF];
|
|
138
|
+
|
|
139
|
+
if (argsSpecification[ref].type === NUM_TYPE)
|
|
140
|
+
val = argsSpecification[ref].data;
|
|
141
|
+
else
|
|
142
|
+
val = argsSpecification[ref].data[arg[NUM_OF_ROWS][VALUE]];
|
|
143
|
+
|
|
144
|
+
arg.data = {'numOfRows': val};
|
|
145
|
+
|
|
146
|
+
i++;
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
// columns or column_list
|
|
150
|
+
case INT_COLUMNS_TYPE:
|
|
151
|
+
case FLOAT_COLUMNS_TYPE:
|
|
152
|
+
let arrays = [];
|
|
153
|
+
|
|
154
|
+
// this is OK if type of columns and target type coinside
|
|
155
|
+
//for(let col of inputVals[i].toList())
|
|
156
|
+
// arrays.push(col.getRawData());
|
|
157
|
+
|
|
158
|
+
// here, we check types and perform an appropriate transform
|
|
159
|
+
for(let col of inputVals[i].toList())
|
|
160
|
+
if( ( (col.type === INT_TYPE) && (type === INT_COLUMN_TYPE) )
|
|
161
|
+
|| ( (col.type === DOUBLE_TYPE) && (type === FLOAT_COLUMN_TYPE) ) )
|
|
162
|
+
arrays.push(col.getRawData());
|
|
163
|
+
else
|
|
164
|
+
arrays.push(new typeMap[type](col.getRawData()));
|
|
165
|
+
|
|
166
|
+
/*for(let col of inputVals[i].toList())
|
|
167
|
+
if(((col.type == 'int') && (type == INT_COLUMN_TYPE))
|
|
168
|
+
|| ((col.type == 'double') && (type == FLOAT_COLUMN_TYPE)))
|
|
169
|
+
arrays.push(col.getRawData());
|
|
170
|
+
else
|
|
171
|
+
arrays.push(new typeMap[type](col.getRawData()));*/
|
|
172
|
+
|
|
173
|
+
arg.data = { 'arrays': arrays,
|
|
174
|
+
'numOfRows': arrays[0].length,
|
|
175
|
+
'numOfColumns': arrays.length};
|
|
176
|
+
|
|
177
|
+
i++;
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
// new columns or new column_list
|
|
181
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
182
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
183
|
+
let val1 = 0;
|
|
184
|
+
let val2 = 0;
|
|
185
|
+
|
|
186
|
+
ref = arg[NUM_OF_ROWS][REF];
|
|
187
|
+
|
|
188
|
+
if (argsSpecification[ref].type === NUM_TYPE)
|
|
189
|
+
val1 = argsSpecification[ref].data;
|
|
190
|
+
else
|
|
191
|
+
val1 = argsSpecification[ref].data[arg[NUM_OF_ROWS][VALUE]];
|
|
192
|
+
|
|
193
|
+
ref = arg[NUM_OF_COLUMNS][REF];
|
|
194
|
+
|
|
195
|
+
//console.log('Ref:');
|
|
196
|
+
//console.log(ref);
|
|
197
|
+
//console.log(argsSpecification[ref].data);
|
|
198
|
+
|
|
199
|
+
if (argsSpecification[ref].type === NUM_TYPE)
|
|
200
|
+
val2 = argsSpecification[ref].data;
|
|
201
|
+
else
|
|
202
|
+
val2 = argsSpecification[ref].data[arg[NUM_OF_COLUMNS][VALUE]];
|
|
203
|
+
|
|
204
|
+
arg.data = {'numOfRows': val1,
|
|
205
|
+
'numOfColumns': val2};
|
|
206
|
+
|
|
207
|
+
i++;
|
|
208
|
+
break;
|
|
209
|
+
|
|
210
|
+
default:
|
|
211
|
+
return; // TODO: specify behaviour
|
|
212
|
+
} // switch
|
|
213
|
+
|
|
214
|
+
cppFuncInput.push(arg);
|
|
215
|
+
} // for key
|
|
216
|
+
|
|
217
|
+
//console.log('cppFuncInput:');
|
|
218
|
+
//console.log(cppFuncInput);
|
|
219
|
+
|
|
220
|
+
return cppFuncInput;
|
|
221
|
+
} // getCppInput
|
|
222
|
+
|
|
223
|
+
// Allocate memory for buffers for array data
|
|
224
|
+
function allocateMemoryForBuffer(module, inputs) {
|
|
225
|
+
for(const arg of inputs) {
|
|
226
|
+
const type = arg.type;
|
|
227
|
+
|
|
228
|
+
switch(type) { // Process each type of input
|
|
229
|
+
|
|
230
|
+
// numbers
|
|
231
|
+
case NUM_TYPE:
|
|
232
|
+
case INT_TYPE:
|
|
233
|
+
case DOUBLE_TYPE:
|
|
234
|
+
break;
|
|
235
|
+
|
|
236
|
+
// column & new column
|
|
237
|
+
case INT_COLUMN_TYPE:
|
|
238
|
+
case FLOAT_COLUMN_TYPE:
|
|
239
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
240
|
+
case NEW_INT_COLUMN_TYPE:
|
|
241
|
+
arg.data.buf = module._malloc(arg.data.numOfRows * typeMap[type].BYTES_PER_ELEMENT);
|
|
242
|
+
break;
|
|
243
|
+
|
|
244
|
+
// columns & new columns
|
|
245
|
+
case INT_COLUMNS_TYPE:
|
|
246
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
247
|
+
case FLOAT_COLUMNS_TYPE:
|
|
248
|
+
case NEW_FLOAT_COLUMNS_TYPE: // allocation memory for columns that are created
|
|
249
|
+
arg.data.buf = module._malloc(arg.data.numOfRows * arg.data.numOfColumns
|
|
250
|
+
* typeMap[type].BYTES_PER_ELEMENT);
|
|
251
|
+
break;
|
|
252
|
+
|
|
253
|
+
// TODO: process other cases and mistakes
|
|
254
|
+
default:
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
//console.log('inputs after memory allocation:');
|
|
260
|
+
//console.log(inputs);
|
|
261
|
+
} // allocateMemoryForBuffer
|
|
262
|
+
|
|
263
|
+
// Get array of values that are put to wasm-function.
|
|
264
|
+
function getArrOfWasmParams(inputs) {
|
|
265
|
+
let params = [];
|
|
266
|
+
|
|
267
|
+
// Process each type of input
|
|
268
|
+
for(const arg of inputs) {
|
|
269
|
+
switch (arg.type) {
|
|
270
|
+
|
|
271
|
+
// numbers
|
|
272
|
+
case NUM_TYPE:
|
|
273
|
+
case INT_TYPE:
|
|
274
|
+
case DOUBLE_TYPE:
|
|
275
|
+
params.push(arg.data);
|
|
276
|
+
break;
|
|
277
|
+
|
|
278
|
+
// column & new column
|
|
279
|
+
case INT_COLUMN_TYPE:
|
|
280
|
+
case FLOAT_COLUMN_TYPE:
|
|
281
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
282
|
+
case NEW_INT_COLUMN_TYPE:
|
|
283
|
+
params.push(arg.data.buf);
|
|
284
|
+
params.push(arg.data.numOfRows);
|
|
285
|
+
break;
|
|
286
|
+
|
|
287
|
+
// columns & new columns
|
|
288
|
+
case INT_COLUMNS_TYPE:
|
|
289
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
290
|
+
case FLOAT_COLUMNS_TYPE:
|
|
291
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
292
|
+
params.push(arg.data.buf);
|
|
293
|
+
params.push(arg.data.numOfRows);
|
|
294
|
+
params.push(arg.data.numOfColumns);
|
|
295
|
+
break;
|
|
296
|
+
|
|
297
|
+
// TODO: process other cases and mistakes
|
|
298
|
+
default:
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return params;
|
|
304
|
+
} // getArrOfWasmParams
|
|
305
|
+
|
|
306
|
+
// Get array of types that are put to wasm-function.
|
|
307
|
+
function getArrOfWasmTypes(inputs) {
|
|
308
|
+
let types = [];
|
|
309
|
+
|
|
310
|
+
for(const arg of inputs) {
|
|
311
|
+
switch (arg.type) { // Process each type of input
|
|
312
|
+
|
|
313
|
+
// numbers
|
|
314
|
+
case NUM_TYPE:
|
|
315
|
+
case INT_TYPE:
|
|
316
|
+
case DOUBLE_TYPE:
|
|
317
|
+
types.push(NUMBER);
|
|
318
|
+
break;
|
|
319
|
+
|
|
320
|
+
// column & new column
|
|
321
|
+
case INT_COLUMN_TYPE:
|
|
322
|
+
case FLOAT_COLUMN_TYPE:
|
|
323
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
324
|
+
case NEW_INT_COLUMN_TYPE:
|
|
325
|
+
types.push(NUMBER);
|
|
326
|
+
types.push(NUMBER);
|
|
327
|
+
break;
|
|
328
|
+
|
|
329
|
+
// columns & new columns
|
|
330
|
+
case INT_COLUMNS_TYPE:
|
|
331
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
332
|
+
case FLOAT_COLUMNS_TYPE:
|
|
333
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
334
|
+
types.push(NUMBER);
|
|
335
|
+
types.push(NUMBER);
|
|
336
|
+
types.push(NUMBER);
|
|
337
|
+
break;
|
|
338
|
+
|
|
339
|
+
// TODO: process other cases and mistakes
|
|
340
|
+
default:
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
return types;
|
|
346
|
+
} // getArrOfWasmTypes
|
|
347
|
+
|
|
348
|
+
// Put array data to buffer
|
|
349
|
+
function putDataToBuffer(module, inputs) {
|
|
350
|
+
let shift;
|
|
351
|
+
let heap;
|
|
352
|
+
|
|
353
|
+
for(const arg of inputs) {
|
|
354
|
+
const type = arg.type;
|
|
355
|
+
|
|
356
|
+
switch (type) { // Process each type of input
|
|
357
|
+
|
|
358
|
+
// numbers
|
|
359
|
+
case NUM_TYPE:
|
|
360
|
+
case INT_TYPE:
|
|
361
|
+
case DOUBLE_TYPE:
|
|
362
|
+
break;
|
|
363
|
+
|
|
364
|
+
// column
|
|
365
|
+
case INT_COLUMN_TYPE:
|
|
366
|
+
case FLOAT_COLUMN_TYPE:
|
|
367
|
+
shift = shiftMap[type];
|
|
368
|
+
heap = module[heapMap[type]];
|
|
369
|
+
heap.set(arg.data.array, arg.data.buf >> shift);
|
|
370
|
+
break;
|
|
371
|
+
|
|
372
|
+
// columns
|
|
373
|
+
case INT_COLUMNS_TYPE:
|
|
374
|
+
case FLOAT_COLUMNS_TYPE:
|
|
375
|
+
shift = shiftMap[type];
|
|
376
|
+
heap = module[heapMap[type]];
|
|
377
|
+
let numOfBytes = typeMap[type].BYTES_PER_ELEMENT;
|
|
378
|
+
let buf = arg.data.buf;
|
|
379
|
+
let numOfColumns = arg.data.numOfColumns;
|
|
380
|
+
let numOfRows = arg.data.numOfRows;
|
|
381
|
+
let arrays = arg.data.arrays;
|
|
382
|
+
|
|
383
|
+
for(let i = 0; i < numOfColumns; i++)
|
|
384
|
+
heap.set(arrays[i], (buf + i * numOfRows * numOfBytes) >> shift);
|
|
385
|
+
|
|
386
|
+
break;
|
|
387
|
+
|
|
388
|
+
// new column(s)
|
|
389
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
390
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
391
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
392
|
+
case NEW_INT_COLUMN_TYPE:
|
|
393
|
+
break;
|
|
394
|
+
|
|
395
|
+
// TODO: process other cases and mistakes
|
|
396
|
+
default:
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
} // putDataToBuffer
|
|
401
|
+
|
|
402
|
+
// Get array data from buffer.
|
|
403
|
+
function getDataFromBuffer(module, inputs) {
|
|
404
|
+
|
|
405
|
+
let heap;
|
|
406
|
+
let numOfRows;
|
|
407
|
+
let numOfCols;
|
|
408
|
+
let numOfBytes;
|
|
409
|
+
let buf;
|
|
410
|
+
|
|
411
|
+
for(const arg of inputs) {
|
|
412
|
+
const type = arg.type;
|
|
413
|
+
|
|
414
|
+
switch (type) { // Process each type of input
|
|
415
|
+
|
|
416
|
+
// number
|
|
417
|
+
case NUM_TYPE:
|
|
418
|
+
case INT_TYPE:
|
|
419
|
+
case DOUBLE_TYPE:
|
|
420
|
+
break;
|
|
421
|
+
|
|
422
|
+
// column(s)
|
|
423
|
+
case INT_COLUMN_TYPE:
|
|
424
|
+
case FLOAT_COLUMN_TYPE:
|
|
425
|
+
case FLOAT_COLUMNS_TYPE:
|
|
426
|
+
case INT_COLUMNS_TYPE:
|
|
427
|
+
break;
|
|
428
|
+
|
|
429
|
+
// new column
|
|
430
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
431
|
+
case NEW_INT_COLUMN_TYPE:
|
|
432
|
+
heap = module[heapMap[type]];
|
|
433
|
+
numOfRows = arg.data.numOfRows;
|
|
434
|
+
numOfBytes = typeMap[type].BYTES_PER_ELEMENT;
|
|
435
|
+
buf = arg.data.buf;
|
|
436
|
+
let array = new typeMap[type](numOfRows);
|
|
437
|
+
|
|
438
|
+
for(let j = 0; j < numOfRows; j++)
|
|
439
|
+
array[j] = heap[buf / numOfBytes + j];
|
|
440
|
+
|
|
441
|
+
arg.array = array;
|
|
442
|
+
|
|
443
|
+
break;
|
|
444
|
+
|
|
445
|
+
// new columns
|
|
446
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
447
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
448
|
+
heap = module[heapMap[type]];
|
|
449
|
+
numOfRows = arg.data.numOfRows;
|
|
450
|
+
numOfCols = arg.data.numOfColumns;
|
|
451
|
+
numOfBytes = typeMap[type].BYTES_PER_ELEMENT;
|
|
452
|
+
buf = arg.data.buf;
|
|
453
|
+
let arrays = [];
|
|
454
|
+
|
|
455
|
+
for(let i = 0; i < numOfCols; i++) {
|
|
456
|
+
let arr = new typeMap[type](numOfRows);
|
|
457
|
+
|
|
458
|
+
for(let j = 0; j < numOfRows; j++)
|
|
459
|
+
arr[j] = heap[buf / numOfBytes + j + i * numOfRows];
|
|
460
|
+
|
|
461
|
+
arrays.push(arr);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
arg.arrays = arrays;
|
|
465
|
+
|
|
466
|
+
break;
|
|
467
|
+
|
|
468
|
+
// TODO: process other cases and mistakes
|
|
469
|
+
default:
|
|
470
|
+
break;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
} // getDataFromBuffer
|
|
474
|
+
|
|
475
|
+
// Clear memory allocated for array data
|
|
476
|
+
function clearMemoryForBuffer(module, inputs) {
|
|
477
|
+
for(const arg of inputs)
|
|
478
|
+
switch(arg.type) { // process each type of input
|
|
479
|
+
|
|
480
|
+
// number
|
|
481
|
+
case NUM_TYPE:
|
|
482
|
+
case INT_TYPE:
|
|
483
|
+
case DOUBLE_TYPE:
|
|
484
|
+
break;
|
|
485
|
+
|
|
486
|
+
// each non-number case
|
|
487
|
+
case INT_COLUMN_TYPE:
|
|
488
|
+
case FLOAT_COLUMN_TYPE:
|
|
489
|
+
case INT_COLUMNS_TYPE:
|
|
490
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
491
|
+
case FLOAT_COLUMNS_TYPE:
|
|
492
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
493
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
494
|
+
case NEW_INT_COLUMN_TYPE:
|
|
495
|
+
module._free(arg.data.buf);
|
|
496
|
+
break;
|
|
497
|
+
|
|
498
|
+
// TODO: process other cases and mistakes
|
|
499
|
+
default:
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
} // clearMemoryForBuffer
|
|
503
|
+
|
|
504
|
+
// Extract newly created data: new column(s) are created
|
|
505
|
+
function extractNewlyCreatedData(funcSpecificationArgs, argsAfterWasmCall) {
|
|
506
|
+
// type-to-column_creator map
|
|
507
|
+
const typeToColumnCreatorMap = {'newFloatColumns': DG.Column.fromFloat32Array,
|
|
508
|
+
'newIntColumns': DG.Column.fromInt32Array,
|
|
509
|
+
'newFloatColumn': DG.Column.fromFloat32Array,
|
|
510
|
+
'newIntColumn': DG.Column.fromInt32Array};
|
|
511
|
+
|
|
512
|
+
let i = 0;
|
|
513
|
+
|
|
514
|
+
for(const key in funcSpecificationArgs)
|
|
515
|
+
{
|
|
516
|
+
const arg = funcSpecificationArgs[key];
|
|
517
|
+
|
|
518
|
+
switch(arg.type){ // Process each type
|
|
519
|
+
|
|
520
|
+
// number
|
|
521
|
+
case NUM_TYPE:
|
|
522
|
+
case INT_TYPE:
|
|
523
|
+
case DOUBLE_TYPE:
|
|
524
|
+
break;
|
|
525
|
+
|
|
526
|
+
// column(s)
|
|
527
|
+
case INT_COLUMN_TYPE:
|
|
528
|
+
case FLOAT_COLUMN_TYPE:
|
|
529
|
+
case FLOAT_COLUMNS_TYPE:
|
|
530
|
+
case INT_COLUMNS_TYPE:
|
|
531
|
+
break;
|
|
532
|
+
|
|
533
|
+
// new column
|
|
534
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
535
|
+
case NEW_INT_COLUMN_TYPE:
|
|
536
|
+
let name;
|
|
537
|
+
|
|
538
|
+
// specify name for column
|
|
539
|
+
if(arg.name == undefined)
|
|
540
|
+
name = (0).toString();
|
|
541
|
+
else
|
|
542
|
+
names = arg.name;
|
|
543
|
+
|
|
544
|
+
arg.column = typeToColumnCreatorMap[arg.type](name,
|
|
545
|
+
argsAfterWasmCall[i].array);
|
|
546
|
+
break;
|
|
547
|
+
|
|
548
|
+
// new columns
|
|
549
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
550
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
551
|
+
let columns = [];
|
|
552
|
+
let length = argsAfterWasmCall[i].arrays.length;
|
|
553
|
+
|
|
554
|
+
let names = [];
|
|
555
|
+
|
|
556
|
+
// specify name for column
|
|
557
|
+
if(arg.names == undefined)
|
|
558
|
+
for(let k = 1; k <= length; k++)
|
|
559
|
+
names.push((k).toString());
|
|
560
|
+
else names = arg.names;
|
|
561
|
+
|
|
562
|
+
for(let j = 0; j < length; j++)
|
|
563
|
+
columns.push(typeToColumnCreatorMap[arg.type](names[j],
|
|
564
|
+
argsAfterWasmCall[i].arrays[j]));
|
|
565
|
+
|
|
566
|
+
arg.columns = columns;
|
|
567
|
+
|
|
568
|
+
break;
|
|
569
|
+
|
|
570
|
+
// TODO: process other cases and mistakes
|
|
571
|
+
default:
|
|
572
|
+
break;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
i++;
|
|
576
|
+
}
|
|
577
|
+
} // extractNewlyCreatedData
|
|
578
|
+
|
|
579
|
+
// Get output data: overall output is created
|
|
580
|
+
function getOutput(funcSpecification) {
|
|
581
|
+
let output = funcSpecification.output;
|
|
582
|
+
|
|
583
|
+
const typeToDataFieldMap = {'newFloatColumns': 'columns',
|
|
584
|
+
'newIntColumns': 'columns',
|
|
585
|
+
'newFloatColumn': 'column',
|
|
586
|
+
'newIntColumn': 'column'};
|
|
587
|
+
|
|
588
|
+
switch(output.type) {
|
|
589
|
+
|
|
590
|
+
case NUM_TYPE:
|
|
591
|
+
case INT_TYPE:
|
|
592
|
+
case DOUBLE_TYPE:
|
|
593
|
+
return funcSpecification.arguments[output.source];
|
|
594
|
+
break;
|
|
595
|
+
|
|
596
|
+
case COLUMN:
|
|
597
|
+
return funcSpecification.arguments[output.source].column;
|
|
598
|
+
break;
|
|
599
|
+
|
|
600
|
+
case TABLE_OF_COLUMNS:
|
|
601
|
+
return DG.DataFrame.fromColumns(funcSpecification.arguments[output.source].columns);
|
|
602
|
+
break;
|
|
603
|
+
|
|
604
|
+
case OBJECTS:
|
|
605
|
+
let arrayToReturn = [];
|
|
606
|
+
|
|
607
|
+
// push data of the required arguments
|
|
608
|
+
for(let name of output.source) {
|
|
609
|
+
let arg = funcSpecification.arguments[name];
|
|
610
|
+
arrayToReturn.push(arg[typeToDataFieldMap[arg.type]]);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return arrayToReturn;
|
|
614
|
+
break;
|
|
615
|
+
|
|
616
|
+
// TODO: process other cases and mistakes
|
|
617
|
+
default:
|
|
618
|
+
break;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
} // getOutput
|
|
622
|
+
|
|
623
|
+
// Clear newly created data fields (new column(s))
|
|
624
|
+
function clearNewlyCreatedData(funcSpecificationArgs) {
|
|
625
|
+
for(const key in funcSpecificationArgs) {
|
|
626
|
+
const arg = funcSpecificationArgs[key];
|
|
627
|
+
|
|
628
|
+
switch (arg.type) {
|
|
629
|
+
case NUM_TYPE:
|
|
630
|
+
case INT_TYPE:
|
|
631
|
+
case DOUBLE_TYPE:
|
|
632
|
+
case INT_COLUMN_TYPE:
|
|
633
|
+
case FLOAT_COLUMN_TYPE:
|
|
634
|
+
case INT_COLUMNS_TYPE:
|
|
635
|
+
case FLOAT_COLUMNS_TYPE:
|
|
636
|
+
break;
|
|
637
|
+
|
|
638
|
+
case NEW_INT_COLUMN_TYPE:
|
|
639
|
+
case NEW_FLOAT_COLUMN_TYPE:
|
|
640
|
+
arg.column = null;
|
|
641
|
+
break;
|
|
642
|
+
|
|
643
|
+
case NEW_INT_COLUMNS_TYPE:
|
|
644
|
+
case NEW_FLOAT_COLUMNS_TYPE:
|
|
645
|
+
arg.columns = null;
|
|
646
|
+
break;
|
|
647
|
+
|
|
648
|
+
// TODO: process other cases and mistakes
|
|
649
|
+
default:
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
} // clearNewlyCreatedData
|
|
654
|
+
|
|
655
|
+
// THE MAIN FUNCTION: a wrapper for C++-function call
|
|
656
|
+
export function cppWrapper(module, args, cppFuncName, returnType) {
|
|
657
|
+
// allocate memory for arrays that are passed to C++-function
|
|
658
|
+
allocateMemoryForBuffer(module, args);
|
|
659
|
+
|
|
660
|
+
// put data (just column(s)) to allocated buffers
|
|
661
|
+
putDataToBuffer(module, args);
|
|
662
|
+
|
|
663
|
+
// create array of parameters that are passed to C++-function
|
|
664
|
+
let params = getArrOfWasmParams(args);
|
|
665
|
+
|
|
666
|
+
//console.log('params:');
|
|
667
|
+
//console.log(params);
|
|
668
|
+
|
|
669
|
+
// create array of parameters' types that are passed to C++-function
|
|
670
|
+
let types = getArrOfWasmTypes(args);
|
|
671
|
+
|
|
672
|
+
//console.log('types:');
|
|
673
|
+
//console.log(types);
|
|
674
|
+
|
|
675
|
+
// call wasm-function
|
|
676
|
+
let result = module.ccall(cppFuncName, returnType, types, params);
|
|
677
|
+
|
|
678
|
+
//console.log(result);
|
|
679
|
+
|
|
680
|
+
// get data from buffers (just column(s))
|
|
681
|
+
getDataFromBuffer(module, args);
|
|
682
|
+
|
|
683
|
+
// clear memory that was previousely allocated
|
|
684
|
+
clearMemoryForBuffer(module, args);
|
|
685
|
+
|
|
686
|
+
//console.log('done');
|
|
687
|
+
|
|
688
|
+
return result;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// Get the required output.
|
|
692
|
+
// It takes a specification of the function and the data computed
|
|
693
|
+
// and extracts the required results.
|
|
694
|
+
export function getResult(funcSpecification, dataFromWebWorker) {
|
|
695
|
+
funcSpecification.arguments._callResult = dataFromWebWorker.callResult;
|
|
696
|
+
|
|
697
|
+
extractNewlyCreatedData(funcSpecification.arguments, dataFromWebWorker.args);
|
|
698
|
+
|
|
699
|
+
let outPut = getOutput(funcSpecification);
|
|
700
|
+
|
|
701
|
+
// Below, we remove newly created column(s), which are created at the extraction-step.
|
|
702
|
+
// It is especially required, when multiple call of wasm-functions in webworker.
|
|
703
|
+
clearNewlyCreatedData(funcSpecification.arguments);
|
|
704
|
+
|
|
705
|
+
return outPut;
|
|
706
|
+
}
|