wgblas 1.2.1 → 2.0.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 (70) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +36 -54
  3. package/dist/wgblas.browser.js +779 -34
  4. package/index.d.mts +13 -0
  5. package/index.mjs +8 -0
  6. package/package.json +55 -2
  7. package/src/dasum/dasum.d.mts +2 -2
  8. package/src/dasum/dasum.mjs +6 -4
  9. package/src/idamax/idamax.d.mts +51 -0
  10. package/src/idamax/idamax.mjs +128 -0
  11. package/src/init.mjs +9 -1
  12. package/src/isamax/isamax.d.mts +1 -1
  13. package/src/sasum/sasum.d.mts +1 -1
  14. package/src/saxpy/saxpy.d.mts +1 -1
  15. package/src/scopy/scopy.d.mts +1 -1
  16. package/src/sdot/sdot.d.mts +1 -1
  17. package/src/sgemm/sgemm.d.mts +102 -0
  18. package/src/sgemm/sgemm.mjs +195 -0
  19. package/src/sgemmtr/sgemmtr.d.mts +104 -0
  20. package/src/sgemmtr/sgemmtr.mjs +203 -0
  21. package/src/sgemv/sgemv.d.mts +1 -38
  22. package/src/sgemv/sgemv.mjs +4 -0
  23. package/src/sger/sger.d.mts +1 -34
  24. package/src/sger/sger.mjs +2 -0
  25. package/src/shaders/block_transfer.wgsl +42 -0
  26. package/src/shaders/browser-shaders.mjs +26 -0
  27. package/src/shaders/dasum.wgsl +3 -2
  28. package/src/shaders/f64/dekker.wgsl +4 -85
  29. package/src/shaders/f64/utils/abs.wgsl +10 -0
  30. package/src/shaders/f64/utils/add.wgsl +77 -0
  31. package/src/shaders/f64/utils/equal.wgsl +7 -0
  32. package/src/shaders/f64/utils/greater.wgsl +12 -0
  33. package/src/shaders/f64/utils/multiply.wgsl +81 -0
  34. package/src/shaders/idamax.wgsl +96 -0
  35. package/src/shaders/reduction/argmaxF64.wgsl +50 -0
  36. package/src/shaders/reduction/sumF64.wgsl +2 -2
  37. package/src/shaders/sgemm_large.wgsl +117 -0
  38. package/src/shaders/sgemm_small.wgsl +112 -0
  39. package/src/shaders/sgemmtr_large.wgsl +117 -0
  40. package/src/shaders/sgemmtr_small.wgsl +110 -0
  41. package/src/shaders/symmetrize.wgsl +31 -0
  42. package/src/shaders/triangularize.wgsl +44 -0
  43. package/src/snrm2/snrm2.d.mts +1 -1
  44. package/src/srot/srot.d.mts +1 -1
  45. package/src/srotm/srotm.d.mts +1 -1
  46. package/src/sscal/sscal.d.mts +1 -1
  47. package/src/sswap/sswap.d.mts +1 -1
  48. package/src/ssymm/ssymm.d.mts +103 -0
  49. package/src/ssymm/ssymm.mjs +209 -0
  50. package/src/ssymv/ssymv.d.mts +1 -36
  51. package/src/ssymv/ssymv.mjs +2 -0
  52. package/src/ssyr/ssyr.d.mts +1 -30
  53. package/src/ssyr/ssyr.mjs +2 -0
  54. package/src/ssyr2/ssyr2.d.mts +1 -34
  55. package/src/ssyr2/ssyr2.mjs +2 -0
  56. package/src/ssyr2k/ssyr2k.d.mts +100 -0
  57. package/src/ssyr2k/ssyr2k.mjs +201 -0
  58. package/src/ssyrk/ssyrk.d.mts +90 -0
  59. package/src/ssyrk/ssyrk.mjs +176 -0
  60. package/src/strmm/strmm.d.mts +100 -0
  61. package/src/strmm/strmm.mjs +211 -0
  62. package/src/strmv/strmv.d.mts +1 -36
  63. package/src/strmv/strmv.mjs +2 -0
  64. package/src/strsm/strsm.d.mts +99 -0
  65. package/src/strsm/strsm.mjs +342 -0
  66. package/src/strsv/strsv.d.mts +1 -32
  67. package/src/strsv/strsv.mjs +2 -0
  68. package/src/util/buffer.mjs +4 -2
  69. package/src/util/compute.mjs +6 -3
  70. package/src/util/f64.mjs +3 -3
