wgblas 0.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 (43) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +161 -0
  3. package/dist/wgblas.browser.js +422 -0
  4. package/index.d.mts +94 -0
  5. package/index.mjs +16 -0
  6. package/package.json +127 -0
  7. package/src/classes/GpuVector.d.mts +69 -0
  8. package/src/classes/GpuVector.mjs +33 -0
  9. package/src/devdocs.mjs +81 -0
  10. package/src/index.mjs +4 -0
  11. package/src/init.mjs +105 -0
  12. package/src/isamax/isamax.d.mts +46 -0
  13. package/src/isamax/isamax.mjs +115 -0
  14. package/src/random/random.d.mts +61 -0
  15. package/src/random/random.mjs +11 -0
  16. package/src/sasum/sasum.d.mts +44 -0
  17. package/src/sasum/sasum.mjs +98 -0
  18. package/src/saxpy/saxpy.d.mts +54 -0
  19. package/src/saxpy/saxpy.mjs +90 -0
  20. package/src/scopy/scopy.d.mts +50 -0
  21. package/src/scopy/scopy.mjs +87 -0
  22. package/src/sdot/sdot.d.mts +52 -0
  23. package/src/sdot/sdot.mjs +118 -0
  24. package/src/shaders/browser-shaders.mjs +27 -0
  25. package/src/shaders/index.mjs +27 -0
  26. package/src/snrm2/snrm2.d.mts +44 -0
  27. package/src/snrm2/snrm2.mjs +100 -0
  28. package/src/srot/srot.d.mts +62 -0
  29. package/src/srot/srot.mjs +95 -0
  30. package/src/srotm/srotm.d.mts +60 -0
  31. package/src/srotm/srotm.mjs +94 -0
  32. package/src/sscal/sscal.d.mts +46 -0
  33. package/src/sscal/sscal.mjs +71 -0
  34. package/src/sswap/sswap.d.mts +50 -0
  35. package/src/sswap/sswap.mjs +90 -0
  36. package/src/util/benchmark.mjs +103 -0
  37. package/src/util/bindgroup.mjs +22 -0
  38. package/src/util/buffer.mjs +160 -0
  39. package/src/util/compute.mjs +52 -0
  40. package/src/util/index.mjs +12 -0
  41. package/src/util/pipeline.mjs +82 -0
  42. package/src/util/result.mjs +19 -0
  43. package/src/util/workgroup.mjs +31 -0
