numbl 0.1.6 → 0.2.0

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.
Files changed (105) hide show
  1. package/binding.gyp +53 -2
  2. package/dist-cli/cli.js +38743 -24679
  3. package/dist-lib/lib.js +43424 -30466
  4. package/dist-lib/numbl-core/executeCode.d.ts +22 -0
  5. package/dist-lib/numbl-core/helpers/bessel.d.ts +9 -0
  6. package/dist-lib/numbl-core/helpers/reduction-helpers.d.ts +7 -2
  7. package/dist-lib/numbl-core/interpreter/builtins/datetime.d.ts +39 -0
  8. package/dist-lib/numbl-core/interpreter/builtins/index.d.ts +1 -0
  9. package/dist-lib/numbl-core/interpreter/builtins/time-system.d.ts +1 -0
  10. package/dist-lib/numbl-core/interpreter/builtins/types.d.ts +100 -5
  11. package/dist-lib/numbl-core/interpreter/interpreter.d.ts +41 -3
  12. package/dist-lib/numbl-core/interpreter/interpreterSpecialBuiltins.d.ts +2 -0
  13. package/dist-lib/numbl-core/interpreter/types.d.ts +16 -7
  14. package/dist-lib/numbl-core/jit/c/abi.d.ts +90 -0
  15. package/dist-lib/numbl-core/jit/c/assemble.d.ts +56 -0
  16. package/dist-lib/numbl-core/jit/c/classify.d.ts +70 -0
  17. package/dist-lib/numbl-core/jit/c/compile.d.ts +37 -0
  18. package/dist-lib/numbl-core/jit/c/context.d.ts +152 -0
  19. package/dist-lib/numbl-core/jit/c/emit/assign.d.ts +20 -0
  20. package/dist-lib/numbl-core/jit/c/emit/complexScalar.d.ts +18 -0
  21. package/dist-lib/numbl-core/jit/c/emit/fused.d.ts +42 -0
  22. package/dist-lib/numbl-core/jit/c/emit/helpers.d.ts +40 -0
  23. package/dist-lib/numbl-core/jit/c/emit/index.d.ts +14 -0
  24. package/dist-lib/numbl-core/jit/c/emit/scalar.d.ts +23 -0
  25. package/dist-lib/numbl-core/jit/c/emit/stmt.d.ts +25 -0
  26. package/dist-lib/numbl-core/jit/c/emit/tensor.d.ts +127 -0
  27. package/dist-lib/numbl-core/jit/c/emit/userCall.d.ts +58 -0
  28. package/dist-lib/numbl-core/jit/c/epilogue.d.ts +26 -0
  29. package/dist-lib/numbl-core/jit/c/feasibility.d.ts +44 -0
  30. package/dist-lib/numbl-core/jit/c/hybrid.d.ts +42 -0
  31. package/dist-lib/numbl-core/jit/c/install.d.ts +15 -0
  32. package/dist-lib/numbl-core/jit/c/parityError.d.ts +26 -0
  33. package/dist-lib/numbl-core/jit/c/prelude.d.ts +37 -0
  34. package/dist-lib/numbl-core/jit/c/registry.d.ts +51 -0
  35. package/dist-lib/numbl-core/jit/c/visit.d.ts +63 -0
  36. package/dist-lib/numbl-core/jit/e1/install.d.ts +13 -0
  37. package/dist-lib/numbl-core/jit/e1/kernelEmit.d.ts +54 -0
  38. package/dist-lib/numbl-core/jit/e1/openmpFlag.d.ts +13 -0
  39. package/dist-lib/numbl-core/jit/e1/scalarFnKernel.d.ts +44 -0
  40. package/dist-lib/numbl-core/jit/fusedChainHelpers.d.ts +65 -0
  41. package/dist-lib/numbl-core/jit/fusedScalarEmit.d.ts +61 -0
  42. package/dist-lib/numbl-core/jit/fusion.d.ts +71 -0
  43. package/dist-lib/numbl-core/jit/fusionOps.d.ts +25 -0
  44. package/dist-lib/numbl-core/{interpreter/jit → jit}/index.d.ts +2 -2
  45. package/dist-lib/numbl-core/jit/jitBailSafety.d.ts +41 -0
  46. package/dist-lib/numbl-core/{interpreter/jit → jit}/jitLoop.d.ts +2 -2
  47. package/dist-lib/numbl-core/{interpreter/jit → jit}/jitLoopAnalysis.d.ts +13 -1
  48. package/dist-lib/numbl-core/jit/jitLower.d.ts +122 -0
  49. package/dist-lib/numbl-core/jit/jitLowerExpr.d.ts +27 -0
  50. package/dist-lib/numbl-core/jit/jitLowerStmt.d.ts +9 -0
  51. package/dist-lib/numbl-core/jit/jitLowerTypes.d.ts +29 -0
  52. package/dist-lib/numbl-core/jit/jitTopLevel.d.ts +22 -0
  53. package/dist-lib/numbl-core/jit/jitTypes.d.ts +394 -0
  54. package/dist-lib/numbl-core/jit/js/jitCodegen.d.ts +7 -0
  55. package/dist-lib/numbl-core/jit/js/jitCodegenHoist.d.ts +70 -0
  56. package/dist-lib/numbl-core/jit/js/jitHelpers.d.ts +34 -0
  57. package/dist-lib/numbl-core/jit/js/jitHelpersComplex.d.ts +21 -0
  58. package/dist-lib/numbl-core/jit/js/jitHelpersIndex.d.ts +33 -0
  59. package/dist-lib/numbl-core/jit/js/jitHelpersTensor.d.ts +34 -0
  60. package/dist-lib/numbl-core/jit/js/jsFusedCodegen.d.ts +17 -0
  61. package/dist-lib/numbl-core/jit/scalarEmit.d.ts +58 -0
  62. package/dist-lib/numbl-core/lexer/types.d.ts +2 -1
  63. package/dist-lib/numbl-core/native/lapack-bridge.d.ts +46 -1
  64. package/dist-lib/numbl-core/ops/bessel.d.ts +18 -0
  65. package/dist-lib/numbl-core/ops/comparison.d.ts +11 -0
  66. package/dist-lib/numbl-core/ops/complexBinaryElemwise.d.ts +10 -0
  67. package/dist-lib/numbl-core/ops/complexUnaryElemwise.d.ts +8 -0
  68. package/dist-lib/numbl-core/ops/dispatch.d.ts +26 -0
  69. package/dist-lib/numbl-core/ops/index.d.ts +8 -0
  70. package/dist-lib/numbl-core/ops/opCodes.d.ts +70 -0
  71. package/dist-lib/numbl-core/ops/realBinaryElemwise.d.ts +8 -0
  72. package/dist-lib/numbl-core/ops/realUnaryElemwise.d.ts +5 -0
  73. package/dist-lib/numbl-core/ops/reduce.d.ts +6 -0
  74. package/dist-lib/numbl-core/parser/types.d.ts +6 -0
  75. package/dist-lib/numbl-core/runtime/alloc.d.ts +23 -0
  76. package/dist-lib/numbl-core/runtime/constructors.d.ts +2 -1
  77. package/dist-lib/numbl-core/runtime/error.d.ts +3 -0
  78. package/dist-lib/numbl-core/runtime/index.d.ts +1 -1
  79. package/dist-lib/numbl-core/runtime/runtime.d.ts +15 -2
  80. package/dist-lib/numbl-core/runtime/runtimePlot.d.ts +11 -0
  81. package/dist-lib/numbl-core/runtime/types.d.ts +16 -1
  82. package/dist-lib/numbl-core/runtime/utils.d.ts +3 -1
  83. package/dist-lib/numbl-core/version.d.ts +1 -1
  84. package/dist-plot-viewer/assets/{index-vtrJ8bml.js → index-GiUNnMQg.js} +1 -1
  85. package/dist-plot-viewer/index.html +1 -1
  86. package/native/elemwise.cpp +134 -0
  87. package/native/jit_runtime/jit_runtime.c +261 -0
  88. package/native/jit_runtime/jit_runtime.h +204 -0
  89. package/native/numbl_addon.cpp +55 -1
  90. package/native/numbl_addon_common.h +1 -0
  91. package/native/ops/bessel.c +572 -0
  92. package/native/ops/comparison.c +150 -0
  93. package/native/ops/complex_binary_elemwise.c +192 -0
  94. package/native/ops/complex_unary_elemwise.c +152 -0
  95. package/native/ops/numbl_ops.c +66 -0
  96. package/native/ops/numbl_ops.h +262 -0
  97. package/native/ops/real_binary_elemwise.c +85 -0
  98. package/native/ops/real_unary_elemwise.c +104 -0
  99. package/native/ops/reduce.c +162 -0
  100. package/native/ops_napi.cpp +320 -0
  101. package/package.json +11 -10
  102. package/dist-lib/numbl-core/interpreter/jit/jitCodegen.d.ts +0 -5
  103. package/dist-lib/numbl-core/interpreter/jit/jitHelpers.d.ts +0 -14
  104. package/dist-lib/numbl-core/interpreter/jit/jitLower.d.ts +0 -20
  105. package/dist-lib/numbl-core/interpreter/jit/jitTypes.d.ts +0 -168