@@ -0,0 +1,211 @@
1
+ import {
2
+ uploadBuffer,
3
+ createParamsBuffer,
4
+ createStorageBuffer,
5
+ stageReadback,
6
+ destroyBuffers,
7
+ } from "../util/buffer.mjs";
8
+ import { createBindGroup } from "../util/bindgroup.mjs";
9
+ import { beginTimedEncoder, encodePass, submit } from "../util/compute.mjs";
10
+ import { extractResult } from "../util/result.mjs";
11
+ import { resolveTimestamp, extractTimestamp } from "../util/benchmark.mjs";
12
+ import { getPipeline } from "../util/pipeline.mjs";
13
+ import { GpuMatrix } from "../classes/GpuMatrix.mjs";
14
+
15
+ const BM_SMALL = 32, BN_SMALL = 32; // sgemm_small.wgsl's block tile
16
+ const BM_LARGE = 64, BN_LARGE = 64; // sgemm_large.wgsl's block tile
17
+ const LARGE_TILE_WORKGROUP_THRESHOLD = 36; // same threshold sgemm/sgemmtr/ssyrk/ssymm use
18
+ const TRI_WG = 8; // triangularize.wgsl's @workgroup_size(8, 8)
19
+
20
+ // strmm: B := alpha*op(A)*B (side='left') or alpha*B*op(A) (side='right'), A
21
+ // triangular. Triangularize then sgemm, one command encoder. B is both
22
+ // input and output, so gemm writes to a fresh buffer (no aliasing race),
23
+ // copied back into B (GpuMatrix) or read back directly (Float32Array).
24
+ export async function strmm(
25
+ device, side, uplo, transA, diag, m, n, alpha, A, lda, B, ldb, layout = "row-major",
26
+ ) {
27
+ const AIsGpu = A instanceof GpuMatrix;
28
+ const BIsGpu = B instanceof GpuMatrix;
29
+ const isUnit = diag === "unit";
30
+
31
+ if (!(device instanceof GPUDevice))
32
+ throw new Error("device must be a GPUDevice.");
33
+ if (side !== "left" && side !== "right")
34
+ throw new Error("side must be 'left' or 'right'.");
35
+ if (uplo !== "lower" && uplo !== "upper")
36
+ throw new Error("uplo must be 'lower' or 'upper'.");
37
+ if (transA !== "no-transpose" && transA !== "transpose")
38
+ throw new Error("transA must be 'no-transpose' or 'transpose'.");
39
+ if (!isUnit && diag !== "non-unit")
40
+ throw new Error("diag must be 'unit' or 'non-unit'.");
41
+ if (layout !== "row-major" && layout !== "column-major")
42
+ throw new Error("layout must be 'row-major' or 'column-major'.");
43
+ if (typeof alpha !== "number")
44
+ throw new Error("alpha must be a number.");
45
+ if (Number.isNaN(alpha)) throw new Error("alpha must not be NaN.");
46
+ if (!Number.isFinite(alpha)) throw new Error("alpha must be finite.");
47
+ if (!Number.isInteger(m) || !Number.isInteger(n) || !Number.isInteger(lda) || !Number.isInteger(ldb))
48
+ throw new Error("m, n, lda, and ldb must be integers.");
49
+ if (!AIsGpu && !(A instanceof Float32Array))
50
+ throw new Error("A must be a Float32Array or GpuMatrix.");
51
+ if (!BIsGpu && !(B instanceof Float32Array))
52
+ throw new Error("B must be a Float32Array or GpuMatrix.");
53
+ if (AIsGpu !== BIsGpu)
54
+ throw new Error("A and B must both be GpuMatrix or both be Float32Array.");
55
+ if (m < 0 || n < 0) throw new Error("m and n must be non-negative.");
56
+ if (m === 0 || n === 0) return BIsGpu ? {} : { B };
57
+
58
+ const effLayoutA = AIsGpu ? A.layout : layout;
59
+ const effLayoutB = BIsGpu ? B.layout : layout;
60
+
61
+ // A: triangular, order = m (side='left') or n (side='right').
62
+ const aOrder = side === "left" ? m : n;
63
+ if (lda < aOrder) throw new Error("lda must be >= " + (side === "left" ? "m" : "n") + ".");
64
+ if (AIsGpu) {
65
+ if (lda !== A.lda) throw new Error("lda must match A.lda when A is a GpuMatrix.");
66
+ if (A.rows < aOrder || A.cols < aOrder) throw new Error("A is too small for the given m/n and side.");
67
+ } else if (A.length < (aOrder - 1) * lda + aOrder) {
68
+ throw new Error("A does not have enough elements for the given dimensions and lda.");
69
+ }
70
+
71
+ // B: always m x n, overwritten in place with the same ldb.
72
+ const bOuter = effLayoutB === "column-major" ? n : m;
73
+ const bInner = effLayoutB === "column-major" ? m : n;
74
+ if (ldb < bInner)
75
+ throw new Error(`ldb must be >= ${effLayoutB === "column-major" ? "rows" : "cols"} of B as stored.`);
76
+ if (BIsGpu) {
77
+ if (ldb !== B.lda) throw new Error("ldb must match B.lda when B is a GpuMatrix.");
78
+ if (B.rows < m || B.cols < n) throw new Error("B is too small for the given m and n.");
79
+ } else if (B.length < (bOuter - 1) * ldb + bInner) {
80
+ throw new Error("B does not have enough elements for the given dimensions and ldb.");
81
+ }
82
+
83
+ // A isn't symmetric: column-major = genuine transpose, so flip transA;
84
+ // transposing also swaps which triangle looks stored, so flip uplo too.
85
+ const uploEffA = effLayoutA === "column-major" ? (uplo === "lower" ? "upper" : "lower") : uplo;
86
+ const transEffA = effLayoutA === "column-major" ? (transA === "no-transpose" ? "transpose" : "no-transpose") : transA;
87
+
88
+ const transB = effLayoutB === "column-major" ? "transpose" : "no-transpose";
89
+ const transDense = "no-transpose"; // Adense already embodies op(A)
90
+
91
+ // X*Y (X=Adense,Y=B for side='left', swapped for 'right'). Column-major
92
+ // output: compute (B_out)^T instead — sgemm's own trick, same as ssymm's.
93
+ let mg = m, ng = n;
94
+ const kg = aOrder;
95
+ let transX = side === "left" ? transDense : transB;
96
+ let transY = side === "left" ? transB : transDense;
97
+ const flip = (t) => (t === "no-transpose" ? "transpose" : "no-transpose");
98
+ let swapXY = side === "right";
99
+ if (effLayoutB === "column-major") {
100
+ [transX, transY] = [flip(transY), flip(transX)];
101
+ swapXY = !swapXY;
102
+ [mg, ng] = [ng, mg];
103
+ }
104
+
105
+ const ldDense = aOrder; // Adense is tightly packed, row-major
106
+ const largeWgX = Math.ceil(ng / BN_LARGE);
107
+ const largeWgY = Math.ceil(mg / BM_LARGE);
108
+ const useLargeTile = largeWgX * largeWgY >= LARGE_TILE_WORKGROUP_THRESHOLD;
109
+ const gemmPipeline = await getPipeline(device, useLargeTile ? "sgemm_large" : "sgemm_small");
110
+ const triPipeline = await getPipeline(device, "triangularize");
111
+ const gemmWgCount = useLargeTile
112
+ ? {
113
+ x: Math.min(largeWgX, device.limits.maxComputeWorkgroupsPerDimension),
114
+ y: Math.min(largeWgY, device.limits.maxComputeWorkgroupsPerDimension),
115
+ }
116
+ : {
117
+ x: Math.min(Math.ceil(ng / BN_SMALL), device.limits.maxComputeWorkgroupsPerDimension),
118
+ y: Math.min(Math.ceil(mg / BM_SMALL), device.limits.maxComputeWorkgroupsPerDimension),
119
+ };
120
+
121
+ const ABuffer = AIsGpu ? A._buf : uploadBuffer(A, "strmm-A", false);
122
+ // readback=true (COPY_SRC): BBuffer is also the source that seeds outBuffer.
123
+ const BBuffer = BIsGpu ? B._buf : uploadBuffer(B, "strmm-B", true);
124
+ const AdenseBuffer = createStorageBuffer(aOrder * ldDense * 4, "strmm-Adense");
125
+ // COPY_DST: seeded from B's own content before gemm runs, so stride-padding
126
+ // gaps (never written by gemm's tight m x n loop) keep B's original bytes
127
+ // instead of reading back as zero. COPY_SRC: read back / adopted by B after.
128
+ const outBuffer = createStorageBuffer(
129
+ bOuter * ldb * 4, "strmm-out", GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST,
130
+ );
131
+ let triParams = null, gemmParams = null;
132
+ let outBufferAdopted = false; // true once B._buf is repointed at outBuffer
133
+
134
+ try {
135
+ triParams = createParamsBuffer(
136
+ [
137
+ { value: aOrder, type: "u32" },
138
+ { value: lda, type: "u32" },
139
+ { value: ldDense, type: "u32" },
140
+ { value: uploEffA === "upper" ? 1 : 0, type: "u32" },
141
+ { value: transEffA === "transpose" ? 1 : 0, type: "u32" },
142
+ { value: isUnit ? 1 : 0, type: "u32" },
143
+ ],
144
+ "strmm-tri-params",
145
+ );
146
+ const triBindGroup = createBindGroup(triPipeline.getBindGroupLayout(0), [ABuffer, AdenseBuffer, triParams]);
147
+
148
+ // X/Y buffers and their own ld, matching swapXY above.
149
+ const XBuffer = swapXY ? BBuffer : AdenseBuffer;
150
+ const ldX = swapXY ? ldb : ldDense;
151
+ const YBuffer = swapXY ? AdenseBuffer : BBuffer;
152
+ const ldY = swapXY ? ldDense : ldb;
153
+
154
+ gemmParams = createParamsBuffer(
155
+ [
156
+ { value: mg, type: "u32" },
157
+ { value: ng, type: "u32" },
158
+ { value: kg, type: "u32" },
159
+ { value: alpha, type: "f32" },
160
+ { value: 0.0, type: "f32" }, // beta — strmm has no C accumulation term
161
+ { value: ldX, type: "u32" },
162
+ { value: ldY, type: "u32" },
163
+ { value: ldb, type: "u32" },
164
+ { value: transX === "transpose" ? 1 : 0, type: "u32" },
165
+ { value: transY === "transpose" ? 1 : 0, type: "u32" },
166
+ ],
167
+ "strmm-gemm-params",
168
+ );
169
+ const gemmBindGroup = createBindGroup(gemmPipeline.getBindGroupLayout(0), [XBuffer, YBuffer, outBuffer, gemmParams]);
170
+
171
+ const { commandEncoder, querySet } = beginTimedEncoder();
172
+ // Seed outBuffer with B's own bytes first, so gemm's tight m x n write
173
+ // leaves stride-padding gaps holding B's original content, not zero.
174
+ // BBuffer may be larger than outBuffer (e.g. a validation-test baseline
175
+ // over-provisioned for a bigger ldb it might later be substituted with).
176
+ commandEncoder.copyBufferToBuffer(BBuffer, 0, outBuffer, 0, Math.min(BBuffer.size, outBuffer.size));
177
+ const triDesc = querySet ? { timestampWrites: { querySet, beginningOfPassWriteIndex: 0 } } : undefined;
178
+ const gemmDesc = querySet ? { timestampWrites: { querySet, endOfPassWriteIndex: 1 } } : undefined;
179
+ encodePass(commandEncoder, triPipeline, triBindGroup, { x: Math.ceil(aOrder / TRI_WG), y: Math.ceil(aOrder / TRI_WG) }, triDesc);
180
+ encodePass(commandEncoder, gemmPipeline, gemmBindGroup, gemmWgCount, gemmDesc);
181
+
182
+ const ts = resolveTimestamp(commandEncoder, querySet);
183
+ const readBuffer = BIsGpu ? null : stageReadback(commandEncoder, outBuffer);
184
+
185
+ submit(commandEncoder);
186
+
187
+ const gpuTimeMs = await extractTimestamp(ts);
188
+
189
+ if (BIsGpu) {
190
+ // Adopt outBuffer as B's own backing buffer instead of copying into the
191
+ // old one (B._buf has no COPY_DST usage) — cheaper and avoids needing
192
+ // an extra buffer-usage flag on every GpuMatrix for this one routine.
193
+ destroyBuffers(B._buf);
194
+ B._buf = outBuffer;
195
+ outBufferAdopted = true;
196
+ if (gpuTimeMs !== undefined) return { gpuTimeMs };
197
+ return {};
198
+ }
199
+
200
+ const result = await extractResult(readBuffer, Float32Array);
201
+ if (gpuTimeMs !== undefined) return { B: result, gpuTimeMs };
202
+ return { B: result };
203
+ } finally {
204
+ if (!AIsGpu) destroyBuffers(ABuffer);
205
+ if (!BIsGpu) destroyBuffers(BBuffer);
206
+ destroyBuffers(AdenseBuffer);
207
+ if (!outBufferAdopted) destroyBuffers(outBuffer);
208
+ if (triParams) destroyBuffers(triParams);
209
+ if (gemmParams) destroyBuffers(gemmParams);
210
+ }
211
+ }
@@ -44,41 +44,6 @@ export declare function strmv(
44
44
  layout?: 'row-major' | 'column-major',
45
45
  ): Promise<{ y: Float32Array; gpuTimeMs?: number }>;
