wgblas 0.1.2 → 1.1.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 (64) hide show
  1. package/README.md +3 -0
  2. package/dist/wgblas.browser.js +1249 -37
  3. package/index.d.mts +9 -0
  4. package/index.mjs +9 -0
  5. package/package.json +47 -1
  6. package/src/classes/GpuMatrix.d.mts +98 -0
  7. package/src/classes/GpuMatrix.mjs +109 -0
  8. package/src/classes/GpuVector.d.mts +11 -7
  9. package/src/classes/GpuVector.mjs +31 -5
  10. package/src/dasum/dasum.d.mts +48 -0
  11. package/src/dasum/dasum.mjs +121 -0
  12. package/src/init.mjs +3 -1
  13. package/src/isamax/isamax.mjs +66 -67
  14. package/src/random/random.d.mts +37 -0
  15. package/src/random/random.mjs +17 -0
  16. package/src/sasum/sasum.mjs +55 -51
  17. package/src/saxpy/saxpy.mjs +48 -35
  18. package/src/scopy/scopy.mjs +43 -32
  19. package/src/sdot/sdot.mjs +60 -55
  20. package/src/sgemv/sgemv.d.mts +127 -0
  21. package/src/sgemv/sgemv.mjs +148 -0
  22. package/src/sger/sger.d.mts +111 -0
  23. package/src/sger/sger.mjs +136 -0
  24. package/src/shaders/browser-shaders.mjs +26 -0
  25. package/src/shaders/dasum.wgsl +98 -0
  26. package/src/shaders/f64add.wgsl +281 -0
  27. package/src/shaders/isamax.wgsl +32 -9
  28. package/src/shaders/reduction/sumF64.wgsl +49 -0
  29. package/src/shaders/sasum.wgsl +18 -4
  30. package/src/shaders/sdot.wgsl +18 -4
  31. package/src/shaders/sgemv_n.wgsl +75 -0
  32. package/src/shaders/sgemv_t.wgsl +65 -0
  33. package/src/shaders/sger.wgsl +48 -0
  34. package/src/shaders/snrm2.wgsl +22 -4
  35. package/src/shaders/ssymv.wgsl +69 -0
  36. package/src/shaders/ssyr.wgsl +60 -0
  37. package/src/shaders/ssyr2.wgsl +63 -0
  38. package/src/shaders/strmv.wgsl +103 -0
  39. package/src/shaders/strsv_apply_inverse.wgsl +47 -0
  40. package/src/shaders/strsv_invert_block.wgsl +109 -0
  41. package/src/shaders/strsv_update.wgsl +75 -0
  42. package/src/snrm2/snrm2.mjs +56 -52
  43. package/src/srot/srot.mjs +57 -41
  44. package/src/srotm/srotm.mjs +54 -38
  45. package/src/sscal/sscal.mjs +43 -32
  46. package/src/sswap/sswap.mjs +49 -34
  47. package/src/ssymv/ssymv.d.mts +117 -0
  48. package/src/ssymv/ssymv.mjs +135 -0
  49. package/src/ssyr/ssyr.d.mts +100 -0
  50. package/src/ssyr/ssyr.mjs +106 -0
  51. package/src/ssyr2/ssyr2.d.mts +112 -0
  52. package/src/ssyr2/ssyr2.mjs +130 -0
  53. package/src/strmv/strmv.d.mts +117 -0
  54. package/src/strmv/strmv.mjs +138 -0
  55. package/src/strsv/strsv.d.mts +106 -0
  56. package/src/strsv/strsv.mjs +207 -0
  57. package/src/util/benchmark.mjs +1 -1
  58. package/src/util/bindgroup.mjs +14 -10
  59. package/src/util/buffer.mjs +7 -2
  60. package/src/util/compute.mjs +41 -15
  61. package/src/util/f64pack.mjs +152 -0
  62. package/src/util/pipeline.mjs +32 -17
  63. package/src/util/result.mjs +8 -4
  64. package/src/util/workgroup.mjs +10 -10
@@ -1,4 +1,4 @@
1
- var wgblas=(()=>{var jr=Object.create;var L=Object.defineProperty;var Qr=Object.getOwnPropertyDescriptor;var Xr=Object.getOwnPropertyNames;var Hr=Object.getPrototypeOf,Kr=Object.prototype.hasOwnProperty;var q=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,e)=>(typeof require<"u"?require:r)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var I=(t,r,e)=>()=>{if(e)throw e[0];try{return t&&(r=t(t=0)),r}catch(a){throw e=[a],a}};var X=(t,r)=>{for(var e in r)L(t,e,{get:r[e],enumerable:!0})},H=(t,r,e,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of Xr(r))!Kr.call(t,o)&&o!==e&&L(t,o,{get:()=>r[o],enumerable:!(a=Qr(r,o))||a.enumerable});return t};var Y=(t,r,e)=>(e=t!=null?jr(Hr(t)):{},H(r||!t||!t.__esModule?L(e,"default",{value:t,enumerable:!0}):e,t)),Zr=t=>H(L({},"__esModule",{value:!0}),t);var ur,sr=I(()=>{ur=`// amax reduction: collapses 2*WGS (value, index) pairs into one index.
1
+ var wgblas=(()=>{var ct=Object.create;var ur=Object.defineProperty;var mt=Object.getOwnPropertyDescriptor;var dt=Object.getOwnPropertyNames;var pt=Object.getPrototypeOf,gt=Object.prototype.hasOwnProperty;var lr=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(r,e)=>(typeof require<"u"?require:r)[e]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});var I=(a,r,e)=>()=>{if(e)throw e[0];try{return a&&(r=a(a=0)),r}catch(o){throw e=[o],o}};var yr=(a,r)=>{for(var e in r)ur(a,e,{get:r[e],enumerable:!0})},_r=(a,r,e,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let t of dt(r))!gt.call(a,t)&&t!==e&&ur(a,t,{get:()=>r[t],enumerable:!(o=mt(r,t))||o.enumerable});return a};var fr=(a,r,e)=>(e=a!=null?ct(pt(a)):{},_r(r||!a||!a.__esModule?ur(e,"default",{value:a,enumerable:!0}):e,a)),wt=a=>_r(ur({},"__esModule",{value:!0}),a);var Mr,Ir=I(()=>{Mr=`// amax reduction: collapses 2*WGS (value, index) pairs into one index.
2
2
  // dispatch: 1 workgroup of WGS threads.
3
3
  // partials_val and partials_idx must have exactly 2*WGS entries.
4
4
 
@@ -41,7 +41,7 @@ fn reduce(
41
41
 
42
42
  if (i == 0u) { result[0] = tile_idx[0]; }
43
43
  }
44
- `});var cr,fr=I(()=>{cr=`// sum reduction: collapses 2*WGS partials into one scalar.
44
+ `});var Tr,Ur=I(()=>{Tr=`// sum reduction: collapses 2*WGS partials into one scalar.
45
45
  // dispatch: 1 workgroup of WGS threads.
46
46
  // partials must have exactly 2*WGS entries.
47
47
 
@@ -67,7 +67,56 @@ fn reduce(
67
67
 
68
68
  if (i == 0u) { result[0] = tile[0]; }
69
69
  }
70
- `});var mr,pr=I(()=>{mr=`// sscal: x = alpha * x
70
+ `});var Rr,Vr=I(()=>{Rr=`// sum reduction (f64): collapses 2*WGS partial [main, aux] pairs into one,
71
+ // using computeSum instead of plain f32 \`+\` (see reduction/sum.wgsl for the
72
+ // f32 original this mirrors).
73
+ // dispatch: 1 workgroup of WGS threads. partialsMain/partialsAux must have
74
+ // exactly 2*WGS entries each.
75
+ //
76
+ // Concatenated after f64add.wgsl by getPipeline (WGSL has no #include),
77
+ // reusing its decode/encode/computeSum and Packed struct \u2014 f64add.wgsl
78
+ // declares no bindings and no entry point of its own (just helper functions),
79
+ // so bindings here start at 0 and the entry point is simply \`reduce_f64\`.
80
+ //
81
+ // partialsAux/result's aux slot are array<u32>, not array<f32> \u2014 aux's bits
82
+ // must never pass through an f32-typed storage slot (NaN-bit-pattern
83
+ // corruption risk, see f64pack.mjs and the Packed struct comment above
84
+ // decode()/encode() in f64add.wgsl).
85
+
86
+ @group(0) @binding(0) var<storage, read> partialsMain: array<f32>;
87
+ @group(0) @binding(1) var<storage, read> partialsAux: array<u32>;
88
+ @group(0) @binding(2) var<storage, read_write> resultMain: array<f32, 1>;
89
+ @group(0) @binding(3) var<storage, read_write> resultAux: array<u32, 1>;
90
+
91
+ const WGS: u32 = 64;
92
+
93
+ var<workgroup> tile: array<Packed, 64>;
94
+
95
+ fn addPair(a: Packed, b: Packed) -> Packed {
96
+ return computeSum(decode(bitcast<u32>(a.main), a.aux), decode(bitcast<u32>(b.main), b.aux));
97
+ }
98
+
99
+ @compute @workgroup_size(64)
100
+ fn reduce_f64(
101
+ @builtin(local_invocation_id) lid: vec3u,
102
+ ) {
103
+ let i = lid.x;
104
+ let a = Packed(partialsMain[i], partialsAux[i]);
105
+ let b = Packed(partialsMain[i + WGS], partialsAux[i + WGS]);
106
+ tile[i] = addPair(a, b);
107
+ workgroupBarrier();
108
+
109
+ for (var s = WGS / 2u; s > 0u; s >>= 1u) {
110
+ if (i < s) { tile[i] = addPair(tile[i], tile[i + s]); }
111
+ workgroupBarrier();
112
+ }
113
+
114
+ if (i == 0u) {
115
+ resultMain[0] = tile[0].main;
116
+ resultAux[0] = tile[0].aux;
117
+ }
118
+ }
119
+ `});var Dr,Hr=I(()=>{Dr=`// sscal: x = alpha * x
71
120
 
72
121
  @group(0) @binding(0) var<storage, read_write> x: array<f32>;
73
122
 
@@ -90,7 +139,7 @@ fn main(
90
139
  x[id * params.x_inc] = params.alpha * x[id * params.x_inc];
91
140
  }
92
141
  }
93
- `});var dr,lr=I(()=>{dr=`// sswap: x <-> y
142
+ `});var Or,Cr=I(()=>{Or=`// sswap: x <-> y
94
143
 
95
144
  @group(0) @binding(0) var<storage, read_write> x: array<f32>;
96
145
  @group(0) @binding(1) var<storage, read_write> y: array<f32>;
@@ -116,7 +165,7 @@ fn main(
116
165
  y[id * params.y_inc] = temp;
117
166
  }
118
167
  }
119
- `});var wr,gr=I(()=>{wr=`// saxpy: y = alpha * x + y
168
+ `});var Qr,zr=I(()=>{Qr=`// saxpy: y = alpha * x + y
120
169
 
121
170
  @group(0) @binding(0) var<storage, read> x: array<f32>;
122
171
  @group(0) @binding(1) var<storage, read_write> y: array<f32>;
@@ -141,7 +190,7 @@ fn main(
141
190
  y[id * params.y_inc] = params.alpha * x[id * params.x_inc] + y[id * params.y_inc];
142
191
  }
143
192
  }
144
- `});var vr,yr=I(()=>{vr=`// scopy: y = x
193
+ `});var Zr,qr=I(()=>{Zr=`// scopy: y = x
145
194
 
146
195
  @group(0) @binding(0) var<storage, read> x: array<f32>;
147
196
  @group(0) @binding(1) var<storage, read_write> y: array<f32>;
@@ -165,7 +214,7 @@ fn main(
165
214
  y[id * params.y_inc] = x[id * params.x_inc];
166
215
  }
167
216
  }
168
- `});var xr,br=I(()=>{xr=`// sdot: result = sum(x[i] * y[i])
217
+ `});var Xr,Kr=I(()=>{Xr=`// sdot: result = sum(x[i] * y[i])
169
218
  // pass 1 dispatches exactly 2 * WGS workgroups; pass 2 uses reduction/sum.wgsl.
170
219
 
171
220
  @group(0) @binding(0) var<storage, read> x: array<f32>;