@@ -0,0 +1,320 @@
1
+ /**
2
+ * N-API wrappers for the new tensor-ops layer (native/ops/).
3
+ *
4
+ * Each export is a thin shim: validate args, get raw pointers via Data(),
5
+ * call the C core, throw on negative return. The output buffer is
6
+ * caller-allocated (passed in as the last argument).
7
+ *
8
+ * Categories exposed:
9
+ * tensorOpRealBinary(op, n, a, b, out)
10
+ * tensorOpRealScalarBinary(op, n, scalar, arr, scalarOnLeft, out)
11
+ * tensorOpComplexBinary(op, n, aRe, aIm|null, bRe, bIm|null, outRe, outIm)
12
+ * tensorOpComplexScalarBinary(op, n, sRe, sIm, arrRe, arrIm|null, scalarOnLeft, outRe, outIm)
13
+ * tensorOpDumpCodes() → string (used only by drift-detection test)
14
+ */
15
+
16
+ #include <napi.h>
17
+
18
+ extern "C" {
19
+ #include "ops/numbl_ops.h"
20
+ }
21
+
22
+ namespace {
23
+
24
+ inline void ThrowOnError(Napi::Env env, int code, const char* op_name) {
25
+ if (code != NUMBL_OK) {
26
+ std::string msg = std::string(op_name) + ": " + numbl_strerror(code);
27
+ Napi::Error::New(env, msg).ThrowAsJavaScriptException();
28
+ }
29
+ }
30
+
31
+ inline const double* AsF64(const Napi::Value& v) {
32
+ return v.As<Napi::Float64Array>().Data();
33
+ }
34
+
35
+ inline double* AsF64Mut(const Napi::Value& v) {
36
+ return v.As<Napi::Float64Array>().Data();
37
+ }
38
+
39
+ inline const double* AsF64OrNull(const Napi::Value& v) {
40
+ if (v.IsNull() || v.IsUndefined()) return nullptr;
41
+ return v.As<Napi::Float64Array>().Data();
42
+ }
43
+
44
+ } // namespace
45
+
46
+ Napi::Value TensorOpRealBinary(const Napi::CallbackInfo& info) {
47
+ Napi::Env env = info.Env();
48
+ if (info.Length() < 5) {
49
+ Napi::TypeError::New(env,
50
+ "tensorOpRealBinary(op, n, a, b, out)")
51
+ .ThrowAsJavaScriptException();
52
+ return env.Undefined();
53
+ }
54
+ int op = info[0].As<Napi::Number>().Int32Value();
55
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
56
+ int rc = numbl_real_binary_elemwise(
57
+ op, n, AsF64(info[2]), AsF64(info[3]), AsF64Mut(info[4]));
58
+ ThrowOnError(env, rc, "tensorOpRealBinary");
59
+ return env.Undefined();
60
+ }
61
+
62
+ Napi::Value TensorOpRealScalarBinary(const Napi::CallbackInfo& info) {
63
+ Napi::Env env = info.Env();
64
+ if (info.Length() < 6) {
65
+ Napi::TypeError::New(env,
66
+ "tensorOpRealScalarBinary(op, n, scalar, arr, scalarOnLeft, out)")
67
+ .ThrowAsJavaScriptException();
68
+ return env.Undefined();
69
+ }
70
+ int op = info[0].As<Napi::Number>().Int32Value();
71
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
72
+ double scalar = info[2].As<Napi::Number>().DoubleValue();
73
+ int scalar_on_left = info[4].As<Napi::Boolean>().Value() ? 1 : 0;
74
+ int rc = numbl_real_scalar_binary_elemwise(
75
+ op, n, scalar, AsF64(info[3]), scalar_on_left, AsF64Mut(info[5]));
76
+ ThrowOnError(env, rc, "tensorOpRealScalarBinary");
77
+ return env.Undefined();
78
+ }
79
+
80
+ Napi::Value TensorOpComplexBinary(const Napi::CallbackInfo& info) {
81
+ Napi::Env env = info.Env();
82
+ if (info.Length() < 8) {
83
+ Napi::TypeError::New(env,
84
+ "tensorOpComplexBinary(op, n, aRe, aIm|null, bRe, bIm|null, outRe, outIm)")
85
+ .ThrowAsJavaScriptException();
86
+ return env.Undefined();
87
+ }
88
+ int op = info[0].As<Napi::Number>().Int32Value();
89
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
90
+ int rc = numbl_complex_binary_elemwise(
91
+ op, n,
92
+ AsF64(info[2]), AsF64OrNull(info[3]),
93
+ AsF64(info[4]), AsF64OrNull(info[5]),
94
+ AsF64Mut(info[6]), AsF64Mut(info[7]));
95
+ ThrowOnError(env, rc, "tensorOpComplexBinary");
96
+ return env.Undefined();
97
+ }
98
+
99
+ Napi::Value TensorOpComplexScalarBinary(const Napi::CallbackInfo& info) {
100
+ Napi::Env env = info.Env();
101
+ if (info.Length() < 9) {
102
+ Napi::TypeError::New(env,
103
+ "tensorOpComplexScalarBinary(op, n, sRe, sIm, arrRe, arrIm|null, scalarOnLeft, outRe, outIm)")
104
+ .ThrowAsJavaScriptException();
105
+ return env.Undefined();
106
+ }
107
+ int op = info[0].As<Napi::Number>().Int32Value();
108
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
109
+ double s_re = info[2].As<Napi::Number>().DoubleValue();
110
+ double s_im = info[3].As<Napi::Number>().DoubleValue();
111
+ int scalar_on_left = info[6].As<Napi::Boolean>().Value() ? 1 : 0;
112
+ int rc = numbl_complex_scalar_binary_elemwise(
113
+ op, n, s_re, s_im,
114
+ AsF64(info[4]), AsF64OrNull(info[5]),
115
+ scalar_on_left,
116
+ AsF64Mut(info[7]), AsF64Mut(info[8]));
117
+ ThrowOnError(env, rc, "tensorOpComplexScalarBinary");
118
+ return env.Undefined();
119
+ }
120
+
121
+ Napi::Value TensorOpRealUnary(const Napi::CallbackInfo& info) {
122
+ Napi::Env env = info.Env();
123
+ if (info.Length() < 4) {
124
+ Napi::TypeError::New(env,
125
+ "tensorOpRealUnary(op, n, a, out)")
126
+ .ThrowAsJavaScriptException();
127
+ return env.Undefined();
128
+ }
129
+ int op = info[0].As<Napi::Number>().Int32Value();
130
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
131
+ int rc = numbl_real_unary_elemwise(op, n, AsF64(info[2]), AsF64Mut(info[3]));
132
+ ThrowOnError(env, rc, "tensorOpRealUnary");
133
+ return env.Undefined();
134
+ }
135
+
136
+ Napi::Value TensorOpComplexUnary(const Napi::CallbackInfo& info) {
137
+ Napi::Env env = info.Env();
138
+ if (info.Length() < 6) {
139
+ Napi::TypeError::New(env,
140
+ "tensorOpComplexUnary(op, n, aRe, aIm|null, outRe, outIm)")
141
+ .ThrowAsJavaScriptException();
142
+ return env.Undefined();
143
+ }
144
+ int op = info[0].As<Napi::Number>().Int32Value();
145
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
146
+ int rc = numbl_complex_unary_elemwise(
147
+ op, n,
148
+ AsF64(info[2]), AsF64OrNull(info[3]),
149
+ AsF64Mut(info[4]), AsF64Mut(info[5]));
150
+ ThrowOnError(env, rc, "tensorOpComplexUnary");
151
+ return env.Undefined();
152
+ }
153
+
154
+ Napi::Value TensorOpComplexAbs(const Napi::CallbackInfo& info) {
155
+ Napi::Env env = info.Env();
156
+ if (info.Length() < 4) {
157
+ Napi::TypeError::New(env,
158
+ "tensorOpComplexAbs(n, aRe, aIm|null, out)")
159
+ .ThrowAsJavaScriptException();
160
+ return env.Undefined();
161
+ }
162
+ size_t n = (size_t)info[0].As<Napi::Number>().Int64Value();
163
+ int rc = numbl_complex_abs(
164
+ n, AsF64(info[1]), AsF64OrNull(info[2]), AsF64Mut(info[3]));
165
+ ThrowOnError(env, rc, "tensorOpComplexAbs");
166
+ return env.Undefined();
167
+ }
168
+
169
+ Napi::Value TensorOpRealComparison(const Napi::CallbackInfo& info) {
170
+ Napi::Env env = info.Env();
171
+ if (info.Length() < 5) {
172
+ Napi::TypeError::New(env,
173
+ "tensorOpRealComparison(op, n, a, b, out)")
174
+ .ThrowAsJavaScriptException();
175
+ return env.Undefined();
176
+ }
177
+ int op = info[0].As<Napi::Number>().Int32Value();
178
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
179
+ int rc = numbl_real_comparison(
180
+ op, n, AsF64(info[2]), AsF64(info[3]), AsF64Mut(info[4]));
181
+ ThrowOnError(env, rc, "tensorOpRealComparison");
182
+ return env.Undefined();
183
+ }
184
+
185
+ Napi::Value TensorOpRealScalarComparison(const Napi::CallbackInfo& info) {
186
+ Napi::Env env = info.Env();
187
+ if (info.Length() < 6) {
188
+ Napi::TypeError::New(env,
189
+ "tensorOpRealScalarComparison(op, n, scalar, arr, scalarOnLeft, out)")
190
+ .ThrowAsJavaScriptException();
191
+ return env.Undefined();
192
+ }
193
+ int op = info[0].As<Napi::Number>().Int32Value();
194
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
195
+ double scalar = info[2].As<Napi::Number>().DoubleValue();
196
+ int scalar_on_left = info[4].As<Napi::Boolean>().Value() ? 1 : 0;
197
+ int rc = numbl_real_scalar_comparison(
198
+ op, n, scalar, AsF64(info[3]), scalar_on_left, AsF64Mut(info[5]));
199
+ ThrowOnError(env, rc, "tensorOpRealScalarComparison");
200
+ return env.Undefined();
201
+ }
202
+
203
+ Napi::Value TensorOpComplexComparison(const Napi::CallbackInfo& info) {
204
+ Napi::Env env = info.Env();
205
+ if (info.Length() < 7) {
206
+ Napi::TypeError::New(env,
207
+ "tensorOpComplexComparison(op, n, aRe, aIm|null, bRe, bIm|null, out)")
208
+ .ThrowAsJavaScriptException();
209
+ return env.Undefined();
210
+ }
211
+ int op = info[0].As<Napi::Number>().Int32Value();
212
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
213
+ int rc = numbl_complex_comparison(
214
+ op, n,
215
+ AsF64(info[2]), AsF64OrNull(info[3]),
216
+ AsF64(info[4]), AsF64OrNull(info[5]),
217
+ AsF64Mut(info[6]));
218
+ ThrowOnError(env, rc, "tensorOpComplexComparison");
219
+ return env.Undefined();
220
+ }
221
+
222
+ Napi::Value TensorOpComplexScalarComparison(const Napi::CallbackInfo& info) {
223
+ Napi::Env env = info.Env();
224
+ if (info.Length() < 8) {
225
+ Napi::TypeError::New(env,
226
+ "tensorOpComplexScalarComparison(op, n, sRe, sIm, arrRe, arrIm|null, scalarOnLeft, out)")
227
+ .ThrowAsJavaScriptException();
228
+ return env.Undefined();
229
+ }
230
+ int op = info[0].As<Napi::Number>().Int32Value();
231
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
232
+ double s_re = info[2].As<Napi::Number>().DoubleValue();
233
+ double s_im = info[3].As<Napi::Number>().DoubleValue();
234
+ int scalar_on_left = info[6].As<Napi::Boolean>().Value() ? 1 : 0;
235
+ int rc = numbl_complex_scalar_comparison(
236
+ op, n, s_re, s_im,
237
+ AsF64(info[4]), AsF64OrNull(info[5]),
238
+ scalar_on_left, AsF64Mut(info[7]));
239
+ ThrowOnError(env, rc, "tensorOpComplexScalarComparison");
240
+ return env.Undefined();
241
+ }
242
+
243
+ Napi::Value TensorOpRealFlatReduce(const Napi::CallbackInfo& info) {
244
+ Napi::Env env = info.Env();
245
+ if (info.Length() < 4) {
246
+ Napi::TypeError::New(env,
247
+ "tensorOpRealFlatReduce(op, n, a, out)")
248
+ .ThrowAsJavaScriptException();
249
+ return env.Undefined();
250
+ }
251
+ int op = info[0].As<Napi::Number>().Int32Value();
252
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
253
+ int rc = numbl_real_flat_reduce(op, n, AsF64(info[2]), AsF64Mut(info[3]));
254
+ ThrowOnError(env, rc, "tensorOpRealFlatReduce");
255
+ return env.Undefined();
256
+ }
257
+
258
+ Napi::Value TensorOpComplexFlatReduce(const Napi::CallbackInfo& info) {
259
+ Napi::Env env = info.Env();
260
+ if (info.Length() < 6) {
261
+ Napi::TypeError::New(env,
262
+ "tensorOpComplexFlatReduce(op, n, aRe, aIm|null, outRe, outIm|null)")
263
+ .ThrowAsJavaScriptException();
264
+ return env.Undefined();
265
+ }
266
+ int op = info[0].As<Napi::Number>().Int32Value();
267
+ size_t n = (size_t)info[1].As<Napi::Number>().Int64Value();
268
+ double* out_im = (info[5].IsNull() || info[5].IsUndefined())
269
+ ? nullptr
270
+ : AsF64Mut(info[5]);
271
+ int rc = numbl_complex_flat_reduce(
272
+ op, n,
273
+ AsF64(info[2]), AsF64OrNull(info[3]),
274
+ AsF64Mut(info[4]), out_im);
275
+ ThrowOnError(env, rc, "tensorOpComplexFlatReduce");
276
+ return env.Undefined();
277
+ }
278
+
279
+ Napi::Value TensorOpBesselReal(const Napi::CallbackInfo& info) {
280
+ Napi::Env env = info.Env();
281
+ if (info.Length() < 6) {
282
+ Napi::TypeError::New(env,
283
+ "tensorOpBesselReal(op, nu, n, z, scale, out)")
284
+ .ThrowAsJavaScriptException();
285
+ return env.Undefined();
286
+ }
287
+ int op = info[0].As<Napi::Number>().Int32Value();
288
+ double nu = info[1].As<Napi::Number>().DoubleValue();
289
+ size_t n = (size_t)info[2].As<Napi::Number>().Int64Value();
290
+ int scale = info[4].As<Napi::Number>().Int32Value();
291
+ int rc = numbl_bessel_real(op, nu, n, AsF64(info[3]), scale, AsF64Mut(info[5]));
292
+ ThrowOnError(env, rc, "tensorOpBesselReal");
293
+ return env.Undefined();
294
+ }
295
+
296
+ Napi::Value TensorOpBesselH(const Napi::CallbackInfo& info) {
297
+ Napi::Env env = info.Env();
298
+ if (info.Length() < 7) {
299
+ Napi::TypeError::New(env,
300
+ "tensorOpBesselH(kKind, nu, n, z, scale, outRe, outIm)")
301
+ .ThrowAsJavaScriptException();
302
+ return env.Undefined();
303
+ }
304
+ int k_kind = info[0].As<Napi::Number>().Int32Value();
305
+ double nu = info[1].As<Napi::Number>().DoubleValue();
306
+ size_t n = (size_t)info[2].As<Napi::Number>().Int64Value();
307
+ int scale = info[4].As<Napi::Number>().Int32Value();
308
+ int rc = numbl_bessel_h(k_kind, nu, n, AsF64(info[3]), scale,
309
+ AsF64Mut(info[5]), AsF64Mut(info[6]));
310
+ ThrowOnError(env, rc, "tensorOpBesselH");
311
+ return env.Undefined();
312
+ }
313
+
314
+ Napi::Value TensorOpDumpCodes(const Napi::CallbackInfo& info) {
315
+ Napi::Env env = info.Env();
316
+ size_t need = numbl_dump_op_codes(nullptr, 0);
317
+ std::string buf(need, '\0');
318
+ numbl_dump_op_codes(&buf[0], need + 1);
319
+ return Napi::String::New(env, buf);
320
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numbl",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
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",
@@ -38,15 +38,15 @@
38
38
  ],