@@ -0,0 +1,44 @@
1
+ import { GpuVector } from "../classes/GpuVector.mjs";
2
+
3
+ /**
4
+ * Computes the Euclidean norm of a vector: result = sqrt(sum(x[i] * x[i]))
5
+ *
6
+ * {@includeCode ../../examples/snrm2/snrm2.js}
7
+ *
8
+ * **Browser (standalone HTML):**
9
+ * {@includeCode ../../examples/snrm2/web/snrm2.html}
10
+ *
11
+ * @param device - GPUDevice from `init()`
12
+ * @param n - number of elements (must be a positive integer)
13
+ * @param x - Float32Array input vector
14
+ * @param incx - stride for x (must be a positive integer)
15
+ * @returns Euclidean norm scalar — always a CPU readback, even for GpuVector inputs
16
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/snrm2/snrm2.mjs#L18">Source code: snrm2.mjs (L18)</a>
17
+ * @category BLAS Level 1
18
+ */
19
+ export declare function snrm2(
20
+ device: GPUDevice,
21
+ n: number,
22
+ x: Float32Array,
23
+ incx: number,
24
+ ): Promise<{ nrm2: number } | { nrm2: number; gpuTimeMs: number }>;
25
+
26
+ /**
27
+ * Computes the Euclidean norm of a vector: result = sqrt(sum(x[i] * x[i]))
28
+ *
29
+ * {@includeCode ../../examples/snrm2/gpuvec.snrm2.js}
30
+ *
31
+ * @param device - GPUDevice from `init()`
32
+ * @param n - number of elements (must be a positive integer)
33
+ * @param x - GpuVector input vector
34
+ * @param incx - stride for x (must be a positive integer)
35
+ * @returns Euclidean norm scalar — always a CPU readback, even for GpuVector inputs
36
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/snrm2/snrm2.mjs#L18">Source code: snrm2.mjs (L18)</a>
37
+ * @category BLAS Level 1
38
+ */
39
+ export declare function snrm2(
40
+ device: GPUDevice,
41
+ n: number,
42
+ x: GpuVector,
43
+ incx: number,
44
+ ): Promise<{ nrm2: number } | { nrm2: number; gpuTimeMs: number }>;
@@ -0,0 +1,100 @@
1
+ import {
2
+ uploadBuffer,
3
+ createStorageBuffer,
4
+ createParamsBuffer,
5
+ createResultBuffer,
6
+ stageReadback,
7
+ destroyBuffers,
8
+ } from "../util/buffer.mjs";
9
+ import { createBindGroup } from "../util/bindgroup.mjs";
10
+ import { runComputePass, submit } from "../util/compute.mjs";
11
+ import { extractTimestamp } from "../util/benchmark.mjs";
12
+ import { extractResult } from "../util/result.mjs";
13
+ import { getPipeline } from "../util/pipeline.mjs";
14
+ import { GpuVector } from "../classes/GpuVector.mjs";
15
+
16
+ const WGS = 64; // workgroup size
17
+
18
+ export async function snrm2(device, n, x, incx) {
19
+ const xIsGpu = x instanceof GpuVector;
20
+
21
+ if (!(device instanceof GPUDevice))
22
+ throw new Error("device must be a GPUDevice.");
23
+ if (!Number.isInteger(n) || !Number.isInteger(incx))
24
+ throw new Error("n and incx must be integers.");
25
+ if (incx <= 0) throw new Error("incx must be positive.");
26
+ if (!xIsGpu && !(x instanceof Float32Array))
27
+ throw new Error("x must be a Float32Array or GpuVector.");
28
+ if (n <= 0) return { nrm2: 0 };
29
+ if (x.length < (n - 1) * incx + 1)
30
+ throw new Error(
31
+ "x does not have enough elements for the given n and incx.",
32
+ );
33
+
34
+ const pipelineMain = await getPipeline(device, "snrm2");
35
+ const pipelineReduce = await getPipeline(device, "reduction/sum");
36
+
37
+ const xBuffer = xIsGpu ? x._buf : uploadBuffer(x, "snrm2-x", false);
38
+ const partialsBuffer = createStorageBuffer(2 * WGS * 4, "snrm2-partials"); // 2*WGS partial sums of f32
39
+ const resultBuffer = createResultBuffer(4, "snrm2-result"); // final f32 scalar
40
+ const paramsBuffer = createParamsBuffer(
41
+ [
42
+ { value: n, type: "u32" },
43
+ { value: incx, type: "u32" },
44
+ ],
45
+ "snrm2-params",
46
+ );
47
+
48
+ const bgMain = createBindGroup(pipelineMain.getBindGroupLayout(0), [
49
+ xBuffer,
50
+ partialsBuffer,
51
+ paramsBuffer,
52
+ ]);
53
+ const { commandEncoder: enc1, ts: ts1 } = runComputePass(
54
+ pipelineMain,
55
+ bgMain,
56
+ 2 * WGS,
57
+ ); // dispatch 2*WGS workgroups
58
+
59
+ submit(enc1);
60
+
61
+ const bgReduce = createBindGroup(pipelineReduce.getBindGroupLayout(0), [
62
+ partialsBuffer,
63
+ resultBuffer,
64
+ ]);
65
+ const { commandEncoder: enc2, ts: ts2 } = runComputePass(
66
+ pipelineReduce,
67
+ bgReduce,
68
+ 1,
69
+ ); // reduce partials to single result
70
+ const readBuffer = stageReadback(enc2, resultBuffer);
71
+
72
+ submit(enc2);
73
+
74
+ const [gpuTime1, gpuTime2, sqsumArr] = await Promise.all([
75
+ extractTimestamp(ts1),
76
+ extractTimestamp(ts2),
77
+ extractResult(readBuffer, Float32Array),
78
+ ]);
79
+
80
+ // sqrt is taken on CPU after the GPU sum-of-squares reduction
81
+ const nrm2 = Math.sqrt(sqsumArr[0]);
82
+
83
+ if (xIsGpu) {
84
+ destroyBuffers(partialsBuffer, resultBuffer, paramsBuffer, readBuffer);
85
+ if (gpuTime1 !== undefined && gpuTime2 !== undefined)
86
+ return { nrm2, gpuTimeMs: gpuTime1 + gpuTime2 };
87
+ return { nrm2 };
88
+ }
89
+
90
+ destroyBuffers(
91
+ xBuffer,
92
+ partialsBuffer,
93
+ resultBuffer,
94
+ paramsBuffer,
95
+ readBuffer,
96
+ );
97
+ if (gpuTime1 !== undefined && gpuTime2 !== undefined)
98
+ return { nrm2, gpuTimeMs: gpuTime1 + gpuTime2 };
99
+ return { nrm2 };
100
+ }
@@ -0,0 +1,62 @@
1
+ import { GpuVector } from "../classes/GpuVector.mjs";
2
+
3
+ /**
4
+ * Applies a Givens plane rotation to vectors x and y:
5
+ * x = c*x + s*y
6
+ * y = -s*x + c*y
7
+ *
8
+ * {@includeCode ../../examples/srot/srot.js}
9
+ *
10
+ * **Browser (standalone HTML):**
11
+ * {@includeCode ../../examples/srot/web/srot.html}
12
+ *
13
+ * @param device - GPUDevice from `init()`
14
+ * @param n - number of elements (must be a positive integer)
15
+ * @param x - Float32Array input/output vector
16
+ * @param incx - stride for x (must be a positive integer)
17
+ * @param y - Float32Array input/output vector
18
+ * @param incy - stride for y (must be a positive integer)
19
+ * @param c - cosine of rotation angle
20
+ * @param s - sine of rotation angle
21
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/srot/srot.mjs#L15">Source code: srot.mjs (L15)</a>
22
+ * @category BLAS Level 1
23
+ */
24
+ export declare function srot(
25
+ device: GPUDevice,
26
+ n: number,
27
+ x: Float32Array,
28
+ incx: number,
29
+ y: Float32Array,
30
+ incy: number,
31
+ c: number,
32
+ s: number,
33
+ ): Promise<{ x: Float32Array; y: Float32Array } | { x: Float32Array; y: Float32Array; gpuTimeMs: number }>;
34
+
35
+ /**
36
+ * Applies a Givens plane rotation to vectors x and y:
37
+ * x = c*x + s*y
38
+ * y = -s*x + c*y
39
+ *
40
+ * {@includeCode ../../examples/srot/gpuvec.srot.js}
41
+ *
42
+ * @param device - GPUDevice from `init()`
43
+ * @param n - number of elements (must be a positive integer)
44
+ * @param x - GpuVector input/output vector (mutated in place)
45
+ * @param incx - stride for x (must be a positive integer)
46
+ * @param y - GpuVector input/output vector (mutated in place)
47
+ * @param incy - stride for y (must be a positive integer)
48
+ * @param c - cosine of rotation angle
49
+ * @param s - sine of rotation angle
50
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/srot/srot.mjs#L15">Source code: srot.mjs (L15)</a>
51
+ * @category BLAS Level 1
52
+ */
53
+ export declare function srot(
54
+ device: GPUDevice,
55
+ n: number,
56
+ x: GpuVector,
57
+ incx: number,
58
+ y: GpuVector,
59
+ incy: number,
60
+ c: number,
61
+ s: number,
62
+ ): Promise<{} | { gpuTimeMs: number }>;
@@ -0,0 +1,95 @@
1
+ import {
2
+ uploadBuffer,
3
+ createParamsBuffer,
4
+ stageReadback,
5
+ destroyBuffers,
6
+ } from "../util/buffer.mjs";
7
+ import { createBindGroup } from "../util/bindgroup.mjs";
8
+ import { runComputePass, submit } from "../util/compute.mjs";
9
+ import { extractTimestamp } from "../util/benchmark.mjs";
10
+ import { extractResult } from "../util/result.mjs";
11
+ import { getPipeline } from "../util/pipeline.mjs";
12
+ import { calcWorkgroups } from "../util/workgroup.mjs";
13
+ import { GpuVector } from "../classes/GpuVector.mjs";
14
+
15
+ export async function srot(device, n, x, incx, y, incy, c, s) {
16
+ const xIsGpu = x instanceof GpuVector;
17
+ const yIsGpu = y instanceof GpuVector;
18
+
19
+ if (!(device instanceof GPUDevice))
20
+ throw new Error("device must be a GPUDevice.");
21
+ if (
22
+ !Number.isInteger(n) ||
23
+ !Number.isInteger(incx) ||
24
+ !Number.isInteger(incy)
25
+ )
26
+ throw new Error("n, incx, and incy must be integers.");
27
+ if (isNaN(c) || isNaN(s)) throw new Error("c and s must not be NaN.");
28
+ if (!isFinite(c)) throw new Error("c must be finite.");
29
+ if (!isFinite(s)) throw new Error("s must be finite.");
30
+ if (incx <= 0 || incy <= 0)
31
+ throw new Error("incx and incy must be positive.");
32
+ if (!xIsGpu && !(x instanceof Float32Array))
33
+ throw new Error("x must be a Float32Array or GpuVector.");
34
+ if (!yIsGpu && !(y instanceof Float32Array))
35
+ throw new Error("y must be a Float32Array or GpuVector.");
36
+ if (xIsGpu !== yIsGpu)
37
+ throw new Error(
38
+ "x and y must be the same type (both Float32Array or both GpuVector).",
39
+ );
40
+ if (n <= 0) return xIsGpu ? {} : { x, y };
41
+ if (x.length < (n - 1) * incx + 1)
42
+ throw new Error(
43
+ "x does not have enough elements for the given n and incx.",
44
+ );
45
+ if (y.length < (n - 1) * incy + 1)
46
+ throw new Error(
47
+ "y does not have enough elements for the given n and incy.",
48
+ );
49
+
50
+ const pipeline = await getPipeline(device, "srot");
51
+
52
+ const xBuffer = xIsGpu ? x._buf : uploadBuffer(x, "srot-x", true);
53
+ const yBuffer = yIsGpu ? y._buf : uploadBuffer(y, "srot-y", true);
54
+ const paramsBuffer = createParamsBuffer(
55
+ [
56
+ { value: n, type: "u32" },
57
+ { value: c, type: "f32" },
58
+ { value: s, type: "f32" },
59
+ { value: incx, type: "u32" },
60
+ { value: incy, type: "u32" },
61
+ ],
62
+ "srot-params",
63
+ );
64
+
65
+ const bindGroup = createBindGroup(pipeline.getBindGroupLayout(0), [
66
+ xBuffer,
67
+ yBuffer,
68
+ paramsBuffer,
69
+ ]);
70
+ const { commandEncoder, ts } = runComputePass(
71
+ pipeline,
72
+ bindGroup,
73
+ calcWorkgroups(n),
74
+ );
75
+ const readX = xIsGpu ? null : stageReadback(commandEncoder, xBuffer);
76
+ const readY = yIsGpu ? null : stageReadback(commandEncoder, yBuffer);
77
+ submit(commandEncoder);
78
+
79
+ const gpuTimeMs = await extractTimestamp(ts);
80
+
81
+ if (xIsGpu && yIsGpu) {
82
+ destroyBuffers(paramsBuffer);
83
+ if (gpuTimeMs !== undefined) return { gpuTimeMs };
84
+ return {};
85
+ }
86
+
87
+ const [xResult, yResult] = await Promise.all([
88
+ extractResult(readX, Float32Array),
89
+ extractResult(readY, Float32Array),
90
+ ]);
91
+ destroyBuffers(xBuffer, yBuffer, paramsBuffer, readX, readY);
92
+
93
+ if (gpuTimeMs !== undefined) return { x: xResult, y: yResult, gpuTimeMs };
94
+ return { x: xResult, y: yResult };
95
+ }
@@ -0,0 +1,60 @@
1
+ import { GpuVector } from "../classes/GpuVector.mjs";
2
+
3
+ /**
4
+ * Applies a modified Givens plane rotation H to vectors x and y:
5
+ * x = H[0][0]*x + H[0][1]*y
6
+ * y = H[1][0]*x + H[1][1]*y
7
+ *
8
+ * {@includeCode ../../examples/srotm/srotm.js}
9
+ *
10
+ * **Browser (standalone HTML):**
11
+ * {@includeCode ../../examples/srotm/web/srotm.html}
12
+ *
13
+ * @param device - GPUDevice from `init()`
14
+ * @param n - number of elements (must be a positive integer)
15
+ * @param x - Float32Array input/output vector
16
+ * @param incx - stride for x (must be a positive integer)
17
+ * @param y - Float32Array input/output vector
18
+ * @param incy - stride for y (must be a positive integer)
19
+ * @param param - 5-element Float32Array: [flag, h11, h21, h12, h22]
20
+ * flag = -2: identity (no-op), -1: full H, 0: unit diagonal, 1: unit off-diagonal
21
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/srotm/srotm.mjs#L15">Source code: srotm.mjs (L15)</a>
22
+ * @category BLAS Level 1
23
+ */
24
+ export declare function srotm(
25
+ device: GPUDevice,
26
+ n: number,
27
+ x: Float32Array,
28
+ incx: number,
29
+ y: Float32Array,
30
+ incy: number,
31
+ param: Float32Array,
32
+ ): Promise<{ x: Float32Array; y: Float32Array } | { x: Float32Array; y: Float32Array; gpuTimeMs: number }>;
33
+
34
+ /**
35
+ * Applies a modified Givens plane rotation H to vectors x and y:
36
+ * x = H[0][0]*x + H[0][1]*y
37
+ * y = H[1][0]*x + H[1][1]*y
38
+ *
39
+ * {@includeCode ../../examples/srotm/gpuvec.srotm.js}
40
+ *
41
+ * @param device - GPUDevice from `init()`
42
+ * @param n - number of elements (must be a positive integer)
43
+ * @param x - GpuVector input/output vector (mutated in place)
44
+ * @param incx - stride for x (must be a positive integer)
45
+ * @param y - GpuVector input/output vector (mutated in place)
46
+ * @param incy - stride for y (must be a positive integer)
47
+ * @param param - 5-element Float32Array: [flag, h11, h21, h12, h22]
48
+ * flag = -2: identity (no-op), -1: full H, 0: unit diagonal, 1: unit off-diagonal
49
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/srotm/srotm.mjs#L15">Source code: srotm.mjs (L15)</a>
50
+ * @category BLAS Level 1
51
+ */
52
+ export declare function srotm(
53
+ device: GPUDevice,
54
+ n: number,
55
+ x: GpuVector,
56
+ incx: number,
57
+ y: GpuVector,
58
+ incy: number,
59
+ param: Float32Array,
60
+ ): Promise<{} | { gpuTimeMs: number }>;
@@ -0,0 +1,94 @@
1
+ import {
2
+ uploadBuffer,
3
+ createParamsBuffer,
4
+ stageReadback,
5
+ destroyBuffers,
6
+ } from "../util/buffer.mjs";
7
+ import { createBindGroup } from "../util/bindgroup.mjs";
8
+ import { runComputePass, submit } from "../util/compute.mjs";
9
+ import { extractTimestamp } from "../util/benchmark.mjs";
10
+ import { extractResult } from "../util/result.mjs";
11
+ import { getPipeline } from "../util/pipeline.mjs";
12
+ import { calcWorkgroups } from "../util/workgroup.mjs";
13
+ import { GpuVector } from "../classes/GpuVector.mjs";
14
+
15
+ export async function srotm(device, n, x, incx, y, incy, param) {
16
+ const xIsGpu = x instanceof GpuVector;
17
+ const yIsGpu = y instanceof GpuVector;
18
+
19
+ if (!(device instanceof GPUDevice))
20
+ throw new Error("device must be a GPUDevice.");
21
+ if (
22
+ !Number.isInteger(n) ||
23
+ !Number.isInteger(incx) ||
24
+ !Number.isInteger(incy)
25
+ )
26
+ throw new Error("n, incx, and incy must be integers.");
27
+ if (!(param instanceof Float32Array) || param.length !== 5)
28
+ throw new Error("param must be a Float32Array of length 5.");
29
+ if (incx <= 0 || incy <= 0)
30
+ throw new Error("incx and incy must be positive.");
31
+ if (!xIsGpu && !(x instanceof Float32Array))
32
+ throw new Error("x must be a Float32Array or GpuVector.");
33
+ if (!yIsGpu && !(y instanceof Float32Array))
34
+ throw new Error("y must be a Float32Array or GpuVector.");
35
+ if (xIsGpu !== yIsGpu)
36
+ throw new Error(
37
+ "x and y must be the same type (both Float32Array or both GpuVector).",
38
+ );
39
+ if (n <= 0 || param[0] === -2.0) return xIsGpu ? {} : { x, y };
40
+ if (x.length < (n - 1) * incx + 1)
41
+ throw new Error(
42
+ "x does not have enough elements for the given n and incx.",
43
+ );
44
+ if (y.length < (n - 1) * incy + 1)
45
+ throw new Error(
46
+ "y does not have enough elements for the given n and incy.",
47
+ );
48
+
49
+ const pipeline = await getPipeline(device, "srotm");
50
+
51
+ const xBuffer = xIsGpu ? x._buf : uploadBuffer(x, "srotm-x", true);
52
+ const yBuffer = yIsGpu ? y._buf : uploadBuffer(y, "srotm-y", true);
53
+ const paramBuffer = uploadBuffer(param, "srotm-param", false);
54
+ const paramsBuffer = createParamsBuffer(
55
+ [
56
+ { value: n, type: "u32" },
57
+ { value: incx, type: "u32" },
58
+ { value: incy, type: "u32" },
59
+ ],
60
+ "srotm-params",
61
+ );
62
+
63
+ const bindGroup = createBindGroup(pipeline.getBindGroupLayout(0), [
64
+ xBuffer,
65
+ yBuffer,
66
+ paramBuffer,
67
+ paramsBuffer,
68
+ ]);
69
+ const { commandEncoder, ts } = runComputePass(
70
+ pipeline,
71
+ bindGroup,
72
+ calcWorkgroups(n),
73
+ );
74
+ const readX = xIsGpu ? null : stageReadback(commandEncoder, xBuffer);
75
+ const readY = yIsGpu ? null : stageReadback(commandEncoder, yBuffer);
76
+ submit(commandEncoder);
77
+
78
+ const gpuTimeMs = await extractTimestamp(ts);
79
+
80
+ if (xIsGpu && yIsGpu) {
81
+ destroyBuffers(paramBuffer, paramsBuffer);
82
+ if (gpuTimeMs !== undefined) return { gpuTimeMs };
83
+ return {};
84
+ }
85
+
86
+ const [xResult, yResult] = await Promise.all([
87
+ extractResult(readX, Float32Array),
88
+ extractResult(readY, Float32Array),
89
+ ]);
90
+ destroyBuffers(xBuffer, yBuffer, paramBuffer, paramsBuffer, readX, readY);
91
+
92
+ if (gpuTimeMs !== undefined) return { x: xResult, y: yResult, gpuTimeMs };
93
+ return { x: xResult, y: yResult };
94
+ }
@@ -0,0 +1,46 @@
1
+ import { GpuVector } from "../classes/GpuVector.mjs";
2
+
3
+ /**
4
+ * Scales a single-precision vector by a constant: x = alpha * x
5
+ *
6
+ * {@includeCode ../../examples/sscal/sscal.js}
7
+ *
8
+ * **Browser (standalone HTML):**
9
+ * {@includeCode ../../examples/sscal/web/sscal.html}
10
+ *
11
+ * @param device - GPUDevice from `init()`
12
+ * @param n - number of elements to scale (must be a positive integer)
13
+ * @param alpha - scalar multiplier
14
+ * @param x - Float32Array input/output vector
15
+ * @param incx - stride for x (must be a positive integer)
16
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/sscal/sscal.mjs#L15">Source code: sscal.mjs (L15)</a>
17
+ * @category BLAS Level 1
18
+ */
19
+ export declare function sscal(
20
+ device: GPUDevice,
21
+ n: number,
22
+ alpha: number,
23
+ x: Float32Array,
24
+ incx: number,
25
+ ): Promise<Float32Array | { result: Float32Array; gpuTimeMs: number }>;
26
+
27
+ /**
28
+ * Scales a single-precision vector by a constant: x = alpha * x
29
+ *
30
+ * {@includeCode ../../examples/sscal/gpuvec.sscal.js}
31
+ *
32
+ * @param device - GPUDevice from `init()`
33
+ * @param n - number of elements to scale (must be a positive integer)
34
+ * @param alpha - scalar multiplier
35
+ * @param x - GpuVector input/output vector (mutated in place)
36
+ * @param incx - stride for x (must be a positive integer)
37
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/sscal/sscal.mjs#L15">Source code: sscal.mjs (L15)</a>
38
+ * @category BLAS Level 1
39
+ */
40
+ export declare function sscal(
41
+ device: GPUDevice,
42
+ n: number,
43
+ alpha: number,
44
+ x: GpuVector,
45
+ incx: number,
46
+ ): Promise<{} | { gpuTimeMs: number }>;
@@ -0,0 +1,71 @@
1
+ import {
2
+ uploadBuffer,
3
+ createParamsBuffer,
4
+ stageReadback,
5
+ destroyBuffers,
6
+ } from "../util/buffer.mjs";
7
+ import { createBindGroup } from "../util/bindgroup.mjs";
8
+ import { runComputePass, submit } from "../util/compute.mjs";
9
+ import { extractResult } from "../util/result.mjs";
10
+ import { extractTimestamp } from "../util/benchmark.mjs";
11
+ import { getPipeline } from "../util/pipeline.mjs";
12
+ import { calcWorkgroups } from "../util/workgroup.mjs";
13
+ import { GpuVector } from "../classes/GpuVector.mjs";
14
+
15
+ export async function sscal(device, n, alpha, x, incx) {
16
+ const xIsGpu = x instanceof GpuVector;
17
+
18
+ if (!(device instanceof GPUDevice))
19
+ throw new Error("device must be a GPUDevice.");
20
+ if (!Number.isInteger(n) || !Number.isInteger(incx))
21
+ throw new Error("n and incx must be integers.");
22
+ if (isNaN(alpha)) throw new Error("alpha must not be NaN.");
23
+ if (!isFinite(alpha)) throw new Error("alpha must be finite.");
24
+ if (incx <= 0) throw new Error("incx must be positive.");
25
+ if (!(x instanceof Float32Array) && !(x instanceof GpuVector))
26
+ throw new Error("x must be a Float32Array or GpuVector.");
27
+ if (n <= 0) return xIsGpu ? {} : x;
28
+ if (x.length < (n - 1) * incx + 1)
29
+ throw new Error(
30
+ "x does not have enough elements for the given n and incx.",
31
+ );
32
+
33
+ const pipeline = await getPipeline(device, "sscal");
34
+
35
+ const xBuffer = xIsGpu ? x._buf : uploadBuffer(x, "sscal-x", true);
36
+ const paramsBuffer = createParamsBuffer(
37
+ [
38
+ { value: n, type: "u32" },
39
+ { value: alpha, type: "f32" },
40
+ { value: incx, type: "u32" },
41
+ ],
42
+ "sscal-params",
43
+ );
44
+
45
+ const bindGroup = createBindGroup(pipeline.getBindGroupLayout(0), [
46
+ xBuffer,
47
+ paramsBuffer,
48
+ ]);
49
+ const { commandEncoder, ts } = runComputePass(
50
+ pipeline,
51
+ bindGroup,
52
+ calcWorkgroups(n),
53
+ );
54
+ const readBuffer = xIsGpu ? null : stageReadback(commandEncoder, xBuffer);
55
+
56
+ submit(commandEncoder);
57
+
58
+ const gpuTimeMs = await extractTimestamp(ts);
59
+
60
+ if (xIsGpu) {
61
+ destroyBuffers(paramsBuffer);
62
+ if (gpuTimeMs !== undefined) return { gpuTimeMs };
63
+ return {};
64
+ }
65
+
66
+ const result = await extractResult(readBuffer, Float32Array);
67
+ destroyBuffers(xBuffer, paramsBuffer, readBuffer);
68
+
69
+ if (gpuTimeMs !== undefined) return { result, gpuTimeMs };
70
+ return result;
71
+ }
@@ -0,0 +1,50 @@
1
+ import { GpuVector } from "../classes/GpuVector.mjs";
2
+
3
+ /**
4
+ * Swaps the elements of two single-precision vectors: x <-> y
5
+ *
6
+ * {@includeCode ../../examples/sswap/sswap.js}
7
+ *
8
+ * **Browser (standalone HTML):**
9
+ * {@includeCode ../../examples/sswap/web/sswap.html}
10
+ *
11
+ * @param device - GPUDevice from `init()`
12
+ * @param n - number of elements to swap (must be a positive integer)
13
+ * @param x - Float32Array first input/output vector
14
+ * @param incx - stride for x (must be a positive integer)
15
+ * @param y - Float32Array second input/output vector
16
+ * @param incy - stride for y (must be a positive integer)
17
+ * @see [Source code: sswap.mjs (L15)](https://github.com/manit2004/wgblas/blob/main/src/sswap/sswap.mjs#L15)
18
+ * @category BLAS Level 1
19
+ */
20
+ export declare function sswap(
21
+ device: GPUDevice,
22
+ n: number,
23
+ x: Float32Array,
24
+ incx: number,
25
+ y: Float32Array,
26
+ incy: number,
27
+ ): Promise<{ x: Float32Array; y: Float32Array } | { x: Float32Array; y: Float32Array; gpuTimeMs: number }>;
28
+
29
+ /**
30
+ * Swaps the elements of two single-precision vectors: x <-> y
31
+ *
32
+ * {@includeCode ../../examples/sswap/gpuvec.sswap.js}
33
+ *
34
+ * @param device - GPUDevice from `init()`
35
+ * @param n - number of elements to swap (must be a positive integer)
36
+ * @param x - GpuVector first input/output vector (mutated in place)
37
+ * @param incx - stride for x (must be a positive integer)
38
+ * @param y - GpuVector second input/output vector (mutated in place)
39
+ * @param incy - stride for y (must be a positive integer)
40
+ * @see <a href="https://github.com/manit2004/wgblas/blob/main/src/sswap/sswap.mjs#L15">Source code: sswap.mjs (L15)</a>
41
+ * @category BLAS Level 1
42
+ */
43
+ export declare function sswap(
44
+ device: GPUDevice,
45
+ n: number,
46
+ x: GpuVector,
47
+ incx: number,
48
+ y: GpuVector,
49
+ incy: number,
50
+ ): Promise<{} | { gpuTimeMs: number }>;