@@ -190,11 +239,25 @@ fn main(
190
239
  @builtin(workgroup_id) wgid: vec3u,
191
240
  @builtin(num_workgroups) num_wg: vec3u,
192
241
  ) {
193
- var acc: f32 = 0.0;
194
- for (var id = gid.x; id < params.n; id += num_wg.x * WGS) {
195
- acc += x[id * params.x_inc] * y[id * params.y_inc];
242
+ var acc0: f32 = 0.0;
243
+ var acc1: f32 = 0.0;
244
+ var acc2: f32 = 0.0;
245
+ var acc3: f32 = 0.0;
246
+
247
+ let stride = num_wg.x * WGS;
248
+ let n4_floor = (params.n / (4u * stride)) * (4u * stride);
249
+
250
+ for (var id = gid.x; id < n4_floor; id += 4u * stride) {
251
+ acc0 += x[ id * params.x_inc] * y[ id * params.y_inc];
252
+ acc1 += x[(id + stride) * params.x_inc] * y[(id + stride) * params.y_inc];
253
+ acc2 += x[(id + 2u * stride) * params.x_inc] * y[(id + 2u * stride) * params.y_inc];
254
+ acc3 += x[(id + 3u * stride) * params.x_inc] * y[(id + 3u * stride) * params.y_inc];
255
+ }
256
+ for (var id = n4_floor + gid.x; id < params.n; id += stride) {
257
+ acc0 += x[id * params.x_inc] * y[id * params.y_inc];
196
258
  }
197
- tile[lid.x] = acc;
259
+
260
+ tile[lid.x] = acc0 + acc1 + acc2 + acc3;
198
261
  workgroupBarrier();
199
262
 
200
263
  for (var s = WGS / 2u; s > 0u; s >>= 1u) {
@@ -204,7 +267,7 @@ fn main(
204
267
 
205
268
  if (lid.x == 0u) { partials[wgid.x] = tile[0]; }
206
269
  }
207
- `});var _r,hr=I(()=>{_r=`// sasum: result = sum(|x[i]|)
270
+ `});var Yr,$r=I(()=>{Yr=`// sasum: result = sum(|x[i]|)
208
271
  // pass 1 dispatches exactly 2 * WGS workgroups; pass 2 uses reduction/abssum.wgsl.
209
272
 
210
273
  @group(0) @binding(0) var<storage, read> x: array<f32>;
@@ -227,11 +290,25 @@ fn main(
227
290
  @builtin(workgroup_id) wgid: vec3u,
228
291
  @builtin(num_workgroups) num_wg: vec3u,
229
292
  ) {
230
- var acc: f32 = 0.0;
231
- for (var id = gid.x; id < params.n; id += num_wg.x * WGS) {
232
- acc += abs(x[id * params.x_inc]);
293
+ var acc0: f32 = 0.0;
294
+ var acc1: f32 = 0.0;
295
+ var acc2: f32 = 0.0;
296
+ var acc3: f32 = 0.0;
297
+
298
+ let stride = num_wg.x * WGS;
299
+ let n4_floor = (params.n / (4u * stride)) * (4u * stride);
300
+
301
+ for (var id = gid.x; id < n4_floor; id += 4u * stride) {
302
+ acc0 += abs(x[ id * params.x_inc]);
303
+ acc1 += abs(x[(id + stride) * params.x_inc]);
304
+ acc2 += abs(x[(id + 2u * stride) * params.x_inc]);
305
+ acc3 += abs(x[(id + 3u * stride) * params.x_inc]);
306
+ }
307
+ for (var id = n4_floor + gid.x; id < params.n; id += stride) {
308
+ acc0 += abs(x[id * params.x_inc]);
233
309
  }
234
- tile[lid.x] = acc;
310
+
311
+ tile[lid.x] = acc0 + acc1 + acc2 + acc3;
235
312
  workgroupBarrier();
236
313
 
237
314
  for (var s = WGS / 2u; s > 0u; s >>= 1u) {
@@ -241,7 +318,7 @@ fn main(
241
318
 
242
319
  if (lid.x == 0u) { partials[wgid.x] = tile[0]; }
243
320
  }
244
- `});var Br,Gr=I(()=>{Br=`// snrm2: result = sqrt(sum(x[i] * x[i]))
321
+ `});var re,Jr=I(()=>{re=`// snrm2: result = sqrt(sum(x[i] * x[i]))
245
322
  // pass 1 dispatches exactly 2 * WGS workgroups; pass 2 uses reduction/sqsum.wgsl.
246
323
 
247
324
  @group(0) @binding(0) var<storage, read> x: array<f32>;
@@ -264,12 +341,30 @@ fn main(
264
341
  @builtin(workgroup_id) wgid: vec3u,
265
342
  @builtin(num_workgroups) num_wg: vec3u,
266
343
  ) {
267
- var acc: f32 = 0.0;
268
- for (var id = gid.x; id < params.n; id += num_wg.x * WGS) {
344
+ var acc0: f32 = 0.0;
345
+ var acc1: f32 = 0.0;
346
+ var acc2: f32 = 0.0;
347
+ var acc3: f32 = 0.0;
348
+
349
+ let stride = num_wg.x * WGS;
350
+ let n4_floor = (params.n / (4u * stride)) * (4u * stride);
351
+
352
+ for (var id = gid.x; id < n4_floor; id += 4u * stride) {
353
+ let v0 = x[ id * params.x_inc];
354
+ let v1 = x[(id + stride) * params.x_inc];
355
+ let v2 = x[(id + 2u * stride) * params.x_inc];
356
+ let v3 = x[(id + 3u * stride) * params.x_inc];
357
+ acc0 += v0 * v0;
358
+ acc1 += v1 * v1;
359
+ acc2 += v2 * v2;
360
+ acc3 += v3 * v3;
361
+ }
362
+ for (var id = n4_floor + gid.x; id < params.n; id += stride) {
269
363
  let v = x[id * params.x_inc];
270
- acc += v * v;
364
+ acc0 += v * v;
271
365
  }
272
- tile[lid.x] = acc;
366
+
367
+ tile[lid.x] = acc0 + acc1 + acc2 + acc3;
273
368
  workgroupBarrier();
274
369
 
275
370
  for (var s = WGS / 2u; s > 0u; s >>= 1u) {
@@ -279,7 +374,7 @@ fn main(
279
374
 
280
375
  if (lid.x == 0u) { partials[wgid.x] = tile[0]; }
281
376
  }
282
- `});var Pr,Er=I(()=>{Pr=`// srot: x = c*x + s*y, y = -s*x + c*y
377
+ `});var te,ee=I(()=>{te=`// srot: x = c*x + s*y, y = -s*x + c*y
283
378
 
284
379
  @group(0) @binding(0) var<storage, read_write> x: array<f32>;
285
380
  @group(0) @binding(1) var<storage, read_write> y: array<f32>;
@@ -308,7 +403,7 @@ fn main(
308
403
  y[id * params.y_inc] = -params.s * xi + params.c * yi;
309
404
  }
310
405
  }
311
- `});var kr,Ar=I(()=>{kr=`// srotm: applies modified Givens rotation H to vectors x and y.
406
+ `});var oe,ae=I(()=>{oe=`// srotm: applies modified Givens rotation H to vectors x and y.
312
407
  // param[0] = flag: -1 (full H), 0 (unit diagonal), 1 (unit off-diagonal)
313
408
  // param = [ flag, h11, h21, h12, h22 ]
314
409
  // flag == -2 (identity/no-op) is handled in JS before dispatch reaches here.
@@ -358,7 +453,7 @@ fn main(
358
453
  y[id * params.y_inc] = h21 * xi + h22 * yi;
359
454
  }
360
455
  }
361
- `});var Fr,Sr=I(()=>{Fr=`// isamax: returns index of element with largest absolute value
456
+ `});var ne,ie=I(()=>{ne=`// isamax: returns index of element with largest absolute value
362
457
  // pass 1 dispatches exactly 2 * WGS workgroups; pass 2 uses reduction/argmax.wgsl.
363
458
 
364
459
  @group(0) @binding(0) var<storage, read> x: array<f32>;
@@ -385,19 +480,42 @@ fn main(
385
480
  ) {
386
481
  // -1.0 is a safe sentinel: any |x[i]| >= 0 beats it,
387
482
  // so workgroups with no elements lose gracefully in the epilogue.
388
- var best_val: f32 = -1.0;
389
- var best_idx: u32 = 0u;
390
-
391
- for (var id = gid.x; id < params.n; id += num_wg.x * WGS) {
483
+ var best_val0: f32 = -1.0; var best_idx0: u32 = 0u;
484
+ var best_val1: f32 = -1.0; var best_idx1: u32 = 0u;
485
+ var best_val2: f32 = -1.0; var best_idx2: u32 = 0u;
486
+ var best_val3: f32 = -1.0; var best_idx3: u32 = 0u;
487
+
488
+ let stride = num_wg.x * WGS;
489
+ let n4_floor = (params.n / (4u * stride)) * (4u * stride);
490
+
491
+ for (var id = gid.x; id < n4_floor; id += 4u * stride) {
492
+ let v0 = abs(x[ id * params.x_inc]);
493
+ let v1 = abs(x[(id + stride) * params.x_inc]);
494
+ let v2 = abs(x[(id + 2u * stride) * params.x_inc]);
495
+ let v3 = abs(x[(id + 3u * stride) * params.x_inc]);
496
+ if (v0 > best_val0) { best_val0 = v0; best_idx0 = id; }
497
+ if (v1 > best_val1) { best_val1 = v1; best_idx1 = id + stride; }
498
+ if (v2 > best_val2) { best_val2 = v2; best_idx2 = id + 2u * stride; }
499
+ if (v3 > best_val3) { best_val3 = v3; best_idx3 = id + 3u * stride; }
500
+ }
501
+ for (var id = n4_floor + gid.x; id < params.n; id += stride) {
392
502
  let v = abs(x[id * params.x_inc]);
393
- if (v > best_val) {
394
- best_val = v;
395
- best_idx = id;
396
- }
503
+ if (v > best_val0) { best_val0 = v; best_idx0 = id; }
504
+ }
505
+
506
+ // merge 4 independent lanes; prefer lower index on tie (first occurrence wins)
507
+ if (best_val1 > best_val0 || (best_val1 == best_val0 && best_idx1 < best_idx0)) {
508
+ best_val0 = best_val1; best_idx0 = best_idx1;
509
+ }
510
+ if (best_val2 > best_val0 || (best_val2 == best_val0 && best_idx2 < best_idx0)) {
511
+ best_val0 = best_val2; best_idx0 = best_idx2;
512
+ }
513
+ if (best_val3 > best_val0 || (best_val3 == best_val0 && best_idx3 < best_idx0)) {
514
+ best_val0 = best_val3; best_idx0 = best_idx3;
397
515
  }
398
516
 
399
- tile_val[lid.x] = best_val;
400
- tile_idx[lid.x] = best_idx;
517
+ tile_val[lid.x] = best_val0;
518
+ tile_idx[lid.x] = best_idx0;
401
519
  workgroupBarrier();
402
520
 
403
521
  for (var s = WGS / 2u; s > 0u; s >>= 1u) {
@@ -417,6 +535,1100 @@ fn main(
417
535
  partials_idx[wgid.x] = tile_idx[0];
418
536
  }
419
537
  }
420
- `});var Rr={};X(Rr,{shaderSources:()=>pe});var pe,Wr=I(()=>{sr();fr();pr();lr();gr();yr();br();hr();Gr();Er();Ar();Sr();pe={"reduction/argmax":ur,"reduction/sum":cr,sscal:mr,sswap:dr,saxpy:wr,scopy:vr,sdot:xr,sasum:_r,snrm2:Br,srot:Pr,srotm:kr,isamax:Fr}});var we={};X(we,{GpuVector:()=>m,cleanup:()=>ar,gpuName:()=>or,init:()=>tr,isamax:()=>qr,randomFloat32Array:()=>ir,randomFloat64Array:()=>nr,sasum:()=>zr,saxpy:()=>Tr,scopy:()=>Dr,sdot:()=>Vr,snrm2:()=>Lr,srot:()=>Yr,srotm:()=>$r,sscal:()=>Ir,sswap:()=>Mr});function K(t,r){return r?t.features.has("timestamp-query")?{requiredFeatures:["timestamp-query"]}:(console.warn("timestamp-query not supported on this device \u2014 benchmark mode disabled."),{}):{}}function Z(){if(!rr())return{querySet:null,passDescriptor:void 0};let r=F().createQuerySet({type:"timestamp",count:2});return{querySet:r,passDescriptor:{timestampWrites:{querySet:r,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}}}}function J(t,r){if(!r)return null;let e=F(),a=e.createBuffer({label:"timestamp-resolve",size:16,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC});t.resolveQuerySet(r,0,2,a,0);let o=e.createBuffer({label:"timestamp-readback",size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});return t.copyBufferToBuffer(a,0,o,0,16),{tsReadBuffer:o,resolveBuffer:a,querySet:r}}async function G(t){if(!t)return;let{tsReadBuffer:r,resolveBuffer:e,querySet:a}=t;await r.mapAsync(GPUMapMode.READ);let o=new BigInt64Array(r.getMappedRange().slice());return r.unmap(),r.destroy(),e.destroy(),a.destroy(),Number(o[1]-o[0])/1e6}var T=null,C=null,er=null,$=!1;async function tr({powerPreference:t="high-performance",benchmark:r=!1}={}){if(T)return T;let e;if(typeof window>"u"){let{create:a,globals:o}=await import("webgpu");Object.assign(globalThis,o),e=a([]),er=e}else e=navigator.gpu;if(!e)throw new Error("WebGPU not supported in this environment.");if(C=await e.requestAdapter({powerPreference:t})??await e.requestAdapter(),!C)throw new Error("No WebGPU adapter found.");return $=r,T=await C.requestDevice(K(C,r)),T.addEventListener("uncapturederror",a=>{console.error("Uncaptured GPU error:",a.error.message)}),T}function ar(){T&&(T.destroy(),T=null),C=null,er=null,$=!1}function or(){if(!C)throw new Error("WebGPU adapter not initialized \u2014 call init() first.");let{device:t,description:r}=C.info;return{description:r||"unknown",device:t||"unknown"}}function rr(){return $}function F(){if(!T)throw new Error("WebGPU device not initialized \u2014 call init() first.");return T}function w(...t){t.flat().forEach(r=>r.destroy())}function v(t,r="blas-input",e=!1){let a=F(),o=a.limits.maxStorageBufferBindingSize,n=t.byteLength;if(n>o)throw new Error(`Buffer size ${n} bytes exceeds device limit of ${o} bytes.`);let s=e?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC:GPUBufferUsage.STORAGE,i=a.createBuffer({label:r,size:n,usage:s,mappedAtCreation:!0});return new Float32Array(i.getMappedRange()).set(t),i.unmap(),i}function N(t,r="blas-storage"){return F().createBuffer({label:r,size:t,usage:GPUBufferUsage.STORAGE})}function V(t,r="blas-result"){return F().createBuffer({label:r,size:t,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC})}function h(t,r){let a=F().createBuffer({label:"blas-readback",size:r.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});return t.copyBufferToBuffer(r,0,a,0,r.size),a}function R(t,r="blas-params"){let e=F(),a=t.length*4,o=Math.ceil(a/16)*16,n=new ArrayBuffer(o),s=new DataView(n);t.forEach(({value:u,type:f},c)=>{let p=c*4;if(f==="u32")s.setUint32(p,u,!0);else if(f==="i32")s.setInt32(p,u,!0);else if(f==="f32")s.setFloat32(p,u,!0);else throw new Error(`Unknown param type "${f}". Use "f32", "u32", or "i32".`)});let i=e.createBuffer({label:r,size:o,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});return e.queue.writeBuffer(i,0,n),i}async function _(t,r=Float32Array){await t.mapAsync(GPUMapMode.READ);let e=new r(t.getMappedRange().slice());return t.unmap(),e}var m=class t{constructor(r,e,a=Float32Array){this._buf=r,this.length=e,this.dtype=a}static from(r){if(!(r instanceof Float32Array))throw new Error("GpuVector.from expects a Float32Array.");let e=v(r,"gpu-vector",!0);return new t(e,r.length,r.constructor)}async read(){let r=F(),e=r.createCommandEncoder(),a=h(e,this._buf);return r.queue.submit([e.finish()]),_(a,this.dtype)}destroy(){this._buf.destroy()}};function ir(t,r=-1,e=1){let a=new Float32Array(t);for(let o=0;o<t;o++)a[o]=r+Math.random()*(e-r);return a}function nr(t,r=-1,e=1){let a=new Float64Array(t);for(let o=0;o<t;o++)a[o]=r+Math.random()*(e-r);return a}function B(t,r,e=null){let a=F(),n=(e?[...r,e]:[...r]).map((s,i)=>({binding:i,resource:{buffer:s}}));return a.createBindGroup({layout:t,entries:n})}function E(t){F().queue.submit([t.finish()])}function P(t,r,e){let a=F(),{querySet:o,passDescriptor:n}=Z(),s=a.createCommandEncoder(),i=s.beginComputePass(n);i.setPipeline(t),i.setBindGroup(0,r),typeof e=="number"?i.dispatchWorkgroups(e):i.dispatchWorkgroups(e.x,e.y),i.end();let u=J(s,o);return s._passEncoder=i,{commandEncoder:s,ts:u}}var de={},j=new WeakMap;async function A(t,r){j.has(t)||j.set(t,new Map);let e=j.get(t);return e.has(r)||e.set(r,await le(r)),e.get(r)}async function me(t){if(typeof window<"u"){let{shaderSources:r}=await Promise.resolve().then(()=>(Wr(),Rr)),e=r[t];if(!e)throw new Error(`Shader "${t}" not found in browser bundle.`);return e}else{let{readFileSync:r}=await import("fs"),{fileURLToPath:e}=await import("url"),{dirname:a,join:o}=await import("path"),n=a(e(de.url));return r(o(n,`../shaders/${t}.wgsl`),"utf8")}}async function le(t){let r=F(),e=await me(t),a=r.createShaderModule({label:t,code:e}),n=(await a.getCompilationInfo()).messages.filter(i=>i.type==="error");if(n.length>0)throw new Error(`Shader "${t}" compilation failed:
421
- ${n.map(i=>` line ${i.lineNum}: ${i.message}`).join(`
422
- `)}`);let s=r.createComputePipeline({label:t,layout:"auto",compute:{module:a}});return s._shaderModule=a,s}var ge=64,Ur=8;function M(t,r){let e=F().limits.maxComputeWorkgroupsPerDimension;return r===void 0?Math.min(Math.ceil(t/ge),e):{x:Math.min(Math.ceil(r/Ur),e),y:Math.min(Math.ceil(t/Ur),e)}}async function Ir(t,r,e,a,o){let n=a instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o))throw new Error("n and incx must be integers.");if(isNaN(e))throw new Error("alpha must not be NaN.");if(!isFinite(e))throw new Error("alpha must be finite.");if(o<=0)throw new Error("incx must be positive.");if(!(a instanceof Float32Array)&&!(a instanceof m))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return n?{}:a;if(a.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");let s=await A(t,"sscal"),i=n?a._buf:v(a,"sscal-x",!0),u=R([{value:r,type:"u32"},{value:e,type:"f32"},{value:o,type:"u32"}],"sscal-params"),f=B(s.getBindGroupLayout(0),[i,u]),{commandEncoder:c,ts:p}=P(s,f,M(r)),y=n?null:h(c,i);E(c);let l=await G(p);if(n)return w(u),l!==void 0?{gpuTimeMs:l}:{};let k=await _(y,Float32Array);return w(i,u,y),l!==void 0?{result:k,gpuTimeMs:l}:k}async function Mr(t,r,e,a,o,n){let s=e instanceof m,i=o instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(a<=0||n<=0)throw new Error("incx and incy must be positive.");if(!(e instanceof Float32Array)&&!(e instanceof m))throw new Error("x must be a Float32Array or GpuVector.");if(!(o instanceof Float32Array)&&!(o instanceof m))throw new Error("y must be a Float32Array or GpuVector.");if(e.constructor!==o.constructor)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return s?{}:{x:e,y:o};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");if(o.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let u=await A(t,"sswap"),f=s?e._buf:v(e,"sswap-x",!0),c=i?o._buf:v(o,"sswap-y",!0),p=R([{value:r,type:"u32"},{value:a,type:"u32"},{value:n,type:"u32"}],"sswap-params"),y=B(u.getBindGroupLayout(0),[f,c,p]),{commandEncoder:l,ts:k}=P(u,y,M(r)),x=s?null:h(l,f),S=i?null:h(l,c);E(l);let d=await G(k);if(s&&i)return w(p),d!==void 0?{gpuTimeMs:d}:{};let b=await _(x,Float32Array),g=await _(S,Float32Array);return w(f,x,c,S,p),d!==void 0?{x:b,y:g,gpuTimeMs:d}:{x:b,y:g}}async function Tr(t,r,e,a,o,n,s){let i=a instanceof m,u=n instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(s))throw new Error("n, incx, and incy must be integers.");if(isNaN(e))throw new Error("alpha must not be NaN.");if(!isFinite(e))throw new Error("alpha must be finite.");if(o<=0||s<=0)throw new Error("incx and incy must be positive.");if(!i&&!(a instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!u&&!(n instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(i!==u)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return u?{}:{y:n};if(a.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(n.length<(r-1)*s+1)throw new Error("y does not have enough elements for the given n and incy.");let f=await A(t,"saxpy"),c=i?a._buf:v(a,"saxpy-x",!1),p=u?n._buf:v(n,"saxpy-y",!0),y=R([{value:r,type:"u32"},{value:e,type:"f32"},{value:o,type:"u32"},{value:s,type:"u32"}],"saxpy-params"),l=B(f.getBindGroupLayout(0),[c,p,y]),{commandEncoder:k,ts:x}=P(f,l,M(r)),S=u?null:h(k,p);E(k);let d=await G(x);if(u&&i)return w(y),d!==void 0?{gpuTimeMs:d}:{};let b=await _(S,Float32Array);return w(c,p,y,S),d!==void 0?{y:b,gpuTimeMs:d}:{y:b}}async function Dr(t,r,e,a,o,n){let s=e instanceof m,i=o instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(a<=0||n<=0)throw new Error("incx and incy must be positive.");if(!s&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!i&&!(o instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(s!==i)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return i?{}:{y:o};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");if(o.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let u=await A(t,"scopy"),f=s?e._buf:v(e,"scopy-x",!1),c=i?o._buf:v(o,"scopy-y",!0),p=R([{value:r,type:"u32"},{value:a,type:"u32"},{value:n,type:"u32"}],"scopy-params"),y=B(u.getBindGroupLayout(0),[f,c,p]),{commandEncoder:l,ts:k}=P(u,y,M(r)),x=i?null:h(l,c);E(l);let S=await G(k);if(i&&s)return w(p),S!==void 0?{gpuTimeMs:S}:{};let d=await _(x,Float32Array);return w(f,c,p,x),S!==void 0?{y:d,gpuTimeMs:S}:{y:d}}var Nr=64;async function Vr(t,r,e,a,o,n){let s=e instanceof m,i=o instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(a<=0||n<=0)throw new Error("incx and incy must be positive.");if(!s&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!i&&!(o instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(s!==i)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return{dot:0};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");if(o.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let u=await A(t,"sdot"),f=await A(t,"reduction/sum"),c=s?e._buf:v(e,"sdot-x",!1),p=i?o._buf:v(o,"sdot-y",!1),y=N(2*Nr*4,"sdot-partials"),l=V(4,"sdot-result"),k=R([{value:r,type:"u32"},{value:a,type:"u32"},{value:n,type:"u32"}],"sdot-params"),x=B(u.getBindGroupLayout(0),[c,p,y,k]),{commandEncoder:S,ts:d}=P(u,x,2*Nr);E(S);let b=B(f.getBindGroupLayout(0),[y,l]),{commandEncoder:g,ts:W}=P(f,b,1),U=h(g,l);E(g);let[D,z,O]=await Promise.all([G(d),G(W),_(U,Float32Array)]);return s&&i?(w(y,l,k,U),D!==void 0&&z!==void 0?{dot:O[0],gpuTimeMs:D+z}:{dot:O[0]}):(w(c,p,y,l,k,U),D!==void 0&&z!==void 0?{dot:O[0],gpuTimeMs:D+z}:{dot:O[0]})}var Cr=64;async function zr(t,r,e,a){let o=e instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a))throw new Error("n and incx must be integers.");if(a<=0)throw new Error("incx must be positive.");if(!o&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{asum:0};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");let n=await A(t,"sasum"),s=await A(t,"reduction/sum"),i=o?e._buf:v(e,"sasum-x",!1),u=N(2*Cr*4,"sasum-partials"),f=V(4,"sasum-result"),c=R([{value:r,type:"u32"},{value:a,type:"u32"}],"sasum-params"),p=B(n.getBindGroupLayout(0),[i,u,c]),{commandEncoder:y,ts:l}=P(n,p,2*Cr);E(y);let k=B(s.getBindGroupLayout(0),[u,f]),{commandEncoder:x,ts:S}=P(s,k,1),d=h(x,f);E(x);let[b,g,W]=await Promise.all([G(l),G(S),_(d,Float32Array)]);return o?(w(u,f,c,d),b!==void 0&&g!==void 0?{asum:W[0],gpuTimeMs:b+g}:{asum:W[0]}):(w(i,u,f,c,d),b!==void 0&&g!==void 0?{asum:W[0],gpuTimeMs:b+g}:{asum:W[0]})}var Or=64;async function Lr(t,r,e,a){let o=e instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a))throw new Error("n and incx must be integers.");if(a<=0)throw new Error("incx must be positive.");if(!o&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{nrm2:0};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");let n=await A(t,"snrm2"),s=await A(t,"reduction/sum"),i=o?e._buf:v(e,"snrm2-x",!1),u=N(2*Or*4,"snrm2-partials"),f=V(4,"snrm2-result"),c=R([{value:r,type:"u32"},{value:a,type:"u32"}],"snrm2-params"),p=B(n.getBindGroupLayout(0),[i,u,c]),{commandEncoder:y,ts:l}=P(n,p,2*Or);E(y);let k=B(s.getBindGroupLayout(0),[u,f]),{commandEncoder:x,ts:S}=P(s,k,1),d=h(x,f);E(x);let[b,g,W]=await Promise.all([G(l),G(S),_(d,Float32Array)]),U=Math.sqrt(W[0]);return o?(w(u,f,c,d),b!==void 0&&g!==void 0?{nrm2:U,gpuTimeMs:b+g}:{nrm2:U}):(w(i,u,f,c,d),b!==void 0&&g!==void 0?{nrm2:U,gpuTimeMs:b+g}:{nrm2:U})}var Q=64;async function qr(t,r,e,a){let o=e instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a))throw new Error("n and incx must be integers.");if(a<=0)throw new Error("incx must be positive.");if(!o&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{index:0};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");let n=await A(t,"isamax"),s=await A(t,"reduction/argmax"),i=o?e._buf:v(e,"isamax-x",!1),u=N(2*Q*4,"isamax-partials-val"),f=N(2*Q*4,"isamax-partials-idx"),c=V(4,"isamax-result"),p=R([{value:r,type:"u32"},{value:a,type:"u32"}],"isamax-params"),y=B(n.getBindGroupLayout(0),[i,u,f,p]),{commandEncoder:l,ts:k}=P(n,y,2*Q);E(l);let x=B(s.getBindGroupLayout(0),[u,f,c]),{commandEncoder:S,ts:d}=P(s,x,1),b=h(S,c);E(S);let[g,W,U]=await Promise.all([G(k),G(d),_(b,Uint32Array)]),D=U[0];return o?(w(u,f,c,p,b),g!==void 0&&W!==void 0?{index:D,gpuTimeMs:g+W}:{index:D}):(w(i,u,f,c,p,b),g!==void 0&&W!==void 0?{index:D,gpuTimeMs:g+W}:{index:D})}async function Yr(t,r,e,a,o,n,s,i){let u=e instanceof m,f=o instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(isNaN(s)||isNaN(i))throw new Error("c and s must not be NaN.");if(!isFinite(s))throw new Error("c must be finite.");if(!isFinite(i))throw new Error("s must be finite.");if(a<=0||n<=0)throw new Error("incx and incy must be positive.");if(!u&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!f&&!(o instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(u!==f)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return u?{}:{x:e,y:o};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");if(o.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let c=await A(t,"srot"),p=u?e._buf:v(e,"srot-x",!0),y=f?o._buf:v(o,"srot-y",!0),l=R([{value:r,type:"u32"},{value:s,type:"f32"},{value:i,type:"f32"},{value:a,type:"u32"},{value:n,type:"u32"}],"srot-params"),k=B(c.getBindGroupLayout(0),[p,y,l]),{commandEncoder:x,ts:S}=P(c,k,M(r)),d=u?null:h(x,p),b=f?null:h(x,y);E(x);let g=await G(S);if(u&&f)return w(l),g!==void 0?{gpuTimeMs:g}:{};let[W,U]=await Promise.all([_(d,Float32Array),_(b,Float32Array)]);return w(p,y,l,d,b),g!==void 0?{x:W,y:U,gpuTimeMs:g}:{x:W,y:U}}async function $r(t,r,e,a,o,n,s){let i=e instanceof m,u=o instanceof m;if(!(t instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(a)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(!(s instanceof Float32Array)||s.length!==5)throw new Error("param must be a Float32Array of length 5.");if(a<=0||n<=0)throw new Error("incx and incy must be positive.");if(!i&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!u&&!(o instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(i!==u)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0||s[0]===-2)return i?{}:{x:e,y:o};if(e.length<(r-1)*a+1)throw new Error("x does not have enough elements for the given n and incx.");if(o.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let f=await A(t,"srotm"),c=i?e._buf:v(e,"srotm-x",!0),p=u?o._buf:v(o,"srotm-y",!0),y=v(s,"srotm-param",!1),l=R([{value:r,type:"u32"},{value:a,type:"u32"},{value:n,type:"u32"}],"srotm-params"),k=B(f.getBindGroupLayout(0),[c,p,y,l]),{commandEncoder:x,ts:S}=P(f,k,M(r)),d=i?null:h(x,c),b=u?null:h(x,p);E(x);let g=await G(S);if(i&&u)return w(y,l),g!==void 0?{gpuTimeMs:g}:{};let[W,U]=await Promise.all([_(d,Float32Array),_(b,Float32Array)]);return w(c,p,y,l,d,b),g!==void 0?{x:W,y:U,gpuTimeMs:g}:{x:W,y:U}}return Zr(we);})();
538
+ `});var ue,se=I(()=>{ue=`// sgemv_n: y = alpha * A * x + beta * y (A is m\xD7n row-major, no-transpose)
539
+ //
540
+ // One workgroup per output row, with a grid-stride outer loop so the shader
541
+ // still covers all rows when m exceeds maxComputeWorkgroupsPerDimension.
542
+ // Threads stride through A[row, :] and x with coalesced reads (consecutive
543
+ // threads \u2192 consecutive addresses). Four independent accumulators let the GPU
544
+ // pipeline memory requests across iterations (ILP=4), hiding the
545
+ // global-memory latency.
546
+
547
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
548
+ @group(0) @binding(1) var<storage, read> x: array<f32>;
549
+ @group(0) @binding(2) var<storage, read_write> y: array<f32>;
550
+
551
+ struct Params {
552
+ m: u32,
553
+ n: u32,
554
+ alpha: f32,
555
+ beta: f32,
556
+ incx: u32,
557
+ incy: u32,
558
+ lda: u32,
559
+ }
560
+
561
+ @group(0) @binding(3) var<uniform> params: Params;
562
+
563
+ const WGS: u32 = 64u;
564
+ var<workgroup> scratch: array<f32, 64>;
565
+
566
+ @compute @workgroup_size(64)
567
+ fn main(
568
+ @builtin(workgroup_id) wgid: vec3u,
569
+ @builtin(local_invocation_id) lid: vec3u,
570
+ @builtin(num_workgroups) nwg: vec3u,
571
+ ) {
572
+ // Grid-stride loop: each workgroup handles ceil(m / nwg.x) rows.
573
+ for (var row = wgid.x; row < params.m; row += nwg.x) {
574
+ let row_base = row * params.lda;
575
+ var acc0: f32 = 0.0;
576
+ var acc1: f32 = 0.0;
577
+ var acc2: f32 = 0.0;
578
+ var acc3: f32 = 0.0;
579
+
580
+ // 4-unrolled loop: each iteration issues 4 independent loads for A and x.
581
+ // The accumulators are independent so the GPU can overlap the memory
582
+ // requests rather than serialising them behind a dependency chain.
583
+ let n4_floor = (params.n / (4u * WGS)) * (4u * WGS);
584
+ for (var j: u32 = lid.x; j < n4_floor; j += 4u * WGS) {
585
+ acc0 += A[row_base + j ] * x[ j * params.incx];
586
+ acc1 += A[row_base + j + WGS ] * x[(j + WGS) * params.incx];
587
+ acc2 += A[row_base + j + 2u * WGS ] * x[(j + 2u * WGS) * params.incx];
588
+ acc3 += A[row_base + j + 3u * WGS ] * x[(j + 3u * WGS) * params.incx];
589
+ }
590
+ // Scalar tail: at most 3*WGS elements left after the unrolled block.
591
+ for (var j: u32 = n4_floor + lid.x; j < params.n; j += WGS) {
592
+ acc0 += A[row_base + j] * x[j * params.incx];
593
+ }
594
+
595
+ // Parallel reduction: 64 \u2192 32 \u2192 16 \u2192 8 \u2192 4 \u2192 2 \u2192 1
596
+ scratch[lid.x] = acc0 + acc1 + acc2 + acc3;
597
+ workgroupBarrier();
598
+ for (var stride = WGS >> 1u; stride > 0u; stride >>= 1u) {
599
+ if lid.x < stride {
600
+ scratch[lid.x] += scratch[lid.x + stride];
601
+ }
602
+ workgroupBarrier();
603
+ }
604
+
605
+ if lid.x == 0u {
606
+ let yi = row * params.incy;
607
+ y[yi] = params.alpha * scratch[0] + params.beta * y[yi];
608
+ }
609
+ // All 64 threads must agree before the next row reuses scratch[].
610
+ workgroupBarrier();
611
+ }
612
+ }
613
+ `});var fe,le=I(()=>{fe=`// sgemv_t: y = alpha * A^T * x + beta * y (A is m\xD7n row-major, transposed)
614
+ // each thread owns one column of A \u2192 one element of y (length n)
615
+ // tiles over x (length m) using shared memory; four independent accumulators
616
+ // let the GPU pipeline A reads across j within each tile (ILP=4)
617
+
618
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
619
+ @group(0) @binding(1) var<storage, read> x: array<f32>;
620
+ @group(0) @binding(2) var<storage, read_write> y: array<f32>;
621
+
622
+ struct Params {
623
+ m: u32,
624
+ n: u32,
625
+ alpha: f32,
626
+ beta: f32,
627
+ incx: u32,
628
+ incy: u32,
629
+ lda: u32,
630
+ }
631
+
632
+ @group(0) @binding(3) var<uniform> params: Params;
633
+
634
+ const WGS: u32 = 64u;
635
+ var<workgroup> x_tile: array<f32, 64>;
636
+
637
+ @compute @workgroup_size(64)
638
+ fn main(
639
+ @builtin(global_invocation_id) gid: vec3u,
640
+ @builtin(local_invocation_id) lid: vec3u,
641
+ ) {
642
+ // each thread owns column col of A \u2192 output y[col]
643
+ let col = gid.x;
644
+ // tile over x (length m, the rows of A)
645
+ let m_floor = (params.m / WGS) * WGS;
646
+ var acc0: f32 = 0.0;
647
+ var acc1: f32 = 0.0;
648
+ var acc2: f32 = 0.0;
649
+ var acc3: f32 = 0.0;
650
+
651
+ for (var base = 0u; base < m_floor; base += WGS) {
652
+ // cooperative load: all 64 threads fill x_tile with x[base..base+WGS]
653
+ x_tile[lid.x] = x[(base + lid.x) * params.incx];
654
+ workgroupBarrier();
655
+
656
+ // 4-unrolled inner loop: 4 independent A reads let the GPU pipeline
657
+ // global-memory requests within each tile. WGS=64 divides by 4 exactly.
658
+ if (col < params.n) {
659
+ for (var j = 0u; j < WGS; j += 4u) {
660
+ acc0 += A[(base + j ) * params.lda + col] * x_tile[j ];
661
+ acc1 += A[(base + j + 1) * params.lda + col] * x_tile[j + 1];
662
+ acc2 += A[(base + j + 2) * params.lda + col] * x_tile[j + 2];
663
+ acc3 += A[(base + j + 3) * params.lda + col] * x_tile[j + 3];
664
+ }
665
+ }
666
+ workgroupBarrier();
667
+ }
668
+
669
+ if (col < params.n) {
670
+ // remainder: m not divisible by WGS \u2014 short loop, single accumulator fine
671
+ for (var k = m_floor; k < params.m; k++) {
672
+ acc0 += A[k * params.lda + col] * x[k * params.incx];
673
+ }
674
+ let yi = col * params.incy;
675
+ y[yi] = params.alpha * (acc0 + acc1 + acc2 + acc3) + params.beta * y[yi];
676
+ }
677
+ }
678
+ `});var me,ce=I(()=>{me=`// ssymv: y = alpha * A * x + beta * y
679
+ // A is n\xD7n symmetric, lower (uplo=0) or upper (uplo=1) triangle stored.
680
+ // The logical matrix is fully dense (symmetric), so each row's dot product
681
+ // sums over all n columns; entries on the unstored side of the diagonal are
682
+ // fetched from their mirror position (A[i,j] == A[j,i]).
683
+ // One workgroup per row, grid-stride outer loop.
684
+
685
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
686
+ @group(0) @binding(1) var<storage, read> x: array<f32>;
687
+ @group(0) @binding(2) var<storage, read_write> y: array<f32>;
688
+
689
+ struct Params {
690
+ n: u32,
691
+ alpha: f32,
692
+ beta: f32,
693
+ incx: u32,
694
+ incy: u32,
695
+ lda: u32,
696
+ uplo: u32, // 0 = lower, 1 = upper
697
+ }
698
+
699
+ @group(0) @binding(3) var<uniform> params: Params;
700
+
701
+ const WGS: u32 = 64u;
702
+ var<workgroup> scratch: array<f32, 64>;
703
+
704
+ @compute @workgroup_size(64)
705
+ fn main(
706
+ @builtin(workgroup_id) wgid: vec3u,
707
+ @builtin(local_invocation_id) lid: vec3u,
708
+ @builtin(num_workgroups) nwg: vec3u,
709
+ ) {
710
+ for (var i = wgid.x; i < params.n; i += nwg.x) {
711
+ var acc = 0.0f;
712
+
713
+ // y[i] = \u03A3_j A[i,j] * x[j]
714
+ for (var j = lid.x; j < params.n; j += WGS) {
715
+ var aVal: f32;
716
+ if params.uplo == 0u {
717
+ // Lower: A[i,j] stored at A[i*lda+j] for j \u2264 i, mirrored from A[j*lda+i] otherwise
718
+ if j <= i {
719
+ aVal = A[i * params.lda + j];
720
+ } else {
721
+ aVal = A[j * params.lda + i];
722
+ }
723
+ } else {
724
+ // Upper: A[i,j] stored at A[i*lda+j] for j \u2265 i, mirrored from A[j*lda+i] otherwise
725
+ if j >= i {
726
+ aVal = A[i * params.lda + j];
727
+ } else {
728
+ aVal = A[j * params.lda + i];
729
+ }
730
+ }
731
+ acc += aVal * x[j * params.incx];
732
+ }
733
+
734
+ // Parallel reduction: 64 \u2192 1
735
+ scratch[lid.x] = acc;
736
+ workgroupBarrier();
737
+ for (var stride = WGS >> 1u; stride > 0u; stride >>= 1u) {
738
+ if lid.x < stride { scratch[lid.x] += scratch[lid.x + stride]; }
739
+ workgroupBarrier();
740
+ }
741
+
742
+ if lid.x == 0u {
743
+ y[i * params.incy] = params.alpha * scratch[0] + params.beta * y[i * params.incy];
744
+ }
745
+ }
746
+ }
747
+ `});var pe,de=I(()=>{pe=`// strmv: y = op(A) * x
748
+ // A is n\xD7n triangular, lower (uplo=0) or upper (uplo=1) triangle stored.
749
+ // op(A) is A (trans=0) or A^T (trans=1).
750
+ // diag=1 (unit) treats the diagonal as 1 without reading A's diagonal values.
751
+ // One workgroup per row, grid-stride outer loop.
752
+
753
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
754
+ @group(0) @binding(1) var<storage, read> x: array<f32>;
755
+ @group(0) @binding(2) var<storage, read_write> y: array<f32>;
756
+
757
+ struct Params {
758
+ n: u32,
759
+ incx: u32,
760
+ incy: u32,
761
+ lda: u32,
762
+ trans: u32, // 0 = no-transpose, 1 = transpose
763
+ uplo: u32, // 0 = lower, 1 = upper
764
+ diag: u32, // 0 = non-unit, 1 = unit
765
+ }
766
+
767
+ @group(0) @binding(3) var<uniform> params: Params;
768
+
769
+ const WGS: u32 = 64u;
770
+ var<workgroup> scratch: array<f32, 64>;
771
+
772
+ @compute @workgroup_size(64)
773
+ fn main(
774
+ @builtin(workgroup_id) wgid: vec3u,
775
+ @builtin(local_invocation_id) lid: vec3u,
776
+ @builtin(num_workgroups) nwg: vec3u,
777
+ ) {
778
+ for (var i = wgid.x; i < params.n; i += nwg.x) {
779
+ var acc = 0.0f;
780
+
781
+ if params.trans == 0u {
782
+ // No-transpose: y[i] = \u03A3_j A[i,j] * x[j]
783
+ if params.uplo == 0u {
784
+ // Lower: A[i,j] stored at A[i*lda+j] for j \u2264 i
785
+ for (var j = lid.x; j <= i; j += WGS) {
786
+ var aVal: f32;
787
+ // unit diagonal: use 1 instead of A's actual diagonal value
788
+ if params.diag == 1u && j == i {
789
+ aVal = 1.0;
790
+ } else if ( j <= i ) {
791
+ aVal = A[i * params.lda + j];
792
+ }
793
+ acc += aVal * x[j * params.incx];
794
+ }
795
+ } else {
796
+ // Upper: A[i,j] stored at A[i*lda+j] for j \u2265 i
797
+ for (var j = i + lid.x; j < params.n; j += WGS) {
798
+ var aVal: f32;
799
+ // unit diagonal: use 1 instead of A's actual diagonal value
800
+ if params.diag == 1u && j == i {
801
+ aVal = 1.0;
802
+ } else if ( j >= i ) {
803
+ aVal = A[i * params.lda + j];
804
+ }
805
+ acc += aVal * x[j * params.incx];
806
+ }
807
+ }
808
+ } else {
809
+ // Transpose: y[i] = \u03A3_j A[j,i] * x[j]
810
+ if params.uplo == 0u {
811
+ // Lower: A[j,i] stored at A[j*lda+i] for j \u2265 i
812
+ for (var j = i + lid.x; j < params.n; j += WGS) {
813
+ var aVal: f32;
814
+ // unit diagonal: use 1 instead of A's actual diagonal value
815
+ if params.diag == 1u && j == i {
816
+ aVal = 1.0;
817
+ } else if ( j >= i ) {
818
+ aVal = A[j * params.lda + i];
819
+ }
820
+ acc += aVal * x[j * params.incx];
821
+ }
822
+ } else {
823
+ // Upper: A[j,i] stored at A[j*lda+i] for j \u2264 i
824
+ for (var j = lid.x; j <= i; j += WGS) {
825
+ var aVal: f32;
826
+ // unit diagonal: use 1 instead of A's actual diagonal value
827
+ if params.diag == 1u && j == i {
828
+ aVal = 1.0;
829
+ } else if ( j <= i ) {
830
+ aVal = A[j * params.lda + i];
831
+ }
832
+ acc += aVal * x[j * params.incx];
833
+ }
834
+ }
835
+ }
836
+
837
+ // Parallel reduction: 64 \u2192 1
838
+ scratch[lid.x] = acc;
839
+ workgroupBarrier();
840
+ for (var stride = WGS >> 1u; stride > 0u; stride >>= 1u) {
841
+ if lid.x < stride { scratch[lid.x] += scratch[lid.x + stride]; }
842
+ workgroupBarrier();
843
+ }
844
+
845
+ if lid.x == 0u {
846
+ y[ i * params.incy ] = scratch[0];
847
+ }
848
+ }
849
+ }
850
+ `});var we,ge=I(()=>{we=`// sger: A := alpha * x * y^T + A (rank-1 update, A is m\xD7n general/dense)
851
+
852
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
853
+ @group(0) @binding(1) var<storage, read> y: array<f32>;
854
+ @group(0) @binding(2) var<storage, read_write> A: array<f32>;
855
+
856
+ struct Params {
857
+ m: u32,
858
+ n: u32,
859
+ alpha: f32,
860
+ incx: u32,
861
+ incy: u32,
862
+ lda: u32,
863
+ }
864
+
865
+ @group(0) @binding(3) var<uniform> params: Params;
866
+
867
+ const WGS: u32 = 64u;
868
+
869
+ @compute @workgroup_size(64)
870
+ fn main(
871
+ @builtin(workgroup_id) wgid: vec3u,
872
+ @builtin(local_invocation_id) lid: vec3u,
873
+ @builtin(num_workgroups) nwg: vec3u,
874
+ ) {
875
+ for (var row = wgid.x; row < params.m; row += nwg.x) {
876
+ let xi = params.alpha * x[row * params.incx];
877
+ let row_base = row * params.lda;
878
+
879
+ // 4-unrolled loop: each iteration issues 4 independent A/y accesses.
880
+ let n4_floor = (params.n / (4u * WGS)) * (4u * WGS);
881
+ for (var col: u32 = lid.x; col < n4_floor; col += 4u * WGS) {
882
+ let idx0 = row_base + col;
883
+ let idx1 = row_base + col + WGS;
884
+ let idx2 = row_base + col + 2u * WGS;
885
+ let idx3 = row_base + col + 3u * WGS;
886
+ A[idx0] = xi * y[ col * params.incy] + A[idx0];
887
+ A[idx1] = xi * y[(col + WGS) * params.incy] + A[idx1];
888
+ A[idx2] = xi * y[(col + 2u * WGS) * params.incy] + A[idx2];
889
+ A[idx3] = xi * y[(col + 3u * WGS) * params.incy] + A[idx3];
890
+ }
891
+ // Scalar tail: at most 3*WGS elements left after the unrolled block.
892
+ for (var col: u32 = n4_floor + lid.x; col < params.n; col += WGS) {
893
+ let idx = row_base + col;
894
+ A[idx] = xi * y[col * params.incy] + A[idx];
895
+ }
896
+ }
897
+ }
898
+ `});var he,be=I(()=>{he=`// ssyr: A := alpha * x * x^T + A (symmetric rank-1 update)
899
+ // A is n\xD7n symmetric; only the triangle specified by uplo is referenced/updated,
900
+ // the other triangle is implied by symmetry (not touched).
901
+
902
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
903
+ @group(0) @binding(1) var<storage, read_write> A: array<f32>;
904
+
905
+ struct Params {
906
+ n: u32,
907
+ alpha: f32,
908
+ incx: u32,
909
+ lda: u32,
910
+ uplo: u32, // 0 = lower, 1 = upper
911
+ }
912
+
913
+ @group(0) @binding(2) var<uniform> params: Params;
914
+
915
+ const WGS: u32 = 64u;
916
+
917
+ @compute @workgroup_size(64)
918
+ fn main(
919
+ @builtin(workgroup_id) wgid: vec3u,
920
+ @builtin(local_invocation_id) lid: vec3u,
921
+ @builtin(num_workgroups) nwg: vec3u,
922
+ ) {
923
+ for (var row = wgid.x; row < params.n; row += nwg.x) {
924
+ let xi = params.alpha * x[row * params.incx];
925
+ let row_base = row * params.lda;
926
+
927
+ // Stored-triangle column range for this row: lower [0,row], upper [row,n).
928
+ var colStart: u32;
929
+ var colEnd: u32;
930
+ if params.uplo == 1u {
931
+ colStart = row;
932
+ colEnd = params.n;
933
+ } else {
934
+ colStart = 0u;
935
+ colEnd = row + 1u;
936
+ }
937
+
938
+ // 4-unrolled loop over the stored range.
939
+ let rangeLen = colEnd - colStart;
940
+ let n4_floor = colStart + (rangeLen / (4u * WGS)) * (4u * WGS);
941
+ for (var col: u32 = colStart + lid.x; col < n4_floor; col += 4u * WGS) {
942
+ let idx0 = row_base + col;
943
+ let idx1 = row_base + col + WGS;
944
+ let idx2 = row_base + col + 2u * WGS;
945
+ let idx3 = row_base + col + 3u * WGS;
946
+ A[idx0] = xi * x[ col * params.incx] + A[idx0];
947
+ A[idx1] = xi * x[(col + WGS) * params.incx] + A[idx1];
948
+ A[idx2] = xi * x[(col + 2u * WGS) * params.incx] + A[idx2];
949
+ A[idx3] = xi * x[(col + 3u * WGS) * params.incx] + A[idx3];
950
+ }
951
+ // Scalar tail: at most 3*WGS elements left after the unrolled block.
952
+ for (var col: u32 = n4_floor + lid.x; col < colEnd; col += WGS) {
953
+ let idx = row_base + col;
954
+ A[idx] = xi * x[col * params.incx] + A[idx];
955
+ }
956
+ }
957
+ }
958
+ `});var ve,xe=I(()=>{ve=`// ssyr2: A := alpha * x * y^T + alpha * y * x^T + A (symmetric rank-2 update)
959
+ // A is n\xD7n symmetric; only the triangle specified by uplo is referenced/updated,
960
+ // the other triangle is implied by symmetry (not touched).
961
+
962
+ @group(0) @binding(0) var<storage, read> x: array<f32>;
963
+ @group(0) @binding(1) var<storage, read> y: array<f32>;
964
+ @group(0) @binding(2) var<storage, read_write> A: array<f32>;
965
+
966
+ struct Params {
967
+ n: u32,
968
+ alpha: f32,
969
+ incx: u32,
970
+ incy: u32,
971
+ lda: u32,
972
+ uplo: u32, // 0 = lower, 1 = upper
973
+ }
974
+
975
+ @group(0) @binding(3) var<uniform> params: Params;
976
+
977
+ const WGS: u32 = 64u;
978
+
979
+ @compute @workgroup_size(64)
980
+ fn main(
981
+ @builtin(workgroup_id) wgid: vec3u,
982
+ @builtin(local_invocation_id) lid: vec3u,
983
+ @builtin(num_workgroups) nwg: vec3u,
984
+ ) {
985
+ for (var row = wgid.x; row < params.n; row += nwg.x) {
986
+ let xi = params.alpha * x[row * params.incx];
987
+ let yi = params.alpha * y[row * params.incy];
988
+ let row_base = row * params.lda;
989
+
990
+ // Stored-triangle column range for this row: lower [0,row], upper [row,n).
991
+ var colStart: u32;
992
+ var colEnd: u32;
993
+ if params.uplo == 1u {
994
+ colStart = row;
995
+ colEnd = params.n;
996
+ } else {
997
+ colStart = 0u;
998
+ colEnd = row + 1u;
999
+ }
1000
+
1001
+ // 4-unrolled loop over the stored range.
1002
+ let rangeLen = colEnd - colStart;
1003
+ let n4_floor = colStart + (rangeLen / (4u * WGS)) * (4u * WGS);
1004
+ for (var col: u32 = colStart + lid.x; col < n4_floor; col += 4u * WGS) {
1005
+ let idx0 = row_base + col;
1006
+ let idx1 = row_base + col + WGS;
1007
+ let idx2 = row_base + col + 2u * WGS;
1008
+ let idx3 = row_base + col + 3u * WGS;
1009
+ A[idx0] = xi * y[ col * params.incy] + yi * x[ col * params.incx] + A[idx0];
1010
+ A[idx1] = xi * y[(col + WGS) * params.incy] + yi * x[(col + WGS) * params.incx] + A[idx1];
1011
+ A[idx2] = xi * y[(col + 2u * WGS) * params.incy] + yi * x[(col + 2u * WGS) * params.incx] + A[idx2];
1012
+ A[idx3] = xi * y[(col + 3u * WGS) * params.incy] + yi * x[(col + 3u * WGS) * params.incx] + A[idx3];
1013
+ }
1014
+ // Scalar tail: at most 3*WGS elements left after the unrolled block.
1015
+ for (var col: u32 = n4_floor + lid.x; col < colEnd; col += WGS) {
1016
+ let idx = row_base + col;
1017
+ A[idx] = xi * y[col * params.incy] + yi * x[col * params.incx] + A[idx];
1018
+ }
1019
+ }
1020
+ }
1021
+ `});var _e,ye=I(()=>{_e=`// f64add: adds two doubles, each packed as a [main, aux] pair (main: f32
1022
+ // value, aux: raw u32 bits \u2014 see src/util/f64pack.mjs; decode()/encode()
1023
+ // below are the WGSL mirror of that file's packedToFields()/fieldsToPacked()),
1024
+ // producing the sum as another [main, aux] pair.
1025
+ //
1026
+ // Implements IEEE-754 binary64 addition (align, add/subtract significands,
1027
+ // normalize, round-to-nearest-even) using only u32 bitwise/integer
1028
+ // arithmetic \u2014 WGSL has no 64-bit integer type or arbitrary-precision
1029
+ // integers, so each operand's 53-bit significand is carried as a two-word
1030
+ // (hi, lo) pair, widened by 3 bits at the bottom to hold guard/round/sticky
1031
+ // information while aligning exponents.
1032
+
1033
+ const EXP_ALL_ONES: u32 = 0x7ffu;
1034
+ const BIAS: i32 = 1023;
1035
+ const QUIET_NAN_MANTISSA_HI: u32 = 1u << 19u; // bit51 of the 52-bit mantissa -> canonical quiet NaN
1036
+
1037
+ struct Fields {
1038
+ sign: u32,
1039
+ rawExp: u32,
1040
+ mantissaHi: u32, // 20 bits
1041
+ lo: u32, // 32 bits
1042
+ }
1043
+
1044
+ // A packed [main, aux] result \u2014 aux stays a raw u32; it must never be stored
1045
+ // as an array<f32>/treated as a real float (bit pattern can land on a NaN/
1046
+ // Infinity exponent for perfectly ordinary doubles \u2014 an f32-typed storage
1047
+ // slot canonicalizes/corrupts that on any round-trip). See f64pack.mjs's
1048
+ // comment above fieldsToPacked, and dasum.wgsl's xAux/partialsAux bindings.
1049
+ struct Packed {
1050
+ main: f32,
1051
+ aux: u32,
1052
+ }
1053
+
1054
+ // Mirrors packedToFields() in f64pack.mjs.
1055
+ fn decode(mainBits: u32, auxBits: u32) -> Fields {
1056
+ let sign = mainBits >> 31u;
1057
+ let expMain = (mainBits >> 23u) & 0xffu;
1058
+ let mantMain = mainBits & 0x7fffffu;
1059
+
1060
+ let auxSign = auxBits >> 31u;
1061
+ let auxExp8 = (auxBits >> 23u) & 0xffu;
1062
+ let auxMant23 = auxBits & 0x7fffffu;
1063
+
1064
+ let expExtra = (auxSign << 2u) | (auxExp8 >> 6u);
1065
+ let mantExtra29 = ((auxExp8 & 0x3fu) << 23u) | auxMant23;
1066
+
1067
+ let rawExp = (expMain << 3u) | expExtra;
1068
+ let mantissaHi = mantMain >> 3u;
1069
+ let mantTop3 = mantMain & 0x7u;
1070
+ let lo = (mantTop3 << 29u) | mantExtra29;
1071
+
1072
+ return Fields(sign, rawExp, mantissaHi, lo);
1073
+ }
1074
+
1075
+ // Mirrors fieldsToPacked() in f64pack.mjs.
1076
+ fn encode(sign: u32, rawExp: u32, mantissaHi: u32, lo: u32) -> Packed {
1077
+ let expMain = rawExp >> 3u;
1078
+ let expExtra = rawExp & 0x7u;
1079
+
1080
+ let mantTop3 = lo >> 29u;
1081
+ let mantMain = (mantissaHi << 3u) | mantTop3;
1082
+ let mantExtra29 = lo & 0x1fffffffu;
1083
+
1084
+ let mainBits = (sign << 31u) | (expMain << 23u) | mantMain;
1085
+
1086
+ let auxSign = (expExtra >> 2u) & 0x1u;
1087
+ let auxExpTop2 = expExtra & 0x3u;
1088
+ let auxExpBot6 = mantExtra29 >> 23u;
1089
+ let auxMant23 = mantExtra29 & 0x7fffffu;
1090
+ let auxExp8 = (auxExpTop2 << 6u) | auxExpBot6;
1091
+
1092
+ let auxBits = (auxSign << 31u) | (auxExp8 << 23u) | auxMant23;
1093
+
1094
+ return Packed(bitcast<f32>(mainBits), auxBits);
1095
+ }
1096
+
1097
+ struct Pair { hi: u32, lo: u32 }
1098
+ struct Shifted { hi: u32, lo: u32, sticky: u32 }
1099
+
1100
+ // Two-word right shift by 0..64+ bits, folding every shifted-out 1 bit into
1101
+ // a returned sticky flag \u2014 used only for the (potentially huge) exponent
1102
+ // alignment shift, where exact bits can't all be kept.
1103
+ fn shr_sticky(hi: u32, lo: u32, n: u32) -> Shifted {
1104
+ if (n == 0u) {
1105
+ return Shifted(hi, lo, 0u);
1106
+ }
1107
+ if (n >= 64u) {
1108
+ return Shifted(0u, 0u, select(0u, 1u, hi != 0u || lo != 0u));
1109
+ }
1110
+ if (n < 32u) {
1111
+ let stickyBits = lo & ((1u << n) - 1u);
1112
+ let newLo = (lo >> n) | (hi << (32u - n));
1113
+ let newHi = hi >> n;
1114
+ return Shifted(newHi, newLo, select(0u, 1u, stickyBits != 0u));
1115
+ }
1116
+ if (n == 32u) {
1117
+ return Shifted(0u, hi, select(0u, 1u, lo != 0u));
1118
+ }
1119
+ let m = n - 32u;
1120
+ let stickyBits = lo | (hi & ((1u << m) - 1u));
1121
+ let newLo = hi >> m;
1122
+ return Shifted(0u, newLo, select(0u, 1u, stickyBits != 0u));
1123
+ }
1124
+
1125
+ // Two-word left shift by 0..63 bits \u2014 used only to renormalize after
1126
+ // cancellation, by an amount that exactly matches the leading-zero count,
1127
+ // so nothing meaningful is ever lost off the top.
1128
+ fn shl(hi: u32, lo: u32, n: u32) -> Pair {
1129
+ if (n == 0u) {
1130
+ return Pair(hi, lo);
1131
+ }
1132
+ if (n < 32u) {
1133
+ let newHi = (hi << n) | (lo >> (32u - n));
1134
+ let newLo = lo << n;
1135
+ return Pair(newHi, newLo);
1136
+ }
1137
+ if (n == 32u) {
1138
+ return Pair(lo, 0u);
1139
+ }
1140
+ let m = n - 32u;
1141
+ return Pair(lo << m, 0u);
1142
+ }
1143
+
1144
+ fn add64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> Pair {
1145
+ let sumLo = aLo + bLo;
1146
+ let carry = select(0u, 1u, sumLo < aLo); // wrapped around -> there was a carry
1147
+ let sumHi = aHi + bHi + carry;
1148
+ return Pair(sumHi, sumLo);
1149
+ }
1150
+
1151
+ // Assumes (aHi:aLo) >= (bHi:bLo) \u2014 callers guarantee this so no sign handling is needed.
1152
+ fn sub64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> Pair {
1153
+ let borrow = select(0u, 1u, aLo < bLo);
1154
+ let diffLo = aLo - bLo;
1155
+ let diffHi = aHi - bHi - borrow;
1156
+ return Pair(diffHi, diffLo);
1157
+ }
1158
+
1159
+ fn ge64(aHi: u32, aLo: u32, bHi: u32, bLo: u32) -> bool {
1160
+ return aHi > bHi || (aHi == bHi && aLo >= bLo);
1161
+ }
1162
+
1163
+ // The actual IEEE-754 addition, returning decoded Fields rather than an
1164
+ // encoded Packed pair \u2014 lets a caller that's accumulating many values in a
1165
+ // row (e.g. dasum.wgsl's per-thread reduction loop) keep the running total
1166
+ // in Fields form the whole time, only encoding once at the very end, instead
1167
+ // of paying a decode+encode round-trip on every single addition. computeSum
1168
+ // (below) is the Packed-in/Packed-out convenience wrapper around this.
1169
+ fn addFields(a: Fields, b: Fields) -> Fields {
1170
+ let aIsNaN = a.rawExp == EXP_ALL_ONES && (a.mantissaHi != 0u || a.lo != 0u);
1171
+ let bIsNaN = b.rawExp == EXP_ALL_ONES && (b.mantissaHi != 0u || b.lo != 0u);
1172
+ if (aIsNaN || bIsNaN) {
1173
+ return Fields(0u, EXP_ALL_ONES, QUIET_NAN_MANTISSA_HI, 0u);
1174
+ }
1175
+
1176
+ let aIsInf = a.rawExp == EXP_ALL_ONES; // mantissa==0 here since NaN is excluded above
1177
+ let bIsInf = b.rawExp == EXP_ALL_ONES;
1178
+ if (aIsInf && bIsInf) {
1179
+ if (a.sign != b.sign) {
1180
+ return Fields(0u, EXP_ALL_ONES, QUIET_NAN_MANTISSA_HI, 0u);
1181
+ }
1182
+ return Fields(a.sign, EXP_ALL_ONES, 0u, 0u);
1183
+ }
1184
+ if (aIsInf) { return Fields(a.sign, EXP_ALL_ONES, 0u, 0u); }
1185
+ if (bIsInf) { return Fields(b.sign, EXP_ALL_ONES, 0u, 0u); }
1186
+
1187
+ let aIsZero = a.rawExp == 0u && a.mantissaHi == 0u && a.lo == 0u;
1188
+ let bIsZero = b.rawExp == 0u && b.mantissaHi == 0u && b.lo == 0u;
1189
+ if (aIsZero && bIsZero) {
1190
+ return Fields(a.sign & b.sign, 0u, 0u, 0u);
1191
+ }
1192
+ if (aIsZero) { return Fields(b.sign, b.rawExp, b.mantissaHi, b.lo); }
1193
+ if (bIsZero) { return Fields(a.sign, a.rawExp, a.mantissaHi, a.lo); }
1194
+
1195
+ // Effective (unbiased) exponent \u2014 subnormals share the smallest normal
1196
+ // exponent for alignment purposes and have no implicit leading 1.
1197
+ var expA = i32(a.rawExp) - BIAS;
1198
+ if (a.rawExp == 0u) { expA = 1 - BIAS; }
1199
+ var expB = i32(b.rawExp) - BIAS;
1200
+ if (b.rawExp == 0u) { expB = 1 - BIAS; }
1201
+
1202
+ let implicitA = select(0u, 1u, a.rawExp != 0u);
1203
+ let implicitB = select(0u, 1u, b.rawExp != 0u);
1204
+
1205
+ // Widen each 53-bit significand (implicit + 52-bit mantissa) by 3 zero
1206
+ // bits at the bottom \u2014 room for guard/round/sticky once alignment shifts happen.
1207
+ let sigHiA = (implicitA << 23u) | (a.mantissaHi << 3u) | (a.lo >> 29u);
1208
+ let sigLoA = a.lo << 3u;
1209
+ let sigHiB = (implicitB << 23u) | (b.mantissaHi << 3u) | (b.lo >> 29u);
1210
+ let sigLoB = b.lo << 3u;
1211
+
1212
+ // P = the operand with the larger exponent (Q = the other); on a tie, P =
1213
+ // whichever has the larger significand \u2014 keeps subtraction below always
1214
+ // non-negative without needing signed magnitudes.
1215
+ var signP: u32; var expP: i32; var sigHiP: u32; var sigLoP: u32;
1216
+ var signQ: u32; var expQ: i32; var sigHiQ: u32; var sigLoQ: u32;
1217
+ if (expA > expB || (expA == expB && ge64(sigHiA, sigLoA, sigHiB, sigLoB))) {
1218
+ signP = a.sign; expP = expA; sigHiP = sigHiA; sigLoP = sigLoA;
1219
+ signQ = b.sign; expQ = expB; sigHiQ = sigHiB; sigLoQ = sigLoB;
1220
+ } else {
1221
+ signP = b.sign; expP = expB; sigHiP = sigHiB; sigLoP = sigLoB;
1222
+ signQ = a.sign; expQ = expA; sigHiQ = sigHiA; sigLoQ = sigLoA;
1223
+ }
1224
+
1225
+ let diff = u32(expP - expQ);
1226
+ let shiftedQ = shr_sticky(sigHiQ, sigLoQ, diff);
1227
+ let alignedHiQ = shiftedQ.hi;
1228
+ let alignedLoQ = shiftedQ.lo | shiftedQ.sticky; // fold sticky into bit0
1229
+
1230
+ var sumHi: u32; var sumLo: u32;
1231
+ if (signP == signQ) {
1232
+ let s = add64(sigHiP, sigLoP, alignedHiQ, alignedLoQ);
1233
+ sumHi = s.hi; sumLo = s.lo;
1234
+ } else {
1235
+ let s = sub64(sigHiP, sigLoP, alignedHiQ, alignedLoQ); // P >= Q(aligned) by construction
1236
+ sumHi = s.hi; sumLo = s.lo;
1237
+ }
1238
+
1239
+ if (sumHi == 0u && sumLo == 0u) {
1240
+ return Fields(0u, 0u, 0u, 0u); // exact cancellation -> +0
1241
+ }
1242
+
1243
+ // commonExp2: per-bit scale of sumLo's bit0 in the widened representation.
1244
+ let commonExp2 = expP - 55;
1245
+
1246
+ var leadPos: i32;
1247
+ if (sumHi != 0u) {
1248
+ leadPos = 32 + i32(31u - countLeadingZeros(sumHi));
1249
+ } else {
1250
+ leadPos = i32(31u - countLeadingZeros(sumLo));
1251
+ }
1252
+ let tentativeExp = leadPos + commonExp2;
1253
+ var targetLSBScale = tentativeExp - 52;
1254
+ if (tentativeExp < -1022) { targetLSBScale = -1074; }
1255
+ let shiftAmt = targetLSBScale - commonExp2;
1256
+
1257
+ var keepHi: u32; var keepLo: u32;
1258
+ if (shiftAmt <= 0) {
1259
+ let sh = shl(sumHi, sumLo, u32(-shiftAmt)); // exact \u2014 cancellation only, never loses bits
1260
+ keepHi = sh.hi; keepLo = sh.lo;
1261
+ } else {
1262
+ // Only reached without cancellation (same-sign add, or a tied-exponent
1263
+ // subtract with no shrinkage) \u2014 shiftAmt here is always exactly 3 or 4,
1264
+ // so the dropped bits are fully known from sumLo directly (no sticky
1265
+ // approximation needed, unlike the Q-alignment shift above).
1266
+ let n = u32(shiftAmt);
1267
+ let remainder = sumLo & ((1u << n) - 1u);
1268
+ let halfway = 1u << (n - 1u);
1269
+ let sh = shr_sticky(sumHi, sumLo, n);
1270
+ keepHi = sh.hi; keepLo = sh.lo;
1271
+ if (remainder > halfway || (remainder == halfway && (keepLo & 1u) != 0u)) {
1272
+ let inc = add64(keepHi, keepLo, 0u, 1u);
1273
+ keepHi = inc.hi; keepLo = inc.lo;
1274
+ }
1275
+ }
1276
+
1277
+ var resultExpBase = targetLSBScale;
1278
+ if ((keepHi & (1u << 21u)) != 0u) { // rounding carried past the 53-bit budget
1279
+ let sh = shr_sticky(keepHi, keepLo, 1u); // dropped bit is guaranteed 0 here
1280
+ keepHi = sh.hi; keepLo = sh.lo;
1281
+ resultExpBase = resultExpBase + 1;
1282
+ }
1283
+
1284
+ let resultSign = signP;
1285
+ if ((keepHi & (1u << 20u)) != 0u) { // normal-shaped result
1286
+ let unbiasedExp = 52 + resultExpBase;
1287
+ let rawExpFinal = unbiasedExp + BIAS;
1288
+ if (rawExpFinal >= 2047) {
1289
+ return Fields(resultSign, EXP_ALL_ONES, 0u, 0u); // overflow -> Infinity
1290
+ }
1291
+ return Fields(resultSign, u32(rawExpFinal), keepHi & 0xfffffu, keepLo);
1292
+ }
1293
+ return Fields(resultSign, 0u, keepHi & 0xfffffu, keepLo); // subnormal result
1294
+ }
1295
+
1296
+ // Packed-in/Packed-out convenience wrapper around addFields \u2014 encodes once,
1297
+ // after the math, rather than addFields itself needing to know about Packed.
1298
+ fn computeSum(a: Fields, b: Fields) -> Packed {
1299
+ let f = addFields(a, b);
1300
+ return encode(f.sign, f.rawExp, f.mantissaHi, f.lo);
1301
+ }
1302
+ `});var Ge,Ee=I(()=>{Ge=`// dasum: result = sum(|x[i]|)
1303
+ // pass 1 dispatches exactly 2 * WGS workgroups; pass 2 uses reduction/sumF64.wgsl.
1304
+ // Same structure as sasum.wgsl \u2014 every value is now a [main, aux] pair
1305
+ // (see src/util/f64pack.mjs) and every \`+\`/\`+=\` is computeSum via addPair
1306
+ // instead of plain f32 addition. Concatenated after f64add.wgsl by
1307
+ // getPipeline (WGSL has no #include), reusing its decode/encode/computeSum/
1308
+ // addFields and Packed struct \u2014 f64add.wgsl declares no bindings and no entry
1309
+ // point of its own (just helper functions), so bindings here start at 0 and
1310
+ // the entry point is simply \`dasum_main\`.
1311
+ //
1312
+ // xAux/partialsAux are array<u32>, not array<f32> \u2014 aux's bits must never
1313
+ // pass through an f32-typed storage slot (NaN-bit-pattern corruption risk,
1314
+ // see f64pack.mjs and the Packed struct comment above decode()/encode() in
1315
+ // f64add.wgsl); Packed (from f64add.wgsl) keeps aux as u32 in registers/
1316
+ // workgroup memory too.
1317
+ //
1318
+ // Per-thread accumulation (acc0..acc3) stays in DECODED Fields form for the
1319
+ // entire strided loop below, via addFields \u2014 not re-encoded to Packed and
1320
+ // re-decoded on every single element like a naive version would. Only the
1321
+ // freshly-loaded x[idx] needs decoding each iteration (unavoidable, it's new
1322
+ // data every time); the running total never leaves Fields form until the
1323
+ // four accumulators are combined and encoded exactly once, right before
1324
+ // writing into workgroup-shared \`tile\`. The cross-thread reduction tree
1325
+ // after that still goes through Packed per level (unavoidable \u2014 each level
1326
+ // combines values that live in different threads' registers via shared
1327
+ // memory), but that's a fixed 6 levels regardless of n, unlike the strided
1328
+ // loop above whose iteration count scales with n.
1329
+
1330
+ @group(0) @binding(0) var<storage, read> xMain: array<f32>;
1331
+ @group(0) @binding(1) var<storage, read> xAux: array<u32>;
1332
+ @group(0) @binding(2) var<storage, read_write> partialsMain: array<f32>;
1333
+ @group(0) @binding(3) var<storage, read_write> partialsAux: array<u32>;
1334
+ @group(0) @binding(4) var<uniform> params: Params;
1335
+
1336
+ struct Params {
1337
+ n: u32,
1338
+ x_inc: u32,
1339
+ }
1340
+
1341
+ const WGS: u32 = 64;
1342
+
1343
+ var<workgroup> tile: array<Packed, 64>;
1344
+
1345
+ // a + b, where a/b are [main, aux] pairs \u2014 computeSum takes decoded Fields.
1346
+ // Only used for the cross-thread reduction tree below; the per-thread
1347
+ // strided loop uses addFields directly instead (see module comment).
1348
+ fn addPair(a: Packed, b: Packed) -> Packed {
1349
+ return computeSum(decode(bitcast<u32>(a.main), a.aux), decode(bitcast<u32>(b.main), b.aux));
1350
+ }
1351
+
1352
+ // |x| for a packed double is abs(main) with aux untouched \u2014 only main's
1353
+ // sign bit carries the double's sign (see fieldsToPacked() in f64pack.mjs).
1354
+ // Returns decoded Fields directly (not Packed) for the per-thread loop.
1355
+ fn absFields(idx: u32) -> Fields {
1356
+ return decode(bitcast<u32>(abs(xMain[idx])), xAux[idx]);
1357
+ }
1358
+
1359
+ @compute @workgroup_size(64)
1360
+ fn dasum_main(
1361
+ @builtin(global_invocation_id) gid: vec3u,
1362
+ @builtin(local_invocation_id) lid: vec3u,
1363
+ @builtin(workgroup_id) wgid: vec3u,
1364
+ @builtin(num_workgroups) num_wg: vec3u,
1365
+ ) {
1366
+ var acc0: Fields = Fields(0u, 0u, 0u, 0u);
1367
+ var acc1: Fields = Fields(0u, 0u, 0u, 0u);
1368
+ var acc2: Fields = Fields(0u, 0u, 0u, 0u);
1369
+ var acc3: Fields = Fields(0u, 0u, 0u, 0u);
1370
+
1371
+ let stride = num_wg.x * WGS;
1372
+ let n4_floor = (params.n / (4u * stride)) * (4u * stride);
1373
+
1374
+ for (var id = gid.x; id < n4_floor; id += 4u * stride) {
1375
+ acc0 = addFields(acc0, absFields( id * params.x_inc));
1376
+ acc1 = addFields(acc1, absFields((id + stride) * params.x_inc));
1377
+ acc2 = addFields(acc2, absFields((id + 2u * stride) * params.x_inc));
1378
+ acc3 = addFields(acc3, absFields((id + 3u * stride) * params.x_inc));
1379
+ }
1380
+ for (var id = n4_floor + gid.x; id < params.n; id += stride) {
1381
+ acc0 = addFields(acc0, absFields(id * params.x_inc));
1382
+ }
1383
+
1384
+ // Combine the 4 per-thread accumulators in Fields form too \u2014 still no
1385
+ // encode/decode needed, since none of them have touched Packed yet.
1386
+ let combined = addFields(addFields(acc0, acc1), addFields(acc2, acc3));
1387
+ tile[lid.x] = encode(combined.sign, combined.rawExp, combined.mantissaHi, combined.lo);
1388
+ workgroupBarrier();
1389
+
1390
+ for (var s = WGS / 2u; s > 0u; s >>= 1u) {
1391
+ if (lid.x < s) { tile[lid.x] = addPair(tile[lid.x], tile[lid.x + s]); }
1392
+ workgroupBarrier();
1393
+ }
1394
+
1395
+ if (lid.x == 0u) {
1396
+ partialsMain[wgid.x] = tile[0].main;
1397
+ partialsAux[wgid.x] = tile[0].aux;
1398
+ }
1399
+ }
1400
+ `});var Be,Ae=I(()=>{Be=`// strsv_invert_block: computes ONE column (workgroup_id.x) of ONE block's
1401
+ // (workgroup_id.y) explicit inverse, via the same one-row-at-a-time
1402
+ // substitution as strsv_block.wgsl, but solving against a unit basis vector
1403
+ // e_col instead of the real right-hand side, and writing to a dense
1404
+ // (BLOCK_SIZE x BLOCK_SIZE, row-major) scratch buffer per block instead of
1405
+ // mutating x. Dispatched once for the whole matrix (2D: BLOCK_SIZE columns x
1406
+ // numBlocks), fully in parallel -- unlike the sequential per-block main
1407
+ // loop in strsv.mjs, no block's inverse depends on any other block or on x.
1408
+ //
1409
+ // A triangular block's inverse is itself triangular: forward (effectively-
1410
+ // lower, e.g. no-trans+lower) blocks have inverse column col nonzero only
1411
+ // for row>=col, solved in increasing row order; backward (effectively-
1412
+ // upper) blocks have it nonzero only for row<=col, solved in decreasing
1413
+ // order. Rows outside a column's nonzero range are written as literal 0 \u2014
1414
+ // strsv_apply_inverse.wgsl's dense matvec depends on that, not just on
1415
+ // those entries being mathematically implied zero.
1416
+
1417
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
1418
+ @group(0) @binding(1) var<storage, read_write> Ainv: array<f32>;
1419
+
1420
+ struct Params {
1421
+ n: u32,
1422
+ lda: u32,
1423
+ trans: u32, // 0 = no-transpose, 1 = transpose
1424
+ uplo: u32, // 0 = lower, 1 = upper
1425
+ diag: u32, // 0 = non-unit, 1 = unit
1426
+ }
1427
+
1428
+ @group(0) @binding(2) var<uniform> params: Params;
1429
+
1430
+ const WGS: u32 = 64u;
1431
+ const BLOCK_SIZE: u32 = 64u;
1432
+ var<workgroup> scratch: array<f32, 64>;
1433
+
1434
+ fn readA(i: u32, j: u32) -> f32 {
1435
+ if params.trans == 0u {
1436
+ return A[i * params.lda + j];
1437
+ } else {
1438
+ return A[j * params.lda + i];
1439
+ }
1440
+ }
1441
+
1442
+ @compute @workgroup_size(64)
1443
+ fn strsv_invert_block_main(
1444
+ @builtin(workgroup_id) wgid: vec3u,
1445
+ @builtin(local_invocation_id) lid: vec3u,
1446
+ ) {
1447
+ let col = wgid.x;
1448
+ let blockIndex = wgid.y;
1449
+ let blockStart = blockIndex * BLOCK_SIZE;
1450
+ var blockEnd = blockStart + BLOCK_SIZE;
1451
+ if (blockEnd > params.n) { blockEnd = params.n; }
1452
+ let blockLen = blockEnd - blockStart;
1453
+
1454
+ if (col >= blockLen) { return; }
1455
+
1456
+ let ainvBase = blockIndex * BLOCK_SIZE * BLOCK_SIZE;
1457
+ let forward = (params.trans == 0u) == (params.uplo == 0u);
1458
+
1459
+ if forward {
1460
+ for (var r = lid.x; r < col; r += WGS) {
1461
+ Ainv[ainvBase + r * BLOCK_SIZE + col] = 0.0;
1462
+ }
1463
+ } else {
1464
+ for (var r = col + 1u + lid.x; r < blockLen; r += WGS) {
1465
+ Ainv[ainvBase + r * BLOCK_SIZE + col] = 0.0;
1466
+ }
1467
+ }
1468
+ storageBarrier();
1469
+ workgroupBarrier();
1470
+
1471
+ let numSteps = select(col + 1u, blockLen - col, forward);
1472
+ for (var step = 0u; step < numSteps; step++) {
1473
+ let localRow = select(col - step, col + step, forward);
1474
+ let i = blockStart + localRow;
1475
+
1476
+ var acc = 0.0f;
1477
+ if forward {
1478
+ for (var lj = col + lid.x; lj < localRow; lj += WGS) {
1479
+ acc += readA(i, blockStart + lj) * Ainv[ainvBase + lj * BLOCK_SIZE + col];
1480
+ }
1481
+ } else {
1482
+ for (var lj = localRow + 1u + lid.x; lj <= col; lj += WGS) {
1483
+ acc += readA(i, blockStart + lj) * Ainv[ainvBase + lj * BLOCK_SIZE + col];
1484
+ }
1485
+ }
1486
+
1487
+ scratch[lid.x] = acc;
1488
+ workgroupBarrier();
1489
+ for (var stride = WGS >> 1u; stride > 0u; stride >>= 1u) {
1490
+ if lid.x < stride { scratch[lid.x] += scratch[lid.x + stride]; }
1491
+ workgroupBarrier();
1492
+ }
1493
+
1494
+ if lid.x == 0u {
1495
+ let e = select(0.0, 1.0, localRow == col);
1496
+ let rhs = e - scratch[0];
1497
+ var val: f32;
1498
+ if params.diag == 1u {
1499
+ val = rhs;
1500
+ } else {
1501
+ val = rhs / A[i * params.lda + i];
1502
+ }
1503
+ Ainv[ainvBase + localRow * BLOCK_SIZE + col] = val;
1504
+ }
1505
+ storageBarrier();
1506
+ workgroupBarrier();
1507
+ }
1508
+ }
1509
+ `});var Pe,ke=I(()=>{Pe=`// strsv_apply_inverse: given a precomputed block inverse (from
1510
+ // strsv_invert_block.wgsl), computes this block's solution as a dense
1511
+ // matrix-vector multiply against the block's current remainder in x \u2014
1512
+ // replacing what the old strsv_block.wgsl did via a genuinely sequential,
1513
+ // barrier-per-row substitution.
1514
+ //
1515
+ // All blockLen rows are computed in parallel within a single workgroup: the
1516
+ // remainder is loaded into workgroup-shared memory once, then each thread
1517
+ // independently computes one full row's dot product from that shared copy.
1518
+ // No further synchronization is needed after the load \u2014 every thread only
1519
+ // reads shared memory from then on (never written again within this call)
1520
+ // and writes a distinct element of x, so there's no cross-thread hazard to
1521
+ // guard against.
1522
+
1523
+ @group(0) @binding(0) var<storage, read> Ainv: array<f32>;
1524
+ @group(0) @binding(1) var<storage, read_write> x: array<f32>;
1525
+
1526
+ struct Params {
1527
+ incx: u32,
1528
+ blockIndex: u32,
1529
+ blockStart: u32,
1530
+ blockEnd: u32,
1531
+ }
1532
+
1533
+ @group(0) @binding(2) var<uniform> params: Params;
1534
+
1535
+ const BLOCK_SIZE: u32 = 64u;
1536
+ var<workgroup> xLocal: array<f32, 64>;
1537
+
1538
+ @compute @workgroup_size(64)
1539
+ fn strsv_apply_inverse_main(@builtin(local_invocation_id) lid: vec3u) {
1540
+ let blockLen = params.blockEnd - params.blockStart;
1541
+
1542
+ if (lid.x < blockLen) {
1543
+ xLocal[lid.x] = x[(params.blockStart + lid.x) * params.incx];
1544
+ }
1545
+ workgroupBarrier();
1546
+
1547
+ if (lid.x >= blockLen) { return; }
1548
+
1549
+ let ainvBase = params.blockIndex * BLOCK_SIZE * BLOCK_SIZE;
1550
+ var acc = 0.0f;
1551
+ for (var j = 0u; j < blockLen; j++) {
1552
+ acc += Ainv[ainvBase + lid.x * BLOCK_SIZE + j] * xLocal[j];
1553
+ }
1554
+ x[(params.blockStart + lid.x) * params.incx] = acc;
1555
+ }
1556
+ `});var Fe,Se=I(()=>{Fe=`// strsv_update: subtracts a solved block's contribution from every
1557
+ // remaining row in parallel (one workgroup per row, like strmv.wgsl) \u2014
1558
+ // this is what turns strsv's O(n) sequential stages into O(n/blockSize).
1559
+ // No diag/masking needed: this region never touches the diagonal.
1560
+
1561
+ @group(0) @binding(0) var<storage, read> A: array<f32>;
1562
+ @group(0) @binding(1) var<storage, read_write> x: array<f32>;
1563
+
1564
+ struct Params {
1565
+ n: u32,
1566
+ incx: u32,
1567
+ lda: u32,
1568
+ trans: u32, // 0 = no-transpose, 1 = transpose
1569
+ uplo: u32, // 0 = lower, 1 = upper
1570
+ blockStart: u32,
1571
+ blockEnd: u32, // exclusive
1572
+ }
1573
+
1574
+ @group(0) @binding(2) var<uniform> params: Params;
1575
+
1576
+ const WGS: u32 = 64u;
1577
+ var<workgroup> scratch: array<f32, 64>;
1578
+
1579
+ @compute @workgroup_size(64)
1580
+ fn strsv_update_main(
1581
+ @builtin(workgroup_id) wgid: vec3u,
1582
+ @builtin(local_invocation_id) lid: vec3u,
1583
+ @builtin(num_workgroups) nwg: vec3u,
1584
+ ) {
1585
+ // forward: remaining rows are [blockEnd,n); backward: [0,blockStart).
1586
+ let forward = (params.trans == 0u) == (params.uplo == 0u);
1587
+
1588
+ var rangeStart: u32;
1589
+ var rangeEnd: u32;
1590
+
1591
+ if forward {
1592
+ rangeStart = params.blockEnd;
1593
+ rangeEnd = params.n;
1594
+ } else {
1595
+ rangeStart = 0u;
1596
+ rangeEnd = params.blockStart;
1597
+ }
1598
+
1599
+ if (rangeStart >= rangeEnd) { return; }
1600
+ let count = rangeEnd - rangeStart;
1601
+
1602
+ for (var idx = wgid.x; idx < count; idx += nwg.x) {
1603
+ let i = rangeStart + idx;
1604
+
1605
+ // No-trans reads A[i,j]; transpose reads A[j,i] \u2014 uplo only sets the range above.
1606
+ var acc = 0.0f;
1607
+ if params.trans == 0u {
1608
+ for (var j = params.blockStart + lid.x; j < params.blockEnd; j += WGS) {
1609
+ acc += A[i * params.lda + j] * x[j * params.incx];
1610
+ }
1611
+ } else {
1612
+ for (var j = params.blockStart + lid.x; j < params.blockEnd; j += WGS) {
1613
+ acc += A[j * params.lda + i] * x[j * params.incx];
1614
+ }
1615
+ }
1616
+
1617
+ // Parallel reduction: 64 \u2192 1
1618
+ scratch[lid.x] = acc;
1619
+ workgroupBarrier();
1620
+ for (var stride = WGS >> 1u; stride > 0u; stride >>= 1u) {
1621
+ if lid.x < stride { scratch[lid.x] += scratch[lid.x + stride]; }
1622
+ workgroupBarrier();
1623
+ }
1624
+
1625
+ if lid.x == 0u {
1626
+ x[i * params.incx] -= scratch[0];
1627
+ }
1628
+ workgroupBarrier();
1629
+ }
1630
+ }
1631
+ `});var je={};yr(je,{shaderSources:()=>Kt});var Kt,Le=I(()=>{Ir();Ur();Vr();Hr();Cr();zr();qr();Kr();$r();Jr();ee();ae();ie();se();le();ce();de();ge();be();xe();ye();Ee();Ae();ke();Se();Kt={"reduction/argmax":Mr,"reduction/sum":Tr,"reduction/sumF64":Rr,sscal:Dr,sswap:Or,saxpy:Qr,scopy:Zr,sdot:Xr,sasum:Yr,snrm2:re,srot:te,srotm:oe,isamax:ne,sgemv_n:ue,sgemv_t:fe,ssymv:me,strmv:pe,sger:we,ssyr:he,ssyr2:ve,f64add:_e,dasum:Ge,strsv_invert_block:Be,strsv_apply_inverse:Pe,strsv_update:Fe}});var ra={};yr(ra,{GpuMatrix:()=>H,GpuVector:()=>x,cleanup:()=>Pr,dasum:()=>De,gpuName:()=>Sr,init:()=>kr,isamax:()=>ze,randomFloat32Array:()=>Nr,randomFloat64Array:()=>Wr,sasum:()=>He,saxpy:()=>Me,scopy:()=>Ue,sdot:()=>Ve,sgemv:()=>Ze,sger:()=>rt,snrm2:()=>Oe,srot:()=>Qe,srotm:()=>qe,sscal:()=>We,sswap:()=>Ie,ssymv:()=>Ke,ssyr:()=>et,ssyr2:()=>tt,strmv:()=>Xe,strsv:()=>Je});function Er(a,r){return r?a.features.has("timestamp-query")?{requiredFeatures:["timestamp-query"]}:(console.warn("timestamp-query not supported on this device \u2014 benchmark mode disabled."),{}):{}}function Gr(){if(!Ar())return{querySet:null,passDescriptor:void 0};let r=V().createQuerySet({type:"timestamp",count:2});return{querySet:r,passDescriptor:{timestampWrites:{querySet:r,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1}}}}function cr(a,r){if(!r)return null;let e=V(),o=e.createBuffer({label:"timestamp-resolve",size:16,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC});a.resolveQuerySet(r,0,2,o,0);let t=e.createBuffer({label:"timestamp-readback",size:16,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});return a.copyBufferToBuffer(o,0,t,0,16),{tsReadBuffer:t,resolveBuffer:o,querySet:r}}async function P(a){if(!a)return;let{tsReadBuffer:r,resolveBuffer:e,querySet:o}=a;await r.mapAsync(GPUMapMode.READ);let t=new BigInt64Array(r.getMappedRange().slice());return r.unmap(),r.destroy(),e.destroy(),o.destroy(),Math.max(0,Number(t[1]-t[0]))/1e6}var Z=null,J=null,Br=null,dr=!1;async function kr({powerPreference:a="high-performance",benchmark:r=!1}={}){if(Z)return Z;let e;if(typeof window>"u"){let{create:i,globals:n}=await import("webgpu");Object.assign(globalThis,n),e=i([]),Br=e}else e=navigator.gpu;if(!e)throw new Error("WebGPU not supported in this environment.");if(J=await e.requestAdapter({powerPreference:a})??await e.requestAdapter(),!J)throw new Error("No WebGPU adapter found.");dr=r;let t=[...Er(J,r).requiredFeatures??[]];return Z=await J.requestDevice({requiredFeatures:t}),Z.addEventListener("uncapturederror",i=>{console.error("Uncaptured GPU error:",i.error.message)}),Z}function Pr(){Z&&(Z.destroy(),Z=null),J=null,Br=null,dr=!1}function Sr(){if(!J)throw new Error("WebGPU adapter not initialized \u2014 call init() first.");let{device:a,description:r}=J.info;return{description:r||"unknown",device:a||"unknown"}}function Ar(){return dr}function V(){if(!Z)throw new Error("WebGPU device not initialized \u2014 call init() first.");return Z}function d(...a){a.flat().forEach(r=>r.destroy())}function b(a,r="blas-input",e=!1){let o=V(),t=o.limits.maxStorageBufferBindingSize,i=a.byteLength;if(i>t)throw new Error(`Buffer size ${i} bytes exceeds device limit of ${t} bytes.`);let n=e?GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC:GPUBufferUsage.STORAGE,u=o.createBuffer({label:r,size:i,usage:n,mappedAtCreation:!0}),s=a.constructor;return new s(u.getMappedRange()).set(a),u.unmap(),u}function D(a,r="blas-storage"){return V().createBuffer({label:r,size:a,usage:GPUBufferUsage.STORAGE})}function q(a,r="blas-result"){return V().createBuffer({label:r,size:a,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC})}function E(a,r){let o=V().createBuffer({label:"blas-readback",size:r.size,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});return a.copyBufferToBuffer(r,0,o,0,r.size),o}function N(a,r="blas-params"){let e=V(),o=a.length*4,t=Math.ceil(o/16)*16,i=new ArrayBuffer(t),n=new DataView(i);a.forEach(({value:s,type:l},f)=>{let c=f*4;if(l==="u32")n.setUint32(c,s,!0);else if(l==="i32")n.setInt32(c,s,!0);else if(l==="f32")n.setFloat32(c,s,!0);else throw new Error(`Unknown param type "${l}". Use "f32", "u32", or "i32".`)});let u=e.createBuffer({label:r,size:t,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});return e.queue.writeBuffer(u,0,i),u}async function _(a,r=Float32Array){try{await a.mapAsync(GPUMapMode.READ);let e=new r(a.getMappedRange().slice());return a.unmap(),e}finally{a.destroy()}}var bt=new ArrayBuffer(8),er=new DataView(bt),Fr=new ArrayBuffer(4),jr=new Uint32Array(Fr),Lr=new Float32Array(Fr);function ht(a){return jr[0]=a>>>0,Lr[0]}function xt(a){return Lr[0]=a,jr[0]}function vt(a,r,e,o){let t=r>>>3,i=r&7,n=o>>>29,u=e<<3|n,s=o&536870911,l=a<<31|t<<23|u,f=i>>>2&1,c=i&3,p=s>>>23,m=s&8388607,g=c<<6|p,w=(f<<31|g<<23|m)>>>0;return[ht(l),w]}function yt(a,r){let e=xt(a);r=r>>>0;let o=e>>>31,t=e>>>23&255,i=e&8388607,n=r>>>31,u=r>>>23&255,s=r&8388607,l=n<<2|u>>>6,f=(u&63)<<23|s,c=t<<3|l,p=i>>>3,g=((i&7)<<29|f)>>>0;return{sign:o,rawExp:c,mantissaHi:p,lo:g}}var _t=2040;function mr(a){er.setFloat64(0,a,!1);let r=er.getUint32(0,!1),e=er.getUint32(4,!1),o=r>>>31,t=r>>>20&2047,i=r&1048575;if(t>=_t)throw new RangeError(`packF64: |${a}| is too large to pack safely (must be finite with magnitude below ~1.4e306); main's bit pattern would itself be NaN/Infinity-shaped and get silently corrupted by any real float32 round-trip`);return vt(o,t,i,e)}function tr(a,r){let{sign:e,rawExp:o,mantissaHi:t,lo:i}=yt(a,r),n=(e<<31|o<<20|t)>>>0;return er.setUint32(0,n,!1),er.setUint32(4,i,!1),er.getFloat64(0,!1)}var x=class a{constructor(r,e,o=Float32Array,t=null){this._buf=r,this._auxBuf=t,this.length=e,this.dtype=o}static from(r){if(r instanceof Float64Array){let o=new Float32Array(r.length),t=new Uint32Array(r.length);for(let u=0;u<r.length;u++){let s=mr(r[u]);o[u]=s[0],t[u]=s[1]}let i=b(o,"gpu-vector-f64-main",!0),n=b(t,"gpu-vector-f64-aux",!0);return new a(i,r.length,Float64Array,n)}if(!(r instanceof Float32Array))throw new Error("GpuVector.from expects a Float32Array or Float64Array.");let e=b(r,"gpu-vector",!0);return new a(e,r.length,r.constructor)}async read(){let r=V(),e=r.createCommandEncoder(),o=E(e,this._buf);if(r.queue.submit([e.finish()]),!this._auxBuf)return _(o,this.dtype);let t=r.createCommandEncoder(),i=E(t,this._auxBuf);r.queue.submit([t.finish()]);let[n,u]=await Promise.all([_(o,Float32Array),_(i,Uint32Array)]),s=new Float64Array(this.length);for(let l=0;l<this.length;l++)s[l]=tr(n[l],u[l]);return s}destroy(){this._buf.destroy(),this._auxBuf&&this._auxBuf.destroy()}};var H=class a{constructor(r,e,o,t,i=null,n="row-major"){this._buf=r,this._auxBuf=i,this.rows=e,this.cols=o,this.lda=t,this.layout=n}static from(r,e,o,t,i="row-major"){if(i!=="row-major"&&i!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");let n=i==="row-major";if(t===void 0&&(t=n?o:e),!(r instanceof Float32Array)&&!(r instanceof Float64Array))throw new Error("GpuMatrix.from expects a Float32Array or Float64Array.");if(!Number.isInteger(e)||e<=0)throw new Error("rows must be a positive integer.");if(!Number.isInteger(o)||o<=0)throw new Error("cols must be a positive integer.");let u=n?o:e;if(!Number.isInteger(t)||t<u)throw new Error(`lda must be an integer >= ${n?"cols":"rows"}.`);let s=n?e:o;if(r.length<s*t)throw new Error("data does not have enough elements for the given rows, cols, and lda.");if(r instanceof Float64Array){let f=s*t,c=new Float32Array(f),p=new Uint32Array(f);for(let w=0;w<f;w++){let y=mr(r[w]);c[w]=y[0],p[w]=y[1]}let m=b(c,"gpu-matrix-f64-main",!0),g=b(p,"gpu-matrix-f64-aux",!0);return new a(m,e,o,t,g,i)}let l=b(r.subarray(0,s*t),"gpu-matrix",!0);return new a(l,e,o,t,null,i)}async read(){let r=V(),e=r.createCommandEncoder(),o=E(e,this._buf);r.queue.submit([e.finish()]);let t=this.layout!=="column-major",i=t?this.rows:this.cols,n=t?this.cols:this.rows;if(this._auxBuf){let l=r.createCommandEncoder(),f=E(l,this._auxBuf);r.queue.submit([l.finish()]);let[c,p]=await Promise.all([_(o,Float32Array),_(f,Uint32Array)]),m=new Float64Array(i*this.lda);for(let w=0;w<m.length;w++)m[w]=tr(c[w],p[w]);if(this.lda===n)return m;let g=new Float64Array(i*n);for(let w=0;w<i;w++)g.set(m.subarray(w*this.lda,w*this.lda+n),w*n);return g}let u=await _(o,Float32Array);if(this.lda===n)return u;let s=new Float32Array(i*n);for(let l=0;l<i;l++)s.set(u.subarray(l*this.lda,l*this.lda+n),l*n);return s}destroy(){this._buf.destroy(),this._auxBuf&&this._auxBuf.destroy()}};function Nr(a,r=-1,e=1){let o=new Float32Array(a);for(let t=0;t<a;t++)o[t]=r+Math.random()*(e-r);return o}function Wr(a,r=-1,e=1){let o=new Float64Array(a);for(let t=0;t<a;t++)o[t]=r+Math.random()*(e-r);return o}function A(a,r,e=0){let o=V(),t=r.map((i,n)=>({binding:e+n,resource:i instanceof GPUBuffer?{buffer:i}:i}));return o.createBindGroup({layout:a,entries:t})}var Et=new WeakMap;function S(a){V().queue.submit([a.finish()])}function pr(){let a=V(),{querySet:r,passDescriptor:e}=Gr();return{commandEncoder:a.createCommandEncoder(),querySet:r,passDescriptor:e}}function ir(a,r,e,o,t){let i=a.beginComputePass(t);i.setPipeline(r),i.setBindGroup(0,e),typeof o=="number"?i.dispatchWorkgroups(o):i.dispatchWorkgroups(o.x,o.y),i.end(),Et.set(a,i)}function L(a,r,e){let{commandEncoder:o,querySet:t,passDescriptor:i}=pr();ir(o,a,r,e,i);let n=cr(o,t);return{commandEncoder:o,ts:n}}var Yt={},gr=new WeakMap;async function B(a,r,e="main"){gr.has(a)||gr.set(a,new Map);let o=gr.get(a),t=Array.isArray(r)?r:[r],i=`${t.join("+")}::${e}`;return o.has(i)||o.set(i,await $t(t,e)),o.get(i)}async function Xt(a){if(typeof process>"u"||!process.versions?.node){let{shaderSources:r}=await Promise.resolve().then(()=>(Le(),je)),e=r[a];if(!e)throw new Error(`Shader "${a}" not found in browser bundle.`);return e}else{let{readFileSync:r}=await import("fs"),{fileURLToPath:e}=await import("url"),{dirname:o,join:t}=await import("path"),i=o(e(Yt.url));return r(t(i,`../shaders/${a}.wgsl`),"utf8")}}async function $t(a,r="main"){let e=V(),o=a.join("+"),t=(await Promise.all(a.map(Xt))).join(`
1632
+ `),i=e.createShaderModule({label:o,code:t}),u=(await i.getCompilationInfo()).messages.filter(f=>f.type==="error");if(u.length>0)throw new Error(`Shader "${o}" compilation failed:
1633
+ ${u.map(f=>` line ${f.lineNum}: ${f.message}`).join(`
1634
+ `)}`);let s=r==="main"?{module:i}:{module:i,entryPoint:r},l=e.createComputePipeline({label:o,layout:"auto",compute:s});return l._shaderModule=i,l}var Jt=64,Ne=8;function C(a,r){let e=V().limits.maxComputeWorkgroupsPerDimension;return r===void 0?Math.min(Math.ceil(a/Jt),e):{x:Math.min(Math.ceil(r/Ne),e),y:Math.min(Math.ceil(a/Ne),e)}}async function We(a,r,e,o,t){let i=o instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(t))throw new Error("n and incx must be integers.");if(typeof e!="number")throw new Error("alpha must be a number.");if(Number.isNaN(e))throw new Error("alpha must not be NaN.");if(!Number.isFinite(e))throw new Error("alpha must be finite.");if(t<=0)throw new Error("incx must be positive.");if(!(o instanceof Float32Array)&&!(o instanceof x))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return i?{}:o;if(o.length<(r-1)*t+1)throw new Error("x does not have enough elements for the given n and incx.");let n=await B(a,"sscal"),u=null,s=null,l=null;try{u=i?o._buf:b(o,"sscal-x",!0),s=N([{value:r,type:"u32"},{value:e,type:"f32"},{value:t,type:"u32"}],"sscal-params");let f=A(n.getBindGroupLayout(0),[u,s]),{commandEncoder:c,ts:p}=L(n,f,C(r));l=i?null:E(c,u),S(c);let m=await P(p);if(i)return m!==void 0?{gpuTimeMs:m}:{};let g=await _(l,Float32Array);return l=null,m!==void 0?{x:g,gpuTimeMs:m}:g}finally{!i&&u&&d(u),s&&d(s),l&&d(l)}}async function Ie(a,r,e,o,t,i){let n=e instanceof x,u=t instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(i))throw new Error("n, incx, and incy must be integers.");if(o<=0||i<=0)throw new Error("incx and incy must be positive.");if(!(e instanceof Float32Array)&&!(e instanceof x))throw new Error("x must be a Float32Array or GpuVector.");if(!(t instanceof Float32Array)&&!(t instanceof x))throw new Error("y must be a Float32Array or GpuVector.");if(e.constructor!==t.constructor)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return n?{}:{x:e,y:t};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(t.length<(r-1)*i+1)throw new Error("y does not have enough elements for the given n and incy.");let s=await B(a,"sswap"),l=null,f=null,c=null,p=null,m=null;try{l=n?e._buf:b(e,"sswap-x",!0),f=u?t._buf:b(t,"sswap-y",!0),c=N([{value:r,type:"u32"},{value:o,type:"u32"},{value:i,type:"u32"}],"sswap-params");let g=A(s.getBindGroupLayout(0),[l,f,c]),{commandEncoder:w,ts:y}=L(s,g,C(r));p=n?null:E(w,l),m=u?null:E(w,f),S(w);let h=await P(y);if(n&&u)return h!==void 0?{gpuTimeMs:h}:{};let G=await _(p,Float32Array);p=null;let v=await _(m,Float32Array);return m=null,h!==void 0?{x:G,y:v,gpuTimeMs:h}:{x:G,y:v}}finally{!n&&l&&d(l),!u&&f&&d(f),c&&d(c),p&&d(p),m&&d(m)}}async function Me(a,r,e,o,t,i,n){let u=o instanceof x,s=i instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(t)||!Number.isInteger(n))throw new Error("n, incx, and incy must be integers.");if(typeof e!="number")throw new Error("alpha must be a number.");if(Number.isNaN(e))throw new Error("alpha must not be NaN.");if(!Number.isFinite(e))throw new Error("alpha must be finite.");if(t<=0||n<=0)throw new Error("incx and incy must be positive.");if(!u&&!(o instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!s&&!(i instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(u!==s)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return s?{}:{y:i};if(o.length<(r-1)*t+1)throw new Error("x does not have enough elements for the given n and incx.");if(i.length<(r-1)*n+1)throw new Error("y does not have enough elements for the given n and incy.");let l=await B(a,"saxpy"),f=null,c=null,p=null,m=null;try{f=u?o._buf:b(o,"saxpy-x",!1),c=s?i._buf:b(i,"saxpy-y",!0),p=N([{value:r,type:"u32"},{value:e,type:"f32"},{value:t,type:"u32"},{value:n,type:"u32"}],"saxpy-params");let g=A(l.getBindGroupLayout(0),[f,c,p]),{commandEncoder:w,ts:y}=L(l,g,C(r));m=s?null:E(w,c),S(w);let h=await P(y);if(s&&u)return h!==void 0?{gpuTimeMs:h}:{};let G=await _(m,Float32Array);return m=null,h!==void 0?{y:G,gpuTimeMs:h}:{y:G}}finally{!u&&f&&d(f),!s&&c&&d(c),p&&d(p),m&&d(m)}}async function Ue(a,r,e,o,t,i){let n=e instanceof x,u=t instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(i))throw new Error("n, incx, and incy must be integers.");if(o<=0||i<=0)throw new Error("incx and incy must be positive.");if(!n&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!u&&!(t instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(n!==u)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return u?{}:{y:t};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(t.length<(r-1)*i+1)throw new Error("y does not have enough elements for the given n and incy.");let s=await B(a,"scopy"),l=null,f=null,c=null,p=null;try{l=n?e._buf:b(e,"scopy-x",!1),f=u?t._buf:b(t,"scopy-y",!0),c=N([{value:r,type:"u32"},{value:o,type:"u32"},{value:i,type:"u32"}],"scopy-params");let m=A(s.getBindGroupLayout(0),[l,f,c]),{commandEncoder:g,ts:w}=L(s,m,C(r));p=u?null:E(g,f),S(g);let y=await P(w);if(u&&n)return y!==void 0?{gpuTimeMs:y}:{};let h=await _(p,Float32Array);return p=null,y!==void 0?{y:h,gpuTimeMs:y}:{y:h}}finally{!n&&l&&d(l),!u&&f&&d(f),c&&d(c),p&&d(p)}}var Te=64;async function Ve(a,r,e,o,t,i){let n=e instanceof x,u=t instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(i))throw new Error("n, incx, and incy must be integers.");if(o<=0||i<=0)throw new Error("incx and incy must be positive.");if(!n&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!u&&!(t instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(n!==u)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return{dot:0};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(t.length<(r-1)*i+1)throw new Error("y does not have enough elements for the given n and incy.");let s=await B(a,"sdot"),l=await B(a,"reduction/sum"),f=null,c=null,p=null,m=null,g=null,w=null;try{f=n?e._buf:b(e,"sdot-x",!1),c=u?t._buf:b(t,"sdot-y",!1),p=D(2*Te*4,"sdot-partials"),m=q(4,"sdot-result"),g=N([{value:r,type:"u32"},{value:o,type:"u32"},{value:i,type:"u32"}],"sdot-params");let y=A(s.getBindGroupLayout(0),[f,c,p,g]),{commandEncoder:h,ts:G}=L(s,y,2*Te);S(h);let v=A(l.getBindGroupLayout(0),[p,m]),{commandEncoder:F,ts:k}=L(l,v,1);w=E(F,m),S(F);let j=_(w,Float32Array);w=null;let[W,M,U]=await Promise.all([P(G),P(k),j]);return W!==void 0&&M!==void 0?{dot:U[0],gpuTimeMs:W+M}:{dot:U[0]}}finally{!n&&f&&d(f),!u&&c&&d(c),p&&d(p),m&&d(m),g&&d(g),w&&d(w)}}var Re=64;async function He(a,r,e,o){let t=e instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o))throw new Error("n and incx must be integers.");if(o<=0)throw new Error("incx must be positive.");if(!t&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{asum:0};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");let i=await B(a,"sasum"),n=await B(a,"reduction/sum"),u=null,s=null,l=null,f=null,c=null;try{u=t?e._buf:b(e,"sasum-x",!1),s=D(2*Re*4,"sasum-partials"),l=q(4,"sasum-result"),f=N([{value:r,type:"u32"},{value:o,type:"u32"}],"sasum-params");let p=A(i.getBindGroupLayout(0),[u,s,f]),{commandEncoder:m,ts:g}=L(i,p,2*Re);S(m);let w=A(n.getBindGroupLayout(0),[s,l]),{commandEncoder:y,ts:h}=L(n,w,1);c=E(y,l),S(y);let G=_(c,Float32Array);c=null;let[v,F,k]=await Promise.all([P(g),P(h),G]);return v!==void 0&&F!==void 0?{asum:k[0],gpuTimeMs:v+F}:{asum:k[0]}}finally{!t&&u&&d(u),s&&d(s),l&&d(l),f&&d(f),c&&d(c)}}var wr=64;async function De(a,r,e,o){let t=e instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o))throw new Error("n and incx must be integers.");if(o<=0)throw new Error("incx must be positive.");if(!t&&!(e instanceof Float64Array))throw new Error("x must be a Float64Array or GpuVector.");if(t&&e.dtype!==Float64Array)throw new Error("x must be a Float64Array-backed GpuVector.");if(r<=0)return{asum:0};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");let i=await B(a,["f64add","dasum"]),n=await B(a,["f64add","reduction/sumF64"]),u=null,s=null,l=null,f=null,c=null,p=null,m=null,g=null;try{u=t?e:x.from(e),s=D(2*wr*4,"dasum-partialsMain"),l=D(2*wr*4,"dasum-partialsAux"),f=q(4,"dasum-result-main"),c=q(4,"dasum-result-aux"),p=N([{value:r,type:"u32"},{value:o,type:"u32"}],"dasum-params");let w=A(i.getBindGroupLayout(0),[u._buf,u._auxBuf,s,l,p]),{commandEncoder:y,ts:h}=L(i,w,2*wr);S(y);let G=A(n.getBindGroupLayout(0),[s,l,f,c]),{commandEncoder:v,ts:F}=L(n,G,1);m=E(v,f),g=E(v,c),S(v);let k=_(m,Float32Array),j=_(g,Uint32Array);m=null,g=null;let[W,M,U,T]=await Promise.all([P(h),P(F),k,j]),R=tr(U[0],T[0]);return W!==void 0&&M!==void 0?{asum:R,gpuTimeMs:W+M}:{asum:R}}finally{!t&&u&&u.destroy(),s&&d(s),l&&d(l),f&&d(f),c&&d(c),p&&d(p),m&&d(m),g&&d(g)}}var Ce=64;async function Oe(a,r,e,o){let t=e instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o))throw new Error("n and incx must be integers.");if(o<=0)throw new Error("incx must be positive.");if(!t&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{nrm2:0};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");let i=await B(a,"snrm2"),n=await B(a,"reduction/sum"),u=null,s=null,l=null,f=null,c=null;try{u=t?e._buf:b(e,"snrm2-x",!1),s=D(2*Ce*4,"snrm2-partials"),l=q(4,"snrm2-result"),f=N([{value:r,type:"u32"},{value:o,type:"u32"}],"snrm2-params");let p=A(i.getBindGroupLayout(0),[u,s,f]),{commandEncoder:m,ts:g}=L(i,p,2*Ce);S(m);let w=A(n.getBindGroupLayout(0),[s,l]),{commandEncoder:y,ts:h}=L(n,w,1);c=E(y,l),S(y);let G=_(c,Float32Array);c=null;let[v,F,k]=await Promise.all([P(g),P(h),G]),j=Math.sqrt(k[0]);return v!==void 0&&F!==void 0?{nrm2:j,gpuTimeMs:v+F}:{nrm2:j}}finally{!t&&u&&d(u),s&&d(s),l&&d(l),f&&d(f),c&&d(c)}}var br=64;async function ze(a,r,e,o){let t=e instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o))throw new Error("n and incx must be integers.");if(o<=0)throw new Error("incx must be positive.");if(!t&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(r<=0)return{index:0};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");let i=await B(a,"isamax"),n=await B(a,"reduction/argmax"),u=null,s=null,l=null,f=null,c=null,p=null;try{u=t?e._buf:b(e,"isamax-x",!1),s=D(2*br*4,"isamax-partials-val"),l=D(2*br*4,"isamax-partials-idx"),f=q(4,"isamax-result"),c=N([{value:r,type:"u32"},{value:o,type:"u32"}],"isamax-params");let m=A(i.getBindGroupLayout(0),[u,s,l,c]),{commandEncoder:g,ts:w}=L(i,m,2*br);S(g);let y=A(n.getBindGroupLayout(0),[s,l,f]),{commandEncoder:h,ts:G}=L(n,y,1);p=E(h,f),S(h);let v=_(p,Uint32Array);p=null;let[F,k,j]=await Promise.all([P(w),P(G),v]),W=j[0];return F!==void 0&&k!==void 0?{index:W,gpuTimeMs:F+k}:{index:W}}finally{!t&&u&&d(u),s&&d(s),l&&d(l),f&&d(f),c&&d(c),p&&d(p)}}async function Qe(a,r,e,o,t,i,n,u){let s=e instanceof x,l=t instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(i))throw new Error("n, incx, and incy must be integers.");if(typeof n!="number")throw new Error("c must be a number.");if(typeof u!="number")throw new Error("s must be a number.");if(Number.isNaN(n)||Number.isNaN(u))throw new Error("c and s must not be NaN.");if(!Number.isFinite(n))throw new Error("c must be finite.");if(!Number.isFinite(u))throw new Error("s must be finite.");if(o<=0||i<=0)throw new Error("incx and incy must be positive.");if(!s&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!l&&!(t instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(s!==l)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0)return s?{}:{x:e,y:t};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(t.length<(r-1)*i+1)throw new Error("y does not have enough elements for the given n and incy.");let f=await B(a,"srot"),c=null,p=null,m=null,g=null,w=null;try{c=s?e._buf:b(e,"srot-x",!0),p=l?t._buf:b(t,"srot-y",!0),m=N([{value:r,type:"u32"},{value:n,type:"f32"},{value:u,type:"f32"},{value:o,type:"u32"},{value:i,type:"u32"}],"srot-params");let y=A(f.getBindGroupLayout(0),[c,p,m]),{commandEncoder:h,ts:G}=L(f,y,C(r));g=s?null:E(h,c),w=l?null:E(h,p),S(h);let v=await P(G);if(s&&l)return v!==void 0?{gpuTimeMs:v}:{};let F=_(g,Float32Array),k=_(w,Float32Array);g=null,w=null;let[j,W]=await Promise.all([F,k]);return v!==void 0?{x:j,y:W,gpuTimeMs:v}:{x:j,y:W}}finally{!s&&c&&d(c),!l&&p&&d(p),m&&d(m),g&&d(g),w&&d(w)}}async function qe(a,r,e,o,t,i,n){let u=e instanceof x,s=t instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(!Number.isInteger(r)||!Number.isInteger(o)||!Number.isInteger(i))throw new Error("n, incx, and incy must be integers.");if(!(n instanceof Float32Array)||n.length!==5)throw new Error("param must be a Float32Array of length 5.");if(o<=0||i<=0)throw new Error("incx and incy must be positive.");if(!u&&!(e instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!s&&!(t instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(u!==s)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(r<=0||n[0]===-2)return u?{}:{x:e,y:t};if(e.length<(r-1)*o+1)throw new Error("x does not have enough elements for the given n and incx.");if(t.length<(r-1)*i+1)throw new Error("y does not have enough elements for the given n and incy.");let l=await B(a,"srotm"),f=null,c=null,p=null,m=null,g=null,w=null;try{f=u?e._buf:b(e,"srotm-x",!0),c=s?t._buf:b(t,"srotm-y",!0),p=b(n,"srotm-param",!1),m=N([{value:r,type:"u32"},{value:o,type:"u32"},{value:i,type:"u32"}],"srotm-params");let y=A(l.getBindGroupLayout(0),[f,c,p,m]),{commandEncoder:h,ts:G}=L(l,y,C(r));g=u?null:E(h,f),w=s?null:E(h,c),S(h);let v=await P(G);if(u&&s)return v!==void 0?{gpuTimeMs:v}:{};let F=_(g,Float32Array),k=_(w,Float32Array);g=null,w=null;let[j,W]=await Promise.all([F,k]);return v!==void 0?{x:j,y:W,gpuTimeMs:v}:{x:j,y:W}}finally{!u&&f&&d(f),!s&&c&&d(c),p&&d(p),m&&d(m),g&&d(g),w&&d(w)}}async function Ze(a,r,e,o,t,i,n,u,s,l,f,c,p="row-major"){let m=i instanceof H,g=u instanceof x,w=f instanceof x;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="no-transpose"&&r!=="transpose")throw new Error("trans must be 'no-transpose' or 'transpose'.");if(p!=="row-major"&&p!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(typeof t!="number")throw new Error("alpha must be a number.");if(Number.isNaN(t))throw new Error("alpha must not be NaN.");if(!Number.isFinite(t))throw new Error("alpha must be finite.");if(typeof l!="number")throw new Error("beta must be a number.");if(Number.isNaN(l))throw new Error("beta must not be NaN.");if(!Number.isFinite(l))throw new Error("beta must be finite.");if(!Number.isInteger(e)||!Number.isInteger(o)||!Number.isInteger(s)||!Number.isInteger(c)||!Number.isInteger(n))throw new Error("m, n, incx, incy, and lda must be integers.");if(s<=0||c<=0)throw new Error("incx and incy must be positive.");if(!m&&!(i instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!g&&!(u instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!w&&!(f instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(g!==w)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(g&&!m)throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");if(g&&u._buf===f._buf)throw new Error("x and y must not reference the same GPU buffer when both are GpuVectors.");if(m&&n!==i.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(m&&(i.rows<e||i.cols<o))throw new Error("A is too small for the given m and n.");if(e<0||o<0)throw new Error("m and n must be non-negative.");if(e===0||o===0)return w?{}:{y:f};(m?i.layout:p)==="column-major"&&([e,o]=[o,e],r=r==="no-transpose"?"transpose":"no-transpose");let h=r==="no-transpose",G=h?o:e,v=h?e:o;if(n<o)throw new Error("lda must be >= n.");if(!m&&i.length<(e-1)*n+o)throw new Error("A does not have enough elements for the given m, n, and lda.");if(u.length<(G-1)*s+1)throw new Error("x does not have enough elements for the given dimensions and incx.");if(f.length<(v-1)*c+1)throw new Error("y does not have enough elements for the given dimensions and incy.");let k=await B(a,h?"sgemv_n":"sgemv_t"),j=m?i._buf:b(i,"sgemv-A",!1),W=g?u._buf:b(u,"sgemv-x",!1),M=w?f._buf:b(f,"sgemv-y",!0),U=N([{value:e,type:"u32"},{value:o,type:"u32"},{value:t,type:"f32"},{value:l,type:"f32"},{value:s,type:"u32"},{value:c,type:"u32"},{value:n,type:"u32"}],"sgemv-params");try{let T=A(k.getBindGroupLayout(0),[j,W,M,U]),R=h?Math.min(e,a.limits.maxComputeWorkgroupsPerDimension):C(v),{commandEncoder:z,ts:Y}=L(k,T,R),Q=w?null:E(z,M);S(z);let O=await P(Y);if(w)return O!==void 0?{gpuTimeMs:O}:{};let nr=await _(Q,Float32Array);return O!==void 0?{y:nr,gpuTimeMs:O}:{y:nr}}finally{m||d(j),g||d(W),w||d(M),d(U)}}async function Ke(a,r,e,o,t,i,n,u,s,l,f,c="row-major"){let p=n instanceof x,m=l instanceof x,g=t instanceof H;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="lower"&&r!=="upper")throw new Error("uplo must be 'lower' or 'upper'.");if(c!=="row-major"&&c!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(!Number.isInteger(e)||!Number.isInteger(u)||!Number.isInteger(f)||!Number.isInteger(i))throw new Error("n, incx, incy, and lda must be integers.");if(typeof o!="number")throw new Error("alpha must be a number.");if(Number.isNaN(o))throw new Error("alpha must not be NaN.");if(!Number.isFinite(o))throw new Error("alpha must be finite.");if(typeof s!="number")throw new Error("beta must be a number.");if(Number.isNaN(s))throw new Error("beta must not be NaN.");if(!Number.isFinite(s))throw new Error("beta must be finite.");if(u<=0||f<=0)throw new Error("incx and incy must be positive.");if(i<e)throw new Error("lda must be >= n.");if(!g&&!(t instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!p&&!(n instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!m&&!(l instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(p!==m)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(p&&!g)throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");if(p&&n._buf===l._buf)throw new Error("x and y must not reference the same GPU buffer when both are GpuVectors.");if(g&&i!==t.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(g&&(t.rows<e||t.cols<e))throw new Error("A is too small for the given n.");if(e<0)throw new Error("n must be non-negative.");if(e===0)return m?{}:{y:l};if(!g&&t.length<(e-1)*i+e)throw new Error("A does not have enough elements for the given n and lda.");if(n.length<(e-1)*u+1)throw new Error("x does not have enough elements for the given n and incx.");if(l.length<(e-1)*f+1)throw new Error("y does not have enough elements for the given n and incy.");let y=(g?t.layout:c)==="column-major"?r==="upper":r==="lower",h=await B(a,"ssymv"),G=null,v=null,F=null,k=null;try{G=g?t._buf:b(t,"ssymv-A",!1),v=p?n._buf:b(n,"ssymv-x",!1),F=m?l._buf:b(l,"ssymv-y",!0),k=N([{value:e,type:"u32"},{value:o,type:"f32"},{value:s,type:"f32"},{value:u,type:"u32"},{value:f,type:"u32"},{value:i,type:"u32"},{value:y?0:1,type:"u32"}],"ssymv-params");let j=A(h.getBindGroupLayout(0),[G,v,F,k]),W=Math.min(e,a.limits.maxComputeWorkgroupsPerDimension),{commandEncoder:M,ts:U}=L(h,j,W),T=m?null:E(M,F);S(M);let R=await P(U);if(m)return R!==void 0?{gpuTimeMs:R}:{};let z=await _(T,Float32Array);return R!==void 0?{y:z,gpuTimeMs:R}:{y:z}}finally{!g&&G&&d(G),!p&&v&&d(v),!m&&F&&d(F),k&&d(k)}}async function Xe(a,r,e,o,t,i,n,u,s,l,f,c="row-major"){let p=u instanceof x,m=l instanceof x,g=i instanceof H,w=o==="unit";if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="lower"&&r!=="upper")throw new Error("uplo must be 'lower' or 'upper'.");if(e!=="no-transpose"&&e!=="transpose")throw new Error("trans must be 'no-transpose' or 'transpose'.");if(!w&&o!=="non-unit")throw new Error("diag must be 'unit' or 'non-unit'.");if(c!=="row-major"&&c!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(!Number.isInteger(t)||!Number.isInteger(s)||!Number.isInteger(f)||!Number.isInteger(n))throw new Error("n, incx, incy, and lda must be integers.");if(s<=0||f<=0)throw new Error("incx and incy must be positive.");if(n<t)throw new Error("lda must be >= n.");if(!g&&!(i instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!p&&!(u instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!m&&!(l instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(p!==m)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(p&&u._buf===l._buf)throw new Error("x and y must not reference the same GPU buffer when both are GpuVectors.");if(p&&!g)throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");if(g&&m&&i._buf===l._buf)throw new Error("A and y must not reference the same GPU buffer.");if(g&&n!==i.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(g&&(i.rows<t||i.cols<t))throw new Error("A is too small for the given n.");if(t<0)throw new Error("n must be non-negative.");if(t===0)return m?{}:{y:l};if(!g&&i.length<(t-1)*n+t)throw new Error("A does not have enough elements for the given n and lda.");if(u.length<(t-1)*s+1)throw new Error("x does not have enough elements for the given n and incx.");if(l.length<(t-1)*f+1)throw new Error("y does not have enough elements for the given n and incy.");let h=(g?i.layout:c)==="column-major",G=h?r==="upper":r==="lower",v=h?e==="transpose":e==="no-transpose",F=await B(a,"strmv"),k=null,j=null,W=null,M=null;try{k=g?i._buf:b(i,"strmv-A",!1),j=p?u._buf:b(u,"strmv-x",!1),W=m?l._buf:b(l,"strmv-y",!0),M=N([{value:t,type:"u32"},{value:s,type:"u32"},{value:f,type:"u32"},{value:n,type:"u32"},{value:v?0:1,type:"u32"},{value:G?0:1,type:"u32"},{value:w?1:0,type:"u32"}],"strmv-params");let U=A(F.getBindGroupLayout(0),[k,j,W,M]),T=Math.min(t,a.limits.maxComputeWorkgroupsPerDimension),{commandEncoder:R,ts:z}=L(F,U,T),Y=m?null:E(R,W);S(R);let Q=await P(z);if(m)return Q!==void 0?{gpuTimeMs:Q}:{};let O=await _(Y,Float32Array);return Q!==void 0?{y:O,gpuTimeMs:Q}:{y:O}}finally{!g&&k&&d(k),!p&&j&&d(j),!m&&W&&d(W),M&&d(M)}}var K=64;function $e(a,r,e){let o=new ArrayBuffer(a*r),t=new DataView(o);for(let i=0;i<a;i++){let n=e(i),u=i*r;n.forEach((s,l)=>t.setUint32(u+l*4,s,!0))}return o}function Ye(a,r,e){let o=a.createBuffer({label:e,size:r.byteLength,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});return a.queue.writeBuffer(o,0,r),o}async function Je(a,r,e,o,t,i,n,u,s,l="row-major"){let f=u instanceof x,c=i instanceof H,p=o==="unit";if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="lower"&&r!=="upper")throw new Error("uplo must be 'lower' or 'upper'.");if(e!=="no-transpose"&&e!=="transpose")throw new Error("trans must be 'no-transpose' or 'transpose'.");if(!p&&o!=="non-unit")throw new Error("diag must be 'unit' or 'non-unit'.");if(l!=="row-major"&&l!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(!Number.isInteger(t)||!Number.isInteger(s)||!Number.isInteger(n))throw new Error("n, incx, and lda must be integers.");if(s<=0)throw new Error("incx must be positive.");if(n<t)throw new Error("lda must be >= n.");if(!c&&!(i instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!f&&!(u instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(f&&!c)throw new Error("A must be a GpuMatrix when x is a GpuVector.");if(c&&n!==i.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(c&&(i.rows<t||i.cols<t))throw new Error("A is too small for the given n.");if(t<0)throw new Error("n must be non-negative.");if(t===0)return f?{}:{x:u};if(!c&&i.length<(t-1)*n+t)throw new Error("A does not have enough elements for the given n and lda.");if(u.length<(t-1)*s+1)throw new Error("x does not have enough elements for the given n and incx.");let g=(c?i.layout:l)==="column-major",w=g?r==="upper":r==="lower",y=g?e==="transpose":e==="no-transpose",h=await B(a,"strsv_invert_block"),G=await B(a,"strsv_apply_inverse"),v=await B(a,"strsv_update"),F=y===w,k=[];for(let O=0;O<t;O+=K)k.push(O);F||k.reverse();let j=k.length,W=a.limits.maxComputeWorkgroupsPerDimension,M=a.limits.minUniformBufferOffsetAlignment,U=null,T=null,R=null,z=null,Y=null,Q=null;try{U=c?i._buf:b(i,"strsv-A",!1),T=f?u._buf:b(u,"strsv-x",!0),R=D(j*K*K*4,"strsv-Ainv");let O=$e(j,M,X=>{let $=X*K,or=Math.min($+K,t);return[s,X,$,or]});z=Ye(a,O,"strsv-apply-params");let nr=$e(j,M,X=>{let $=X*K,or=Math.min($+K,t);return[t,s,n,y?0:1,w?0:1,$,or]});Y=Ye(a,nr,"strsv-update-params");let{commandEncoder:rr,querySet:ar}=pr();Q=N([{value:t,type:"u32"},{value:n,type:"u32"},{value:y?0:1,type:"u32"},{value:w?0:1,type:"u32"},{value:p?1:0,type:"u32"}],"strsv-invert-params");let at=A(h.getBindGroupLayout(0),[U,R,Q]);ir(rr,h,at,{x:K,y:j},ar?{timestampWrites:{querySet:ar,beginningOfPassWriteIndex:0}}:void 0);for(let X=0;X<k.length;X++){let $=k[X],or=Math.min($+K,t),nt=$/K,st=X===k.length-1,xr=nt*M,ut=A(G.getBindGroupLayout(0),[R,T,{buffer:z,offset:xr,size:16}]);ir(rr,G,ut,1,st&&ar?{timestampWrites:{querySet:ar,endOfPassWriteIndex:1}}:void 0);let vr=F?t-or:$;if(vr===0)continue;let lt=A(v.getBindGroupLayout(0),[U,T,{buffer:Y,offset:xr,size:32}]),ft=Math.min(vr,W);ir(rr,v,lt,ft)}let ot=cr(rr,ar),it=f?null:E(rr,T);S(rr);let sr=await P(ot);if(f)return sr!==void 0?{gpuTimeMs:sr}:{};let hr=await _(it,Float32Array);return sr!==void 0?{x:hr,gpuTimeMs:sr}:{x:hr}}finally{!c&&U&&d(U),!f&&T&&d(T),R&&d(R),z&&d(z),Y&&d(Y),Q&&d(Q)}}async function rt(a,r,e,o,t,i,n,u,s,l,f="row-major"){let c=s instanceof H;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(f!=="row-major"&&f!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(typeof o!="number")throw new Error("alpha must be a number.");if(Number.isNaN(o))throw new Error("alpha must not be NaN.");if(!Number.isFinite(o))throw new Error("alpha must be finite.");if(!Number.isInteger(r)||!Number.isInteger(e)||!Number.isInteger(i)||!Number.isInteger(u)||!Number.isInteger(l))throw new Error("m, n, incx, incy, and lda must be integers.");if(i<=0||u<=0)throw new Error("incx and incy must be positive.");if(!c&&!(s instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(c&&l!==s.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(c&&(s.rows<r||s.cols<e))throw new Error("A is too small for the given m and n.");(c?s.layout:f)==="column-major"&&([r,e]=[e,r],[t,n]=[n,t],[i,u]=[u,i]);let m=t instanceof x,g=n instanceof x;if(l<e)throw new Error("lda must be >= n.");if(!m&&!(t instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!g&&!(n instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(m!==g)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(m&&!c)throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");if(c&&m&&s._buf===t._buf)throw new Error("A and x must not reference the same GPU buffer.");if(c&&g&&s._buf===n._buf)throw new Error("A and y must not reference the same GPU buffer.");if(r<0||e<0)throw new Error("m and n must be non-negative.");if(r===0||e===0)return c?{}:{A:s};if(!c&&s.length<(r-1)*l+e)throw new Error("A does not have enough elements for the given m, n, and lda.");if(t.length<(r-1)*i+1)throw new Error("x does not have enough elements for the given m and incx.");if(n.length<(e-1)*u+1)throw new Error("y does not have enough elements for the given n and incy.");let w=await B(a,"sger"),y=null,h=null,G=null,v=null;try{y=m?t._buf:b(t,"sger-x",!1),h=g?n._buf:b(n,"sger-y",!1),G=c?s._buf:b(s,"sger-A",!0),v=N([{value:r,type:"u32"},{value:e,type:"u32"},{value:o,type:"f32"},{value:i,type:"u32"},{value:u,type:"u32"},{value:l,type:"u32"}],"sger-params");let F=A(w.getBindGroupLayout(0),[y,h,G,v]),k=Math.min(r,a.limits.maxComputeWorkgroupsPerDimension),{commandEncoder:j,ts:W}=L(w,F,k),M=c?null:E(j,G);S(j);let U=await P(W);if(c)return U!==void 0?{gpuTimeMs:U}:{};let T=await _(M,Float32Array);return U!==void 0?{A:T,gpuTimeMs:U}:{A:T}}finally{!m&&y&&d(y),!g&&h&&d(h),!c&&G&&d(G),v&&d(v)}}async function et(a,r,e,o,t,i,n,u,s="row-major"){let l=t instanceof x,f=n instanceof H;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="lower"&&r!=="upper")throw new Error("uplo must be 'lower' or 'upper'.");if(s!=="row-major"&&s!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(!Number.isInteger(e)||!Number.isInteger(i)||!Number.isInteger(u))throw new Error("n, incx, and lda must be integers.");if(typeof o!="number")throw new Error("alpha must be a number.");if(Number.isNaN(o))throw new Error("alpha must not be NaN.");if(!Number.isFinite(o))throw new Error("alpha must be finite.");if(i<=0)throw new Error("incx must be positive.");if(u<e)throw new Error("lda must be >= n.");if(!f&&!(n instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!l&&!(t instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(l&&!f)throw new Error("A must be a GpuMatrix when x is a GpuVector.");if(f&&l&&n._buf===t._buf)throw new Error("A and x must not reference the same GPU buffer.");if(f&&u!==n.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(f&&(n.rows<e||n.cols<e))throw new Error("A is too small for the given n.");if(e<0)throw new Error("n must be non-negative.");if(e===0)return f?{}:{A:n};if(!f&&n.length<(e-1)*u+e)throw new Error("A does not have enough elements for the given n and lda.");if(t.length<(e-1)*i+1)throw new Error("x does not have enough elements for the given n and incx.");let p=(f?n.layout:s)==="column-major"?r==="upper":r==="lower",m=await B(a,"ssyr"),g=null,w=null,y=null;try{g=l?t._buf:b(t,"ssyr-x",!1),w=f?n._buf:b(n,"ssyr-A",!0),y=N([{value:e,type:"u32"},{value:o,type:"f32"},{value:i,type:"u32"},{value:u,type:"u32"},{value:p?0:1,type:"u32"}],"ssyr-params");let h=A(m.getBindGroupLayout(0),[g,w,y]),G=Math.min(e,a.limits.maxComputeWorkgroupsPerDimension),{commandEncoder:v,ts:F}=L(m,h,G),k=f?null:E(v,w);S(v);let j=await P(F);if(f)return j!==void 0?{gpuTimeMs:j}:{};let W=await _(k,Float32Array);return j!==void 0?{A:W,gpuTimeMs:j}:{A:W}}finally{!l&&g&&d(g),!f&&w&&d(w),y&&d(y)}}async function tt(a,r,e,o,t,i,n,u,s,l,f="row-major"){let c=t instanceof x,p=n instanceof x,m=s instanceof H;if(!(a instanceof GPUDevice))throw new Error("device must be a GPUDevice.");if(r!=="lower"&&r!=="upper")throw new Error("uplo must be 'lower' or 'upper'.");if(f!=="row-major"&&f!=="column-major")throw new Error("layout must be 'row-major' or 'column-major'.");if(!Number.isInteger(e)||!Number.isInteger(i)||!Number.isInteger(u)||!Number.isInteger(l))throw new Error("n, incx, incy, and lda must be integers.");if(typeof o!="number")throw new Error("alpha must be a number.");if(Number.isNaN(o))throw new Error("alpha must not be NaN.");if(!Number.isFinite(o))throw new Error("alpha must be finite.");if(i<=0||u<=0)throw new Error("incx and incy must be positive.");if(l<e)throw new Error("lda must be >= n.");if(!m&&!(s instanceof Float32Array))throw new Error("A must be a Float32Array or GpuMatrix.");if(!c&&!(t instanceof Float32Array))throw new Error("x must be a Float32Array or GpuVector.");if(!p&&!(n instanceof Float32Array))throw new Error("y must be a Float32Array or GpuVector.");if(c!==p)throw new Error("x and y must be the same type (both Float32Array or both GpuVector).");if(c&&!m)throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");if(m&&c&&s._buf===t._buf)throw new Error("A and x must not reference the same GPU buffer.");if(m&&p&&s._buf===n._buf)throw new Error("A and y must not reference the same GPU buffer.");if(c&&t._buf===n._buf)throw new Error("x and y must not reference the same GPU buffer when both are GpuVectors.");if(m&&l!==s.lda)throw new Error("lda must match A.lda when A is a GpuMatrix.");if(m&&(s.rows<e||s.cols<e))throw new Error("A is too small for the given n.");if(e<0)throw new Error("n must be non-negative.");if(e===0)return m?{}:{A:s};if(!m&&s.length<(e-1)*l+e)throw new Error("A does not have enough elements for the given n and lda.");if(t.length<(e-1)*i+1)throw new Error("x does not have enough elements for the given n and incx.");if(n.length<(e-1)*u+1)throw new Error("y does not have enough elements for the given n and incy.");let w=(m?s.layout:f)==="column-major"?r==="upper":r==="lower",y=await B(a,"ssyr2"),h=null,G=null,v=null,F=null;try{h=c?t._buf:b(t,"ssyr2-x",!1),G=p?n._buf:b(n,"ssyr2-y",!1),v=m?s._buf:b(s,"ssyr2-A",!0),F=N([{value:e,type:"u32"},{value:o,type:"f32"},{value:i,type:"u32"},{value:u,type:"u32"},{value:l,type:"u32"},{value:w?0:1,type:"u32"}],"ssyr2-params");let k=A(y.getBindGroupLayout(0),[h,G,v,F]),j=Math.min(e,a.limits.maxComputeWorkgroupsPerDimension),{commandEncoder:W,ts:M}=L(y,k,j),U=m?null:E(W,v);S(W);let T=await P(M);if(m)return T!==void 0?{gpuTimeMs:T}:{};let R=await _(U,Float32Array);return T!==void 0?{A:R,gpuTimeMs:T}:{A:R}}finally{!c&&h&&d(h),!p&&G&&d(G),!m&&v&&d(v),F&&d(F)}}return wt(ra);})();