39
39
  "scripts": {
40
40
  "dev": "npm run bundle:stdlib && vite",
41
- "build": "npm run build:web && npm run build:cli && npm run build:plot-viewer",
41
+ "build": "npm run build:web && npm run build:test-runner && npm run copy:test-scripts && npm run build:cli && npm run build:plot-viewer",
42
42
  "build:plot-viewer": "vite build --config vite.plot-viewer.config.ts",
43
+ "build:test-runner": "npm run bundle:stdlib && vite build --config vite.test-runner.config.ts",
44
+ "dev:test-runner": "npm run bundle:stdlib && vite --config vite.test-runner.config.ts",
45
+ "copy:test-scripts": "tsx scripts/copy-test-scripts.ts",
43
46
  "bundle:stdlib": "tsx scripts/bundle-stdlib.ts",
44
47
  "build:web": "npm run bundle:stdlib && tsc -b && vite build",
45
48
  "build:lib": "npm run bundle:stdlib && esbuild src/lib.ts --bundle --platform=neutral --format=esm --outfile=dist-lib/lib.js --loader:.wasm=file && tsc -p tsconfig.lib.json",
46
49
  "build:cli": "npm run bundle:stdlib && esbuild src/cli.ts --bundle --platform=node --format=esm --outfile=dist-cli/cli.js --packages=external --loader:.wasm=file",
47
- "build:server": "esbuild server/execution-service.ts --bundle --platform=node --format=esm --outfile=server/dist/execution-service.js --packages=external",
48
- "server:dev": "node --env-file=server/.env node_modules/.bin/tsx server/execution-service.ts",
49
- "server:start": "node --env-file=server/.env server/dist/execution-service.js",
50
50
  "install": "true",
51
51
  "build:addon": "node-gyp rebuild",
52
52
  "format": "prettier --write .",
@@ -60,10 +60,14 @@
60
60
  "test:coverage": "vitest run --coverage",
61
61
  "test:coverage:all": "bash scripts/coverage-all.sh",
62
62
  "test:scripts": "bash numbl_test_scripts/run_all.sh",
63
- "test:jit": "tsx src/cli.ts run-tests numbl_test_scripts/jit --opt 1",
63
+ "test:browser": "playwright test",
64
+ "test:scripts:c-jit": "bash numbl_test_scripts/run_c_jit.sh",
65
+ "test:scripts:c-jit-fuse": "bash numbl_test_scripts/run_c_jit_fuse.sh",
66
+ "test:scripts:c-jit-parity": "bash numbl_test_scripts/run_c_jit_parity.sh",
64
67
  "build:wasm": "bash numbl_test_scripts/build_wasm.sh",
65
68
  "update-readme": "tsx scripts/update-readme-usage.ts",
66
69
  "check-readme": "tsx scripts/update-readme-usage.ts --check",
70
+ "bump": "tsx scripts/bump-version.ts",
67
71
  "prepublishOnly": "npm run build:lib && npm run build:cli && npm run build:plot-viewer",
68
72
  "prepare": "husky"
69
73
  },
