numbl 0.0.21 → 0.0.23
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/binding.gyp +6 -4
- package/dist-cli/cli.js +767 -170
- package/native/elemwise.cpp +168 -0
- package/native/lapack_chol.cpp +1 -1
- package/native/lapack_eig.cpp +1 -1
- package/native/lapack_fft.cpp +1 -1
- package/native/lapack_fft_batch.cpp +1 -1
- package/native/lapack_inv.cpp +1 -1
- package/native/lapack_linsolve.cpp +1 -1
- package/native/lapack_lu.cpp +1 -1
- package/native/lapack_matmul.cpp +1 -1
- package/native/lapack_matmul_complex.cpp +110 -0
- package/native/lapack_qr.cpp +1 -1
- package/native/lapack_qz.cpp +1 -1
- package/native/lapack_svd.cpp +1 -1
- package/native/{lapack_addon.cpp → numbl_addon.cpp} +30 -3
- package/native/{lapack_common.h → numbl_addon_common.h} +11 -1
- package/package.json +3 -2
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Element-wise binary operations on Float64Arrays.
|
|
3
|
+
*
|
|
4
|
+
* Real:
|
|
5
|
+
* elemwise(a: Float64Array, b: Float64Array, op: number): Float64Array
|
|
6
|
+
* op: 0=add, 1=sub, 2=mul, 3=div
|
|
7
|
+
*
|
|
8
|
+
* Complex:
|
|
9
|
+
* elemwiseComplex(aRe: Float64Array, aIm: Float64Array,
|
|
10
|
+
* bRe: Float64Array, bIm: Float64Array,
|
|
11
|
+
* op: number): { re: Float64Array, im: Float64Array }
|
|
12
|
+
* op: 0=add, 1=sub, 2=mul, 3=div
|
|
13
|
+
* Pass null for aIm or bIm to treat as zero (mixed real/complex).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
#include "numbl_addon_common.h"
|
|
17
|
+
|
|
18
|
+
// ── elemwise() — real element-wise binary op ────────────────────────────────
|
|
19
|
+
|
|
20
|
+
Napi::Value Elemwise(const Napi::CallbackInfo& info) {
|
|
21
|
+
Napi::Env env = info.Env();
|
|
22
|
+
|
|
23
|
+
if (info.Length() < 3
|
|
24
|
+
|| !info[0].IsTypedArray()
|
|
25
|
+
|| !info[1].IsTypedArray()
|
|
26
|
+
|| !info[2].IsNumber()) {
|
|
27
|
+
Napi::TypeError::New(env,
|
|
28
|
+
"elemwise: expected (Float64Array a, Float64Array b, number op)")
|
|
29
|
+
.ThrowAsJavaScriptException();
|
|
30
|
+
return env.Null();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
auto arrA = info[0].As<Napi::Float64Array>();
|
|
34
|
+
auto arrB = info[1].As<Napi::Float64Array>();
|
|
35
|
+
int op = info[2].As<Napi::Number>().Int32Value();
|
|
36
|
+
|
|
37
|
+
size_t n = arrA.ElementLength();
|
|
38
|
+
if (arrB.ElementLength() != n) {
|
|
39
|
+
Napi::RangeError::New(env, "elemwise: arrays must have same length")
|
|
40
|
+
.ThrowAsJavaScriptException();
|
|
41
|
+
return env.Null();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
auto result = Napi::Float64Array::New(env, n);
|
|
45
|
+
const double* a = arrA.Data();
|
|
46
|
+
const double* b = arrB.Data();
|
|
47
|
+
double* out = result.Data();
|
|
48
|
+
|
|
49
|
+
switch (op) {
|
|
50
|
+
case 0: // add
|
|
51
|
+
for (size_t i = 0; i < n; i++) out[i] = a[i] + b[i];
|
|
52
|
+
break;
|
|
53
|
+
case 1: // sub
|
|
54
|
+
for (size_t i = 0; i < n; i++) out[i] = a[i] - b[i];
|
|
55
|
+
break;
|
|
56
|
+
case 2: // mul
|
|
57
|
+
for (size_t i = 0; i < n; i++) out[i] = a[i] * b[i];
|
|
58
|
+
break;
|
|
59
|
+
case 3: // div
|
|
60
|
+
for (size_t i = 0; i < n; i++) out[i] = a[i] / b[i];
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
Napi::RangeError::New(env, "elemwise: op must be 0-3")
|
|
64
|
+
.ThrowAsJavaScriptException();
|
|
65
|
+
return env.Null();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ── elemwiseComplex() — complex element-wise binary op ──────────────────────
|
|
72
|
+
|
|
73
|
+
Napi::Value ElemwiseComplex(const Napi::CallbackInfo& info) {
|
|
74
|
+
Napi::Env env = info.Env();
|
|
75
|
+
|
|
76
|
+
// (aRe, aIm_or_null, bRe, bIm_or_null, op)
|
|
77
|
+
if (info.Length() < 5 || !info[0].IsTypedArray() || !info[2].IsTypedArray()
|
|
78
|
+
|| !info[4].IsNumber()) {
|
|
79
|
+
Napi::TypeError::New(env,
|
|
80
|
+
"elemwiseComplex: expected (Float64Array aRe, Float64Array|null aIm, "
|
|
81
|
+
"Float64Array bRe, Float64Array|null bIm, number op)")
|
|
82
|
+
.ThrowAsJavaScriptException();
|
|
83
|
+
return env.Null();
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
auto arrARe = info[0].As<Napi::Float64Array>();
|
|
87
|
+
auto arrBRe = info[2].As<Napi::Float64Array>();
|
|
88
|
+
int op = info[4].As<Napi::Number>().Int32Value();
|
|
89
|
+
|
|
90
|
+
size_t n = arrARe.ElementLength();
|
|
91
|
+
if (arrBRe.ElementLength() != n) {
|
|
92
|
+
Napi::RangeError::New(env, "elemwiseComplex: arrays must have same length")
|
|
93
|
+
.ThrowAsJavaScriptException();
|
|
94
|
+
return env.Null();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const double* aRe = arrARe.Data();
|
|
98
|
+
const double* bRe = arrBRe.Data();
|
|
99
|
+
|
|
100
|
+
// aIm and bIm may be null (treat as zero)
|
|
101
|
+
bool hasAIm = info[1].IsTypedArray();
|
|
102
|
+
bool hasBIm = info[3].IsTypedArray();
|
|
103
|
+
const double* aIm = hasAIm ? info[1].As<Napi::Float64Array>().Data() : nullptr;
|
|
104
|
+
const double* bIm = hasBIm ? info[3].As<Napi::Float64Array>().Data() : nullptr;
|
|
105
|
+
|
|
106
|
+
auto outRe = Napi::Float64Array::New(env, n);
|
|
107
|
+
auto outIm = Napi::Float64Array::New(env, n);
|
|
108
|
+
double* oRe = outRe.Data();
|
|
109
|
+
double* oIm = outIm.Data();
|
|
110
|
+
|
|
111
|
+
switch (op) {
|
|
112
|
+
case 0: // add
|
|
113
|
+
for (size_t i = 0; i < n; i++) {
|
|
114
|
+
oRe[i] = aRe[i] + bRe[i];
|
|
115
|
+
oIm[i] = (aIm ? aIm[i] : 0.0) + (bIm ? bIm[i] : 0.0);
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
case 1: // sub
|
|
119
|
+
for (size_t i = 0; i < n; i++) {
|
|
120
|
+
oRe[i] = aRe[i] - bRe[i];
|
|
121
|
+
oIm[i] = (aIm ? aIm[i] : 0.0) - (bIm ? bIm[i] : 0.0);
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
case 2: { // mul: (a+bi)(c+di) = (ac-bd) + (ad+bc)i
|
|
125
|
+
for (size_t i = 0; i < n; i++) {
|
|
126
|
+
double ar = aRe[i], ai = aIm ? aIm[i] : 0.0;
|
|
127
|
+
double br = bRe[i], bi = bIm ? bIm[i] : 0.0;
|
|
128
|
+
oRe[i] = ar * br - ai * bi;
|
|
129
|
+
oIm[i] = ar * bi + ai * br;
|
|
130
|
+
}
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case 3: { // div: (a+bi)/(c+di) = ((ac+bd) + (bc-ad)i) / (c²+d²)
|
|
134
|
+
for (size_t i = 0; i < n; i++) {
|
|
135
|
+
double ar = aRe[i], ai = aIm ? aIm[i] : 0.0;
|
|
136
|
+
double br = bRe[i], bi = bIm ? bIm[i] : 0.0;
|
|
137
|
+
double denom = br * br + bi * bi;
|
|
138
|
+
if (denom == 0.0) {
|
|
139
|
+
oRe[i] = (ar == 0.0 && ai == 0.0) ? 0.0 / 0.0 /* NaN */
|
|
140
|
+
: (ar > 0 ? 1.0 : ar < 0 ? -1.0 : 0.0) / 0.0 /* ±Inf */;
|
|
141
|
+
oIm[i] = (ar == 0.0 && ai == 0.0) ? 0.0
|
|
142
|
+
: (ai > 0 ? 1.0 : ai < 0 ? -1.0 : 0.0) / 0.0;
|
|
143
|
+
} else {
|
|
144
|
+
oRe[i] = (ar * br + ai * bi) / denom;
|
|
145
|
+
oIm[i] = (ai * br - ar * bi) / denom;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
default:
|
|
151
|
+
Napi::RangeError::New(env, "elemwiseComplex: op must be 0-3")
|
|
152
|
+
.ThrowAsJavaScriptException();
|
|
153
|
+
return env.Null();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Check if result is purely real
|
|
157
|
+
bool isReal = true;
|
|
158
|
+
for (size_t i = 0; i < n; i++) {
|
|
159
|
+
if (oIm[i] != 0.0) { isReal = false; break; }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
auto result = Napi::Object::New(env);
|
|
163
|
+
result.Set("re", outRe);
|
|
164
|
+
if (!isReal) {
|
|
165
|
+
result.Set("im", outIm);
|
|
166
|
+
}
|
|
167
|
+
return result;
|
|
168
|
+
}
|
package/native/lapack_chol.cpp
CHANGED
package/native/lapack_eig.cpp
CHANGED
package/native/lapack_fft.cpp
CHANGED
package/native/lapack_inv.cpp
CHANGED
package/native/lapack_lu.cpp
CHANGED
package/native/lapack_matmul.cpp
CHANGED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* matmulComplex() — Complex matrix-matrix multiplication via BLAS zgemm.
|
|
3
|
+
*
|
|
4
|
+
* matmulComplex(ARe: Float64Array, AIm: Float64Array,
|
|
5
|
+
* m: number, k: number,
|
|
6
|
+
* BRe: Float64Array, BIm: Float64Array,
|
|
7
|
+
* n: number): { re: Float64Array, im: Float64Array }
|
|
8
|
+
*
|
|
9
|
+
* Computes C = A * B where:
|
|
10
|
+
* A is an m×k complex matrix (split re/im) stored in column-major order
|
|
11
|
+
* B is a k×n complex matrix (split re/im) stored in column-major order
|
|
12
|
+
* C is an m×n complex matrix returned as {re, im} in column-major order
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
#include "numbl_addon_common.h"
|
|
16
|
+
|
|
17
|
+
Napi::Value MatmulComplex(const Napi::CallbackInfo& info) {
|
|
18
|
+
Napi::Env env = info.Env();
|
|
19
|
+
|
|
20
|
+
// matmulComplex(ARe, AIm, m, k, BRe, BIm, n)
|
|
21
|
+
if (info.Length() < 7
|
|
22
|
+
|| !info[0].IsTypedArray() // ARe
|
|
23
|
+
|| !info[1].IsTypedArray() // AIm
|
|
24
|
+
|| !info[2].IsNumber() // m
|
|
25
|
+
|| !info[3].IsNumber() // k
|
|
26
|
+
|| !info[4].IsTypedArray() // BRe
|
|
27
|
+
|| !info[5].IsTypedArray() // BIm
|
|
28
|
+
|| !info[6].IsNumber()) { // n
|
|
29
|
+
Napi::TypeError::New(env,
|
|
30
|
+
"matmulComplex: expected (Float64Array ARe, Float64Array AIm, "
|
|
31
|
+
"number m, number k, Float64Array BRe, Float64Array BIm, number n)")
|
|
32
|
+
.ThrowAsJavaScriptException();
|
|
33
|
+
return env.Null();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
auto arrARe = info[0].As<Napi::Float64Array>();
|
|
37
|
+
auto arrAIm = info[1].As<Napi::Float64Array>();
|
|
38
|
+
int m = info[2].As<Napi::Number>().Int32Value();
|
|
39
|
+
int k = info[3].As<Napi::Number>().Int32Value();
|
|
40
|
+
auto arrBRe = info[4].As<Napi::Float64Array>();
|
|
41
|
+
auto arrBIm = info[5].As<Napi::Float64Array>();
|
|
42
|
+
int n = info[6].As<Napi::Number>().Int32Value();
|
|
43
|
+
|
|
44
|
+
if (m < 0 || k < 0 || n < 0) {
|
|
45
|
+
Napi::RangeError::New(env, "matmulComplex: m, k, n must be non-negative")
|
|
46
|
+
.ThrowAsJavaScriptException();
|
|
47
|
+
return env.Null();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
int mk = m * k;
|
|
51
|
+
int kn = k * n;
|
|
52
|
+
int mn = m * n;
|
|
53
|
+
|
|
54
|
+
// Handle empty-dimension multiply
|
|
55
|
+
if (m == 0 || k == 0 || n == 0) {
|
|
56
|
+
auto result = Napi::Object::New(env);
|
|
57
|
+
result.Set("re", Napi::Float64Array::New(env, static_cast<size_t>(mn)));
|
|
58
|
+
result.Set("im", Napi::Float64Array::New(env, static_cast<size_t>(mn)));
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Interleave into complex arrays for zgemm
|
|
63
|
+
std::vector<lapack_complex_double> a(mk);
|
|
64
|
+
for (int i = 0; i < mk; ++i) {
|
|
65
|
+
a[i].real = arrARe[i];
|
|
66
|
+
a[i].imag = arrAIm[i];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
std::vector<lapack_complex_double> b(kn);
|
|
70
|
+
for (int i = 0; i < kn; ++i) {
|
|
71
|
+
b[i].real = arrBRe[i];
|
|
72
|
+
b[i].imag = arrBIm[i];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
std::vector<lapack_complex_double> c(mn, {0.0, 0.0});
|
|
76
|
+
|
|
77
|
+
char transa = 'N';
|
|
78
|
+
char transb = 'N';
|
|
79
|
+
lapack_complex_double alpha = {1.0, 0.0};
|
|
80
|
+
lapack_complex_double beta = {0.0, 0.0};
|
|
81
|
+
int lda = m;
|
|
82
|
+
int ldb = k;
|
|
83
|
+
int ldc = m;
|
|
84
|
+
|
|
85
|
+
zgemm_(&transa, &transb,
|
|
86
|
+
&m, &n, &k,
|
|
87
|
+
&alpha, a.data(), &lda,
|
|
88
|
+
b.data(), &ldb,
|
|
89
|
+
&beta, c.data(), &ldc);
|
|
90
|
+
|
|
91
|
+
// Deinterleave result
|
|
92
|
+
auto result = Napi::Object::New(env);
|
|
93
|
+
auto outRe = Napi::Float64Array::New(env, static_cast<size_t>(mn));
|
|
94
|
+
auto outIm = Napi::Float64Array::New(env, static_cast<size_t>(mn));
|
|
95
|
+
for (int i = 0; i < mn; ++i) {
|
|
96
|
+
outRe[i] = c[i].real;
|
|
97
|
+
outIm[i] = c[i].imag;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if result is purely real
|
|
101
|
+
bool isReal = true;
|
|
102
|
+
for (int i = 0; i < mn; ++i) {
|
|
103
|
+
if (outIm[i] != 0.0) { isReal = false; break; }
|
|
104
|
+
}
|
|
105
|
+
result.Set("re", outRe);
|
|
106
|
+
if (!isReal) {
|
|
107
|
+
result.Set("im", outIm);
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
package/native/lapack_qr.cpp
CHANGED
package/native/lapack_qz.cpp
CHANGED
package/native/lapack_svd.cpp
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* numbl native addon — LAPACK/BLAS, FFT, element-wise arithmetic, and more.
|
|
3
3
|
*
|
|
4
4
|
* Exported functions (see individual .cpp files for full documentation):
|
|
5
5
|
*
|
|
@@ -19,11 +19,32 @@
|
|
|
19
19
|
* cholComplex(dataRe, dataIm, n, upper) — complex Cholesky (lapack_chol.cpp)
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
#include "
|
|
22
|
+
#include "numbl_addon_common.h"
|
|
23
|
+
#include <cstdlib>
|
|
24
|
+
|
|
25
|
+
extern "C" {
|
|
26
|
+
void openblas_set_num_threads(int num_threads);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ── Addon version ────────────────────────────────────────────────────────────
|
|
30
|
+
// Bump this integer whenever the addon's API changes (new functions, signature
|
|
31
|
+
// changes, etc.) so that the JS side can detect stale builds.
|
|
32
|
+
static const int ADDON_VERSION = 1;
|
|
33
|
+
|
|
34
|
+
static Napi::Value AddonVersion(const Napi::CallbackInfo& info) {
|
|
35
|
+
return Napi::Number::New(info.Env(), ADDON_VERSION);
|
|
36
|
+
}
|
|
23
37
|
|
|
24
38
|
// ── Module initialisation ─────────────────────────────────────────────────────
|
|
25
39
|
|
|
26
40
|
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
41
|
+
// Use single-threaded BLAS unless the user explicitly set the env var.
|
|
42
|
+
// Multi-threaded BLAS adds overhead for the many small matmuls in numbl.
|
|
43
|
+
if (!std::getenv("OPENBLAS_NUM_THREADS")) {
|
|
44
|
+
openblas_set_num_threads(1);
|
|
45
|
+
}
|
|
46
|
+
exports.Set(Napi::String::New(env, "addonVersion"),
|
|
47
|
+
Napi::Function::New(env, AddonVersion));
|
|
27
48
|
exports.Set(Napi::String::New(env, "inv"),
|
|
28
49
|
Napi::Function::New(env, Inv));
|
|
29
50
|
exports.Set(Napi::String::New(env, "invComplex"),
|
|
@@ -42,6 +63,8 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
|
42
63
|
Napi::Function::New(env, SvdComplex));
|
|
43
64
|
exports.Set(Napi::String::New(env, "matmul"),
|
|
44
65
|
Napi::Function::New(env, Matmul));
|
|
66
|
+
exports.Set(Napi::String::New(env, "matmulComplex"),
|
|
67
|
+
Napi::Function::New(env, MatmulComplex));
|
|
45
68
|
exports.Set(Napi::String::New(env, "linsolve"),
|
|
46
69
|
Napi::Function::New(env, Linsolve));
|
|
47
70
|
exports.Set(Napi::String::New(env, "linsolveComplex"),
|
|
@@ -64,7 +87,11 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
|
64
87
|
Napi::Function::New(env, Fft1dComplex));
|
|
65
88
|
exports.Set(Napi::String::New(env, "fftAlongDim"),
|
|
66
89
|
Napi::Function::New(env, FftAlongDim));
|
|
90
|
+
exports.Set(Napi::String::New(env, "elemwise"),
|
|
91
|
+
Napi::Function::New(env, Elemwise));
|
|
92
|
+
exports.Set(Napi::String::New(env, "elemwiseComplex"),
|
|
93
|
+
Napi::Function::New(env, ElemwiseComplex));
|
|
67
94
|
return exports;
|
|
68
95
|
}
|
|
69
96
|
|
|
70
|
-
NODE_API_MODULE(
|
|
97
|
+
NODE_API_MODULE(numbl_addon, Init)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Common includes, type definitions, LAPACK/BLAS declarations, and function
|
|
3
|
-
* prototypes shared across the
|
|
3
|
+
* prototypes shared across the numbl_addon source files.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
#pragma once
|
|
@@ -83,6 +83,13 @@ extern "C" {
|
|
|
83
83
|
double* b, int* ldb,
|
|
84
84
|
double* beta, double* c, int* ldc);
|
|
85
85
|
|
|
86
|
+
// Complex matrix-matrix multiplication: C = alpha * op(A) * op(B) + beta * C
|
|
87
|
+
void zgemm_(char* transa, char* transb,
|
|
88
|
+
int* m, int* n, int* k,
|
|
89
|
+
lapack_complex_double* alpha, lapack_complex_double* a, int* lda,
|
|
90
|
+
lapack_complex_double* b, int* ldb,
|
|
91
|
+
lapack_complex_double* beta, lapack_complex_double* c, int* ldc);
|
|
92
|
+
|
|
86
93
|
// ── Linear solve (square) ─────────────────────────────────────────────────
|
|
87
94
|
// LU factorisation + solve: A * X = B (A is n×n, B is n×nrhs)
|
|
88
95
|
// On exit A contains the LU factors; B contains X.
|
|
@@ -253,6 +260,7 @@ Napi::Value LuComplex(const Napi::CallbackInfo& info);
|
|
|
253
260
|
Napi::Value Svd(const Napi::CallbackInfo& info);
|
|
254
261
|
Napi::Value SvdComplex(const Napi::CallbackInfo& info);
|
|
255
262
|
Napi::Value Matmul(const Napi::CallbackInfo& info);
|
|
263
|
+
Napi::Value MatmulComplex(const Napi::CallbackInfo& info);
|
|
256
264
|
Napi::Value Linsolve(const Napi::CallbackInfo& info);
|
|
257
265
|
Napi::Value LinsolveComplex(const Napi::CallbackInfo& info);
|
|
258
266
|
Napi::Value Eig(const Napi::CallbackInfo& info);
|
|
@@ -264,3 +272,5 @@ Napi::Value QzComplex(const Napi::CallbackInfo& info);
|
|
|
264
272
|
Napi::Value Fft1d(const Napi::CallbackInfo& info);
|
|
265
273
|
Napi::Value Fft1dComplex(const Napi::CallbackInfo& info);
|
|
266
274
|
Napi::Value FftAlongDim(const Napi::CallbackInfo& info);
|
|
275
|
+
Napi::Value Elemwise(const Napi::CallbackInfo& info);
|
|
276
|
+
Napi::Value ElemwiseComplex(const Napi::CallbackInfo& info);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "numbl",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.23",
|
|
4
4
|
"description": "Run .m source files in the browser and on the command line by compiling to JavaScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -106,10 +106,11 @@
|
|
|
106
106
|
"vitest": "^4.0.18"
|
|
107
107
|
},
|
|
108
108
|
"lint-staged": {
|
|
109
|
-
"*.{
|
|
109
|
+
"*.{ts,tsx}": [
|
|
110
110
|
"prettier --write",
|
|
111
111
|
"eslint"
|
|
112
112
|
],
|
|
113
|
+
"*.{js,jsx}": "prettier --write",
|
|
113
114
|
"*.{json,css,md,yml}": "prettier --write"
|
|
114
115
|
},
|
|
115
116
|
"optionalDependencies": {
|