numbl 0.4.19 → 0.4.21
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/dist-browser/browser.js +1 -1
- package/dist-browser/numbl-core/helpers/sparse-direct.d.ts +107 -0
- package/dist-browser/numbl-core/helpers/warn.d.ts +9 -0
- package/dist-browser/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-browser/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
- package/dist-browser/numbl-core/native/lapack-bridge.d.ts +29 -1
- package/dist-browser/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
- package/dist-browser/numbl-core/runtime/types.d.ts +12 -0
- package/dist-browser/numbl-core/version.d.ts +1 -1
- package/dist-browser/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
- package/dist-browser/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlae2.d.ts +4 -0
- package/dist-browser/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
- package/dist-browser/ts-lapack/src/SRC/dlanst.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlansy.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
- package/dist-browser/ts-lapack/src/SRC/dsyev.d.ts +1 -0
- package/dist-browser/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
- package/dist-cli/cli.js +3464 -172
- package/dist-lib/lib.js +3338 -46
- package/dist-lib/numbl-core/helpers/sparse-direct.d.ts +107 -0
- package/dist-lib/numbl-core/helpers/warn.d.ts +9 -0
- package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
- package/dist-lib/numbl-core/interpreter/builtins/sparse-solvers.d.ts +16 -0
- package/dist-lib/numbl-core/native/lapack-bridge.d.ts +29 -1
- package/dist-lib/numbl-core/native/ts-lapack-eig-hermitian.d.ts +33 -0
- package/dist-lib/numbl-core/runtime/types.d.ts +12 -0
- package/dist-lib/numbl-core/version.d.ts +1 -1
- package/dist-lib/ts-lapack/src/BLAS/dsymv.d.ts +1 -0
- package/dist-lib/ts-lapack/src/BLAS/dsyr2.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlae2.d.ts +4 -0
- package/dist-lib/ts-lapack/src/SRC/dlaev2.d.ts +6 -0
- package/dist-lib/ts-lapack/src/SRC/dlanst.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlansy.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dlasrt.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dorgtr.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dsteqr.d.ts +4 -0
- package/dist-lib/ts-lapack/src/SRC/dsyev.d.ts +1 -0
- package/dist-lib/ts-lapack/src/SRC/dsytd2.d.ts +1 -0
- package/dist-site-viewer/assets/index-DrtkDG_M.js +4832 -0
- package/dist-site-viewer/assets/numbl-worker-Dz_Z8B9u.js +5327 -0
- package/dist-site-viewer/index.html +1 -1
- package/native/lapack_eig.cpp +156 -0
- package/native/numbl_addon.cpp +7 -1
- package/native/numbl_addon_common.h +14 -0
- package/package.json +1 -1
- package/dist-site-viewer/assets/index-B5Y5557F.js +0 -4831
- package/dist-site-viewer/assets/numbl-worker-CtoT7C0f.js +0 -5355
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<title>numbl project</title>
|
|
8
8
|
<!-- numbl:base -->
|
|
9
9
|
<script src="./coi-serviceworker.js"></script>
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-DrtkDG_M.js"></script>
|
|
11
11
|
<link rel="stylesheet" crossorigin href="./assets/index-D5YY8PKx.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
package/native/lapack_eig.cpp
CHANGED
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
* eigComplex(dataRe, dataIm, n, computeVL, computeVR):
|
|
9
9
|
* {wRe, wIm, VLRe?, VLIm?, VRRe?, VRIm?}
|
|
10
10
|
*
|
|
11
|
+
* eigSym(data, n, computeV): {w, V?} — symmetric (dsyev)
|
|
12
|
+
* eigHerm(dataRe, dataIm, n, computeV): {w, VRe?, VIm?} — Hermitian (zheev)
|
|
13
|
+
*
|
|
11
14
|
* Note: balance parameter is accepted but ignored — dgeev always balances.
|
|
12
15
|
* The ts-lapack bridge handles the nobalance case.
|
|
13
16
|
*/
|
|
@@ -191,3 +194,156 @@ Napi::Value EigComplex(const Napi::CallbackInfo& info) {
|
|
|
191
194
|
|
|
192
195
|
return result;
|
|
193
196
|
}
|
|
197
|
+
|
|
198
|
+
// ── eigSym() ─────────────────────────────────────────────────────────────────
|
|
199
|
+
//
|
|
200
|
+
// eigSym(data: Float64Array, n: number, computeV: boolean):
|
|
201
|
+
// {w: Float64Array, V?: Float64Array}
|
|
202
|
+
//
|
|
203
|
+
// Symmetric eigenproblem via dsyev. Only the lower triangle of `data` is
|
|
204
|
+
// read. Eigenvalues come back ascending and V is orthonormal, including
|
|
205
|
+
// across repeated eigenvalues — which dgeev cannot guarantee.
|
|
206
|
+
|
|
207
|
+
Napi::Value EigSym(const Napi::CallbackInfo& info) {
|
|
208
|
+
Napi::Env env = info.Env();
|
|
209
|
+
|
|
210
|
+
if (info.Length() < 3
|
|
211
|
+
|| !info[0].IsTypedArray()
|
|
212
|
+
|| !info[1].IsNumber()
|
|
213
|
+
|| !info[2].IsBoolean()) {
|
|
214
|
+
Napi::TypeError::New(env,
|
|
215
|
+
"eigSym: expected (Float64Array data, number n, boolean computeV)")
|
|
216
|
+
.ThrowAsJavaScriptException();
|
|
217
|
+
return env.Null();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
auto arr = info[0].As<Napi::TypedArray>();
|
|
221
|
+
if (arr.TypedArrayType() != napi_float64_array) {
|
|
222
|
+
Napi::TypeError::New(env, "eigSym: data must be a Float64Array")
|
|
223
|
+
.ThrowAsJavaScriptException();
|
|
224
|
+
return env.Null();
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
int n = info[1].As<Napi::Number>().Int32Value();
|
|
228
|
+
bool computeV = info[2].As<Napi::Boolean>().Value();
|
|
229
|
+
|
|
230
|
+
if (n <= 0 || static_cast<int>(arr.ElementLength()) != n * n) {
|
|
231
|
+
Napi::RangeError::New(env, "eigSym: data.length must equal n*n")
|
|
232
|
+
.ThrowAsJavaScriptException();
|
|
233
|
+
return env.Null();
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
auto float64arr = info[0].As<Napi::Float64Array>();
|
|
237
|
+
|
|
238
|
+
std::vector<double> a(n * n);
|
|
239
|
+
std::memcpy(a.data(), float64arr.Data(), n * n * sizeof(double));
|
|
240
|
+
|
|
241
|
+
std::vector<double> w(n);
|
|
242
|
+
|
|
243
|
+
char jobz = computeV ? 'V' : 'N';
|
|
244
|
+
char uplo = 'L';
|
|
245
|
+
int info_val = 0;
|
|
246
|
+
|
|
247
|
+
// Workspace query
|
|
248
|
+
int lwork = -1;
|
|
249
|
+
double work_query = 0.0;
|
|
250
|
+
dsyev_(&jobz, &uplo, &n, a.data(), &n, w.data(),
|
|
251
|
+
&work_query, &lwork, &info_val);
|
|
252
|
+
|
|
253
|
+
lwork = static_cast<int>(work_query);
|
|
254
|
+
if (lwork < 1) lwork = std::max(1, 3 * n - 1);
|
|
255
|
+
|
|
256
|
+
std::vector<double> work(lwork);
|
|
257
|
+
|
|
258
|
+
dsyev_(&jobz, &uplo, &n, a.data(), &n, w.data(),
|
|
259
|
+
work.data(), &lwork, &info_val);
|
|
260
|
+
|
|
261
|
+
if (!checkLapackInfo(env, info_val, "eigSym", "dsyev",
|
|
262
|
+
"QR algorithm failed to converge in dsyev"))
|
|
263
|
+
return env.Null();
|
|
264
|
+
|
|
265
|
+
auto result = Napi::Object::New(env);
|
|
266
|
+
result.Set("w", vecToF64(env, w));
|
|
267
|
+
if (computeV)
|
|
268
|
+
result.Set("V", vecToF64(env, a));
|
|
269
|
+
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ── eigHerm() ────────────────────────────────────────────────────────────────
|
|
274
|
+
//
|
|
275
|
+
// eigHerm(dataRe, dataIm, n, computeV): {w, VRe?, VIm?}
|
|
276
|
+
//
|
|
277
|
+
// Hermitian eigenproblem via zheev. Only the lower triangle is read.
|
|
278
|
+
|
|
279
|
+
Napi::Value EigHerm(const Napi::CallbackInfo& info) {
|
|
280
|
+
Napi::Env env = info.Env();
|
|
281
|
+
|
|
282
|
+
if (info.Length() < 4
|
|
283
|
+
|| !info[0].IsTypedArray()
|
|
284
|
+
|| !info[1].IsTypedArray()
|
|
285
|
+
|| !info[2].IsNumber()
|
|
286
|
+
|| !info[3].IsBoolean()) {
|
|
287
|
+
Napi::TypeError::New(env,
|
|
288
|
+
"eigHerm: expected (Float64Array dataRe, Float64Array dataIm, "
|
|
289
|
+
"number n, boolean computeV)")
|
|
290
|
+
.ThrowAsJavaScriptException();
|
|
291
|
+
return env.Null();
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
auto arrRe = info[0].As<Napi::TypedArray>();
|
|
295
|
+
auto arrIm = info[1].As<Napi::TypedArray>();
|
|
296
|
+
if (arrRe.TypedArrayType() != napi_float64_array
|
|
297
|
+
|| arrIm.TypedArrayType() != napi_float64_array) {
|
|
298
|
+
Napi::TypeError::New(env, "eigHerm: data must be Float64Arrays")
|
|
299
|
+
.ThrowAsJavaScriptException();
|
|
300
|
+
return env.Null();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
int n = info[2].As<Napi::Number>().Int32Value();
|
|
304
|
+
bool computeV = info[3].As<Napi::Boolean>().Value();
|
|
305
|
+
|
|
306
|
+
if (n <= 0
|
|
307
|
+
|| static_cast<int>(arrRe.ElementLength()) != n * n
|
|
308
|
+
|| static_cast<int>(arrIm.ElementLength()) != n * n) {
|
|
309
|
+
Napi::RangeError::New(env, "eigHerm: data.length must equal n*n")
|
|
310
|
+
.ThrowAsJavaScriptException();
|
|
311
|
+
return env.Null();
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
auto a = splitToInterleaved(
|
|
315
|
+
info[0].As<Napi::Float64Array>(),
|
|
316
|
+
info[1].As<Napi::Float64Array>(), n * n);
|
|
317
|
+
|
|
318
|
+
std::vector<double> w(n);
|
|
319
|
+
std::vector<double> rwork(std::max(1, 3 * n - 2));
|
|
320
|
+
|
|
321
|
+
char jobz = computeV ? 'V' : 'N';
|
|
322
|
+
char uplo = 'L';
|
|
323
|
+
int info_val = 0;
|
|
324
|
+
|
|
325
|
+
// Workspace query
|
|
326
|
+
int lwork = -1;
|
|
327
|
+
lapack_complex_double work_query;
|
|
328
|
+
zheev_(&jobz, &uplo, &n, a.data(), &n, w.data(),
|
|
329
|
+
&work_query, &lwork, rwork.data(), &info_val);
|
|
330
|
+
|
|
331
|
+
lwork = static_cast<int>(work_query.real);
|
|
332
|
+
if (lwork < 1) lwork = std::max(1, 2 * n - 1);
|
|
333
|
+
|
|
334
|
+
std::vector<lapack_complex_double> work(lwork);
|
|
335
|
+
|
|
336
|
+
zheev_(&jobz, &uplo, &n, a.data(), &n, w.data(),
|
|
337
|
+
work.data(), &lwork, rwork.data(), &info_val);
|
|
338
|
+
|
|
339
|
+
if (!checkLapackInfo(env, info_val, "eigHerm", "zheev",
|
|
340
|
+
"QR algorithm failed to converge in zheev"))
|
|
341
|
+
return env.Null();
|
|
342
|
+
|
|
343
|
+
auto result = Napi::Object::New(env);
|
|
344
|
+
result.Set("w", vecToF64(env, w));
|
|
345
|
+
if (computeV)
|
|
346
|
+
setSplitComplex(env, result, "VRe", "VIm", a.data(), n * n);
|
|
347
|
+
|
|
348
|
+
return result;
|
|
349
|
+
}
|
package/native/numbl_addon.cpp
CHANGED
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
* linsolveComplex(ARe, AIm, m, n, BRe, BIm, nrhs) — complex linear solve (lapack_linsolve.cpp)
|
|
16
16
|
* eig(data, n, computeVL, computeVR, balance) — eigenvalue decomp. (lapack_eig.cpp)
|
|
17
17
|
* eigComplex(dataRe, dataIm, n, computeVL, computeVR) — complex eigenvalue decomp. (lapack_eig.cpp)
|
|
18
|
+
* eigSym(data, n, computeV) — symmetric eigenvalue decomp. (lapack_eig.cpp)
|
|
19
|
+
* eigHerm(dataRe, dataIm, n, computeV) — Hermitian eigenvalue decomp. (lapack_eig.cpp)
|
|
18
20
|
* chol(data, n, upper) — Cholesky factorization (lapack_chol.cpp)
|
|
19
21
|
* cholComplex(dataRe, dataIm, n, upper) — complex Cholesky (lapack_chol.cpp)
|
|
20
22
|
*/
|
|
@@ -31,7 +33,7 @@ extern "C" {
|
|
|
31
33
|
// ── Addon version ────────────────────────────────────────────────────────────
|
|
32
34
|
// Bump this integer whenever the addon's API changes (new functions, signature
|
|
33
35
|
// changes, etc.) so that the JS side can detect stale builds.
|
|
34
|
-
static const int ADDON_VERSION =
|
|
36
|
+
static const int ADDON_VERSION = 9;
|
|
35
37
|
|
|
36
38
|
// ── New tensor-ops layer (native/ops/) ───────────────────────────────────────
|
|
37
39
|
Napi::Value TensorOpRealBinary(const Napi::CallbackInfo& info);
|
|
@@ -102,8 +104,12 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
|
102
104
|
Napi::Function::New(env, LinsolveComplex));
|
|
103
105
|
exports.Set(Napi::String::New(env, "eig"),
|
|
104
106
|
Napi::Function::New(env, Eig));
|
|
107
|
+
exports.Set(Napi::String::New(env, "eigSym"),
|
|
108
|
+
Napi::Function::New(env, EigSym));
|
|
105
109
|
exports.Set(Napi::String::New(env, "eigComplex"),
|
|
106
110
|
Napi::Function::New(env, EigComplex));
|
|
111
|
+
exports.Set(Napi::String::New(env, "eigHerm"),
|
|
112
|
+
Napi::Function::New(env, EigHerm));
|
|
107
113
|
exports.Set(Napi::String::New(env, "chol"),
|
|
108
114
|
Napi::Function::New(env, Chol));
|
|
109
115
|
exports.Set(Napi::String::New(env, "cholComplex"),
|
|
@@ -137,6 +137,18 @@ extern "C" {
|
|
|
137
137
|
lapack_complex_double* vr, int* ldvr,
|
|
138
138
|
lapack_complex_double* work, int* lwork, double* rwork, int* info);
|
|
139
139
|
|
|
140
|
+
// Compute all eigenvalues and, optionally, eigenvectors of a real symmetric
|
|
141
|
+
// matrix A. Eigenvalues are returned in ascending order and the
|
|
142
|
+
// eigenvectors are orthonormal.
|
|
143
|
+
void dsyev_(char* jobz, char* uplo, int* n, double* a, int* lda,
|
|
144
|
+
double* w, double* work, int* lwork, int* info);
|
|
145
|
+
|
|
146
|
+
// Compute all eigenvalues and, optionally, eigenvectors of a complex
|
|
147
|
+
// Hermitian matrix A. Eigenvalues are real and returned in ascending order.
|
|
148
|
+
void zheev_(char* jobz, char* uplo, int* n, lapack_complex_double* a, int* lda,
|
|
149
|
+
double* w, lapack_complex_double* work, int* lwork,
|
|
150
|
+
double* rwork, int* info);
|
|
151
|
+
|
|
140
152
|
// ── Cholesky factorization ─────────────────────────────────────────────────
|
|
141
153
|
// Compute the Cholesky factorization of a real symmetric positive definite
|
|
142
154
|
// matrix: A = U^T * U (uplo='U') or A = L * L^T (uplo='L')
|
|
@@ -297,7 +309,9 @@ Napi::Value MatmulComplex(const Napi::CallbackInfo& info);
|
|
|
297
309
|
Napi::Value Linsolve(const Napi::CallbackInfo& info);
|
|
298
310
|
Napi::Value LinsolveComplex(const Napi::CallbackInfo& info);
|
|
299
311
|
Napi::Value Eig(const Napi::CallbackInfo& info);
|
|
312
|
+
Napi::Value EigSym(const Napi::CallbackInfo& info);
|
|
300
313
|
Napi::Value EigComplex(const Napi::CallbackInfo& info);
|
|
314
|
+
Napi::Value EigHerm(const Napi::CallbackInfo& info);
|
|
301
315
|
Napi::Value Chol(const Napi::CallbackInfo& info);
|
|
302
316
|
Napi::Value CholComplex(const Napi::CallbackInfo& info);
|
|
303
317
|
Napi::Value Qz(const Napi::CallbackInfo& info);
|