@@ -83,8 +87,7 @@
83
87
  "@monaco-editor/react": "^4.7.0",
84
88
  "@mui/icons-material": "^7.3.7",
85
89
  "@mui/material": "^7.3.7",
86
- "@types/cors": "^2.8.17",
87
- "@types/express": "^5.0.0",
90
+ "@playwright/test": "^1.59.1",
88
91
  "@types/node": "^24.10.1",
89
92
  "@types/pako": "^2.0.4",
90
93
  "@types/react": "^19.2.5",
@@ -95,14 +98,12 @@
95
98
  "@vitest/coverage-v8": "^4.0.18",
96
99
  "@xterm/addon-fit": "^0.11.0",
97
100
  "@xterm/xterm": "^6.0.0",
98
- "cors": "^2.8.5",
99
101
  "dexie": "^4.3.0",
100
102
  "esbuild": "^0.27.3",
101
103
  "eslint": "^9.39.1",
102
104
  "eslint-config-prettier": "^10.1.8",
103
105
  "eslint-plugin-react-hooks": "^7.0.1",
104
106
  "eslint-plugin-react-refresh": "^0.4.24",
105
- "express": "^4.21.2",
106
107
  "globals": "^16.5.0",
107
108
  "husky": "^9.1.7",
108
109
  "lint-staged": "^16.2.7",