46
46
 
47
- /**
48
- * Performs the triangular matrix-vector operation y = op(A) * x
49
- *
50
- * A is kept GPU-resident; x and y are CPU Float32Arrays. `A`'s own `layout`
51
- * (set at `GpuMatrix.from` time) determines the operation — there is no
52
- * separate `layout` argument here.
53
- *
54
- * @param device - GPUDevice from `init()`
55
- * @param uplo - `'lower'` to use the lower triangle, `'upper'` to use the upper triangle
56
- * @param trans - `'no-transpose'` for A, `'transpose'` for A^T
57
- * @param diag - `'unit'` to treat the diagonal as all-ones (A's diagonal is not read), `'non-unit'` to read it
58
- * @param n - order of the matrix A
59
- * @param A - GpuMatrix, GPU-resident
60
- * @param lda - leading dimension of A (must equal A.lda)
61
- * @param x - Float32Array input vector
62
- * @param incx - stride for x (must be a positive integer)
63
- * @param y - Float32Array output vector
64
- * @param incy - stride for y (must be a positive integer)
65
- * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/strmv/strmv.mjs#L15">Source code: strmv.mjs (L15)</a>
66
- * @category BLAS Level 2
67
- */
68
- export declare function strmv(
69
- device: GPUDevice,
70
- uplo: 'lower' | 'upper',
71
- trans: 'no-transpose' | 'transpose',
72
- diag: 'unit' | 'non-unit',
73
- n: number,
74
- A: GpuMatrix,
75
- lda: number,
76
- x: Float32Array,
77
- incx: number,
78
- y: Float32Array,
79
- incy: number,
80
- ): Promise<{ y: Float32Array; gpuTimeMs?: number }>;
81
-
82
47
  /**
83
48
  * Performs the triangular matrix-vector operation y = op(A) * x
84
49
  *
@@ -86,7 +51,7 @@ export declare function strmv(
86
51
  * `layout` (set at `GpuMatrix.from` time) determines the operation — there is
87
52
  * no separate `layout` argument here.
88
53
  *
89
- * {@includeCode ../../examples/strmv/gpuvec.strmv.js}
54
+ * {@includeCode ../../examples/strmv/gpu.strmv.js}
90
55
  *
91
56
  * @param device - GPUDevice from `init()`
92
57
  * @param uplo - `'lower'` to use the lower triangle, `'upper'` to use the upper triangle
@@ -54,6 +54,8 @@ export async function strmv(device, uplo, trans, diag, n, A, lda, x, incx, y, in
54
54
  );
55
55
  if (xIsGpu && !AIsGpu)
56
56
  throw new Error("A must be a GpuMatrix when x and y are GpuVectors.");
57
+ if (AIsGpu && !xIsGpu)
58
+ throw new Error("x and y must be GpuVectors when A is a GpuMatrix.");
57
59
  if (AIsGpu && yIsGpu && A._buf === y._buf)
58
60
  throw new Error("A and y must not reference the same GPU buffer.");
59
61
  if (AIsGpu && lda !== A.lda)
@@ -0,0 +1,99 @@
1
+ import { GpuMatrix } from "../classes/GpuMatrix.mjs";
2
+
3
+ /**
4
+ * Solves the triangular matrix equation
5
+ * op(A) * X = alpha * B (`side='left'`) or
6
+ * X * op(A) = alpha * B (`side='right'`), overwriting `B` with the
7
+ * solution `X` — `A` is triangular, only its `uplo` triangle stored; `B` is
8
+ * a general m×n matrix.
9
+ *
10
+ * - `side='left'`: `A` is m×m — solves `op(A)*X = alpha*B`
11
+ * - `side='right'`: `A` is n×n — solves `X*op(A) = alpha*B`
12
+ *
13
+ * Blocked substitution (strsv's own technique, generalized to a matrix
14
+ * RHS): strsv_invert_block + sgemm, both unmodified. A near-zero diagonal
15
+ * entry amplifies error, same as any triangular solve.
16
+ *
17
+ * {@includeCode ../../examples/strsm/strsm.js}
18
+ *
19
+ * **Browser (standalone HTML):**
20
+ * {@includeCode ../../examples/strsm/web/strsm.html}
21
+ *
22
+ * @param device - GPUDevice from `init()`
23
+ * @param side - `'left'` to solve op(A)*X=alpha*B, `'right'` to solve X*op(A)=alpha*B
24
+ * @param uplo - `'lower'` if only `A`'s lower triangle is stored, `'upper'` for upper
25
+ * @param transA - `'no-transpose'` for A, `'transpose'` for A^T
26
+ * @param diag - `'unit'` to treat A's diagonal as all-ones (A's diagonal is not read), `'non-unit'` to read it
27
+ * @param m - rows of B
28
+ * @param n - columns of B
29
+ * @param alpha - scalar multiplier for B
30
+ * @param A - Float32Array, triangular, row-major or column-major (see `layout`)
31
+ * @param lda - leading dimension of A as stored
32
+ * @param B - Float32Array input/output matrix, overwritten with the solution, row-major or column-major
33
+ * @param ldb - leading dimension of B as stored
34
+ * @param layout - storage layout shared by A/B when they're Float32Array
35
+ * (default: `'row-major'`) — column-major A is a genuine transpose (A isn't
36
+ * symmetric like ssymm's), so both `transA` and `uplo` are adjusted
37
+ * internally to compensate
38
+ * @returns the solution X, written into B, as a Float32Array
39
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/strsm/strsm.mjs#L25">Source code: strsm.mjs (L25)</a>
40
+ * @category BLAS Level 3
41
+ */
42
+ export declare function strsm(
43
+ device: GPUDevice,
44
+ side: 'left' | 'right',
45
+ uplo: 'lower' | 'upper',
46
+ transA: 'no-transpose' | 'transpose',
47
+ diag: 'unit' | 'non-unit',
48
+ m: number,
49
+ n: number,
50
+ alpha: number,
51
+ A: Float32Array,
52
+ lda: number,
53
+ B: Float32Array,
54
+ ldb: number,
55
+ layout?: 'row-major' | 'column-major',
56
+ ): Promise<{ B: Float32Array; gpuTimeMs?: number }>;
57
+
58
+ /**
59
+ * Solves the triangular matrix equation
60
+ * op(A) * X = alpha * B (`side='left'`) or
61
+ * X * op(A) = alpha * B (`side='right'`), overwriting `B` in place with `X`.
62
+ *
63
+ * A and B are both kept GPU-resident. Each matrix's own `layout` (set at
64
+ * `GpuMatrix.from` time) determines the operation — there is no separate
65
+ * `layout` argument here. A and B must both be GpuMatrix or both be
66
+ * Float32Array — mixing is not supported.
67
+ *
68
+ * {@includeCode ../../examples/strsm/gpu.strsm.js}
69
+ *
70
+ * @param device - GPUDevice from `init()`
71
+ * @param side - `'left'` to solve op(A)*X=alpha*B, `'right'` to solve X*op(A)=alpha*B
72
+ * @param uplo - `'lower'` if only `A`'s lower triangle is stored, `'upper'` for upper
73
+ * @param transA - `'no-transpose'` for A, `'transpose'` for A^T
74
+ * @param diag - `'unit'` to treat A's diagonal as all-ones (A's diagonal is not read), `'non-unit'` to read it
75
+ * @param m - rows of B
76
+ * @param n - columns of B
77
+ * @param alpha - scalar multiplier for B
78
+ * @param A - GpuMatrix, triangular
79
+ * @param lda - leading dimension of A (must equal A.lda)
80
+ * @param B - GpuMatrix (overwritten in place with the solution)
81
+ * @param ldb - leading dimension of B (must equal B.lda)
82
+ * @returns no B — it stays GPU-resident; call `B.read()` yourself for a CPU readback (see the example)
83
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/strsm/strsm.mjs#L25">Source code: strsm.mjs (L25)</a>
84
+ * @category BLAS Level 3
85
+ */
86
+ export declare function strsm(
87
+ device: GPUDevice,
88
+ side: 'left' | 'right',
89
+ uplo: 'lower' | 'upper',
90
+ transA: 'no-transpose' | 'transpose',
91
+ diag: 'unit' | 'non-unit',
92
+ m: number,
93
+ n: number,
94
+ alpha: number,
95
+ A: GpuMatrix,
96
+ lda: number,
97
+ B: GpuMatrix,
98
+ ldb: number,
99
+ ): Promise<{ gpuTimeMs?: number }>;