@@ -1,5 +0,0 @@
1
- /**
2
- * JIT IR -> JavaScript code generation.
3
- */
4
- import { type JitStmt } from "./jitTypes.js";
5
- export declare function generateJS(body: JitStmt[], params: string[], outputs: string[], nargout: number, localVars: Set<string>, fileName?: string): string;
@@ -1,14 +0,0 @@
1
- /**
2
- * Runtime helpers for JIT-compiled tensor and complex operations.
3
- * Passed as `$h` to generated functions.
4
- */
5
- export declare const jitHelpers: Record<string, unknown>;
6
- import type { IBuiltin } from "../builtins/index.js";
7
- /**
8
- * Build a per-runtime jitHelpers map for an execution that has .numbl.js
9
- * user functions. The result is a clone of the global jitHelpers extended
10
- * with `ib_<name>` entries (single-output fast path) for each js user
11
- * function and an overridden `ibcall` (multi-output) that consults the
12
- * js user function map first before falling back to the global registry.
13
- */
14
- export declare function buildPerRuntimeJitHelpers(jsUserFunctions: ReadonlyMap<string, IBuiltin>): Record<string, any>;
@@ -1,20 +0,0 @@
1
- /**
2
- * AST -> JIT IR lowering with type propagation.
3
- *
4
- * Returns null if any unsupported construct is encountered,
5
- * causing the entire function to fall back to interpretation.
6
- */
7
- import type { FunctionDef } from "../types.js";
8
- import type { Interpreter } from "../interpreter.js";
9
- import { type JitType, type JitStmt } from "./jitTypes.js";
10
- export interface LoweringResult {
11
- body: JitStmt[];
12
- outputNames: string[];
13
- localVars: Set<string>;
14
- hasTensorOps: boolean;
15
- /** Generated JS code for called user functions: jitName → code */
16
- generatedFns: Map<string, string>;
17
- /** Type of the first output variable after lowering */
18
- outputType: JitType | null;
19
- }
20
- export declare function lowerFunction(fn: FunctionDef, argTypes: JitType[], nargout: number, interp?: Interpreter, generatedFns?: Map<string, string>, loweringInProgress?: Set<string>): LoweringResult | null;
@@ -1,168 +0,0 @@
1
- /**
2
- * JIT type system and IR node definitions.
3
- */
4
- import type { BinaryOperation, UnaryOperation } from "../../parser/types.js";
5
- export type SignCategory = "positive" | "nonneg" | "nonpositive" | "negative";
6
- export type JitType = {
7
- kind: "number";
8
- exact?: number;
9
- sign?: SignCategory;
10
- } | {
11
- kind: "boolean";
12
- value?: boolean;
13
- } | {
14
- kind: "complex_or_number";
15
- pureImaginary?: boolean;
16
- } | {
17
- kind: "tensor";
18
- isComplex: boolean;
19
- shape?: number[];
20
- ndim?: number;
21
- isLogical?: boolean;
22
- nonneg?: boolean;
23
- } | {
24
- kind: "string";
25
- value?: string;
26
- } | {
27
- kind: "char";
28
- value?: string;
29
- } | {
30
- kind: "struct";
31
- fields?: Record<string, JitType>;
32
- } | {
33
- kind: "class_instance";
34
- className: string;
35
- isHandleClass?: boolean;
36
- fields?: Record<string, JitType>;
37
- } | {
38
- kind: "sparse_matrix";
39
- isComplex: boolean;
40
- m?: number;
41
- n?: number;
42
- } | {
43
- kind: "cell";
44
- shape?: number[];
45
- } | {
46
- kind: "dictionary";
47
- } | {
48
- kind: "unknown";
49
- };
50
- export declare function signFromNumber(v: number): SignCategory | undefined;
51
- export declare function isNonneg(t: JitType): boolean;
52
- export declare function flipSign(s?: SignCategory): SignCategory | undefined;
53
- export declare function unifySign(a?: SignCategory, b?: SignCategory): SignCategory | undefined;
54
- export declare function jitTypeKey(t: JitType): string;
55
- export declare function computeJitCacheKey(nargout: number, argTypes: JitType[]): string;
56
- /** Compute a unique JS function name for a JIT'd specialization. */
57
- export declare function computeJitFnName(identity: string, funcName: string): string;
58
- /** Widen/unify two types at control-flow join points. */
59
- export declare function unifyJitTypes(a: JitType, b: JitType): JitType;
60
- export declare function isScalarType(t: JitType): boolean;
61
- export declare function isNumericScalarType(t: JitType): boolean;
62
- export declare function isTensorType(t: JitType): boolean;
63
- export declare function isComplexType(t: JitType): boolean;
64
- /** Types that support arithmetic binary operations in the JIT. */
65
- export declare function isArithmeticType(t: JitType): boolean;
66
- export declare function shapeAfterReduction(shape: number[], dim?: number): {
67
- scalar: true;
68
- } | {
69
- scalar: false;
70
- shape: number[];
71
- };
72
- export type JitExpr = {
73
- tag: "NumberLiteral";
74
- value: number;
75
- jitType: JitType;
76
- } | {
77
- tag: "ImagLiteral";
78
- jitType: JitType;
79
- } | {
80
- tag: "Var";
81
- name: string;
82
- jitType: JitType;
83
- } | {
84
- tag: "Binary";
85
- op: BinaryOperation;
86
- left: JitExpr;
87
- right: JitExpr;
88
- jitType: JitType;
89
- } | {
90
- tag: "Unary";
91
- op: UnaryOperation;
92
- operand: JitExpr;
93
- jitType: JitType;
94
- } | {
95
- tag: "StringLiteral";
96
- value: string;
97
- isChar: boolean;
98
- jitType: JitType;
99
- } | {
100
- tag: "Call";
101
- name: string;
102
- args: JitExpr[];
103
- jitType: JitType;
104
- } | {
105
- tag: "UserCall";
106
- jitName: string;
107
- name: string;
108
- args: JitExpr[];
109
- jitType: JitType;
110
- } | {
111
- tag: "Index";
112
- base: JitExpr;
113
- indices: JitExpr[];
114
- jitType: JitType;
115
- } | {
116
- tag: "TensorLiteral";
117
- rows: JitExpr[][];
118
- nRows: number;
119
- nCols: number;
120
- jitType: JitType;
121
- };
122
- export type JitStmt = {
123
- tag: "Assign";
124
- name: string;
125
- expr: JitExpr;
126
- } | {
127
- tag: "If";
128
- cond: JitExpr;
129
- thenBody: JitStmt[];
130
- elseifBlocks: {
131
- cond: JitExpr;
132
- body: JitStmt[];
133
- }[];
134
- elseBody: JitStmt[] | null;
135
- } | {
136
- tag: "For";
137
- varName: string;
138
- start: JitExpr;
139
- step: JitExpr | null;
140
- end: JitExpr;
141
- body: JitStmt[];
142
- } | {
143
- tag: "While";
144
- cond: JitExpr;
145
- body: JitStmt[];
146
- } | {
147
- tag: "Break";
148
- } | {
149
- tag: "Continue";
150
- } | {
151
- tag: "Return";
152
- } | {
153
- tag: "ExprStmt";
154
- expr: JitExpr;
155
- } | {
156
- tag: "MultiAssign";
157
- names: (string | null)[];
158
- callName: string;
159
- args: JitExpr[];
160
- outputTypes: JitType[];
161
- } | {
162
- tag: "SetLoc";
163
- line: number;
164
- };
165
- export interface JitCacheEntry {
166
- fn: (...args: unknown[]) => unknown;
167
- source: string;
168
- }