Skip to content

Commit d063952

Browse files
committed
chore: update implementation
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 335d5ca commit d063952

26 files changed

+759
-68
lines changed

lib/node_modules/@stdlib/blas/base/sger/docs/repl.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
Indexing is relative to the first index. To introduce an offset, use typed
88
array views.
99

10-
If `M` or `N` or `α` is equal to `0`, the function returns `A` unchanged.
10+
If `M`, `N`, or `α` is equal to `0`, the function returns `A` unchanged.
1111

1212
Parameters
1313
----------

lib/node_modules/@stdlib/blas/base/sger/lib/base.js

Lines changed: 116 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,71 @@ var isRowMajor = require( '@stdlib/ndarray/base/assert/is-row-major' );
2727
// MAIN //
2828

2929
/**
30-
* Performs the rank 1 operation `A = α*x*y^T + A`, where `α` is a scalar, `x` is an `M` element vector, `y` is an `N` element vector and `A` is an `M` by `N` matrix.
30+
* Performs the rank 1 operation `A = α*x*y^T + A`, where `α` is a scalar, `x` is an `M` element vector, `y` is an `N` element vector, and `A` is an `M` by `N` matrix.
3131
*
32+
* ## Notes
33+
*
34+
* - To help motivate the use of loop interchange below, we first recognize that a matrix stored in row-major order is equivalent to storing the matrix's transpose in column-major order. For example, consider the following 2-by-3 matrix `A`
35+
*
36+
* ```tex
37+
* A = \begin{bmatrix}
38+
* 1 & 2 & 3 \\
39+
* 4 & 5 & 6
40+
* \end{bmatrix}
41+
* ```
42+
*
43+
* When stored in a linear buffer in column-major order, `A` becomes
44+
*
45+
* ```text
46+
* [ 1 4 2 5 3 6]
47+
* ```
48+
*
49+
* When stored in a linear buffer in row-major order, `A` becomes
50+
*
51+
* ```text
52+
* [ 1 2 3 4 5 6]
53+
* ```
54+
*
55+
* Now consider the transpose of `A`
56+
*
57+
* ```tex
58+
* A^T = \begin{bmatrix}
59+
* 1 & 4 \\
60+
* 2 & 5 \\
61+
* 3 & 6
62+
* \end{bmatrix}
63+
* ```
64+
*
65+
* When the transpose is stored in a linear buffer in column-major order, the transpose becomes
66+
*
67+
* ```text
68+
* [ 1 2 3 4 5 6 ]
69+
* ```
70+
*
71+
* Similarly, when stored in row-major order, the transpose becomes
72+
*
73+
* ```text
74+
* [ 1 4 2 5 3 6 ]
75+
* ```
76+
*
77+
* As may be observed, `A` stored in column-major order is equivalent to storing the transpose of `A` in row-major order, and storing `A` in row-major order is equivalent to storing the transpose of `A` in column-major order, and vice versa.
78+
*
79+
* Hence, we can interpret an `M` by `N` row-major matrix `B` as the matrix `A^T` stored in column-major order. In which case, we can derive an update equation for `B` as follows:
80+
*
81+
* ```tex
82+
* \begin{align*}
83+
* B &= A^T \\
84+
* &= (\alpha \bar{x} \bar{y}^T + A)^T \\
85+
* &= (\alpha \bar{x} \bar{y}^T)^T + A^T \\
86+
* &= \alpha (\bar{x} \bar{y}^T)^T + A^T \\
87+
* &= \alpha \bar{y} \bar{x}^T + A^T \\
88+
* &= \alpha \bar{y} \bar{x}^T + B
89+
* \end{align*}
90+
* ```
91+
*
92+
* Accordingly, we can reuse the same loop logic for column-major and row-major `A` by simply swapping `x` and `y` and `M` and `N` when `A` is row-major order. That is the essence of loop interchange.
93+
*
94+
* @private
3295
* @param {NonNegativeInteger} M - number of rows in the matrix `A`
3396
* @param {NonNegativeInteger} N - number of columns in the matrix `A`
3497
* @param {number} alpha - scalar constant
@@ -55,56 +118,68 @@ var isRowMajor = require( '@stdlib/ndarray/base/assert/is-row-major' );
55118
* // A => <Float32Array>[ 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 ]
56119
*/
57120
function sger( M, N, alpha, x, strideX, offsetX, y, strideY, offsetY, A, strideA1, strideA2, offsetA ) { // eslint-disable-line max-params, max-len
58-
var isrm;
59121
var tmp;
60-
var ix1;
61-
var iy1;
62-
var sa0;
63-
var sa1;
122+
var da0;
123+
var da1;
124+
var S0;
125+
var S1;
126+
var sx;
127+
var sy;
128+
var ia;
129+
var ix;
130+
var iy;
64131
var i0;
65132
var i1;
66-
var oa;
67133

68-
// Note on variable naming convention: sa#, ix#, i# where # corresponds to the loop number, with `0` being the innermost loop...
134+
// Note on variable naming convention: S#, da#, ia#, i# where # corresponds to the loop number, with `0` being the innermost loop...
69135

70-
isrm = isRowMajor( [ strideA1, strideA2 ] );
71-
if ( isrm ) {
136+
// Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments...
137+
if ( isRowMajor( [ strideA1, strideA2 ] ) ) {
72138
// For row-major matrices, the last dimension has the fastest changing index...
73-
sa0 = strideA2; // stride for innermost loop
74-
sa1 = strideA1; // stride for outermost loop
75-
} else { // isColMajor
139+
S0 = N;
140+
S1 = M;
141+
da0 = strideA2; // offset increment for innermost loop
142+
da1 = strideA1 - ( S0*strideA2 ); // offset increment for outermost loop
143+
144+
// Swap the vectors...
145+
tmp = x;
146+
x = y;
147+
y = tmp;
148+
149+
tmp = strideX;
150+
strideX = strideY;
151+
strideY = tmp;
152+
153+
tmp = offsetX;
154+
offsetX = offsetY;
155+
offsetY = tmp;
156+
} else { // order === 'column-major'
76157
// For column-major matrices, the first dimension has the fastest changing index...
77-
sa0 = strideA1; // stride for innermost loop
78-
sa1 = strideA2; // stride for outermost loop
79-
}
80-
if ( !isrm ) {
81-
iy1 = offsetY;
82-
for ( i1 = 0; i1 < N; i1++ ) {
83-
if ( y[ iy1 ] !== 0.0 ) {
84-
tmp = f32( alpha * y[ iy1 ] );
85-
ix1 = offsetX;
86-
oa = offsetA + ( sa1 * i1 );
87-
for ( i0 = 0; i0 < M; i0++ ) {
88-
A[ oa + ( sa0 * i0 ) ] += f32( x[ ix1 ] * tmp );
89-
ix1 += strideX;
90-
}
91-
}
92-
iy1 += strideY;
93-
}
94-
return A;
158+
S0 = M;
159+
S1 = N;
160+
da0 = strideA1; // offset increment for innermost loop
161+
da1 = strideA2 - ( S0*strideA1 ); // offset increment for outermost loop
95162
}
96-
ix1 = offsetX;
97-
for ( i1 = 0; i1 < M; i1++ ) {
98-
if ( x[ ix1 ] !== 0.0 ) {
99-
tmp = f32( alpha * x[ ix1 ] );
100-
iy1 = offsetY;
101-
oa = offsetA + ( sa1 * i1 );
102-
for ( i0 = 0; i0 < N; i0++ ) {
103-
A[ oa + ( sa0 * i0 ) ] += f32( y[ iy1 ] * tmp );
104-
iy1 += strideY;
163+
sx = strideX;
164+
sy = strideY;
165+
ix = offsetX;
166+
iy = offsetY;
167+
ia = offsetA;
168+
for ( i1 = 0; i1 < S1; i1++ ) {
169+
// Check whether we can avoid the inner loop entirely...
170+
if ( y[ iy ] === 0.0 ) {
171+
ia += da0 * S0;
172+
} else {
173+
tmp = f32( alpha * y[ iy ] );
174+
ix = offsetX;
175+
for ( i0 = 0; i0 < S0; i0++ ) {
176+
A[ ia ] += f32( x[ ix ] * tmp );
177+
ix += sx;
178+
ia += da0;
105179
}
106180
}
107-
ix1 += strideX;
181+
iy += sy;
182+
ia += da1;
108183
}
109184
return A;
110185
}

lib/node_modules/@stdlib/blas/base/sger/lib/ndarray.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @license Apache-2.0
33
*
4-
* Copyright (c) 2025 The Stdlib Authors.
4+
* Copyright (c) 2024 The Stdlib Authors.
55
*
66
* Licensed under the Apache License, Version 2.0 (the "License");
77
* you may not use this file except in compliance with the License.
@@ -27,7 +27,7 @@ var base = require( './base.js' );
2727
// MAIN //
2828

2929
/**
30-
* Performs the rank 1 operation `A = α*x*y^T + A`, where `α` is a scalar, `x` is an `M` element vector, `y` is an `N` element vector and `A` is an `M` by `N` matrix.
30+
* Performs the rank 1 operation `A = α*x*y^T + A`, where `α` is a scalar, `x` is an `M` element vector, `y` is an `N` element vector, and `A` is an `M` by `N` matrix.
3131
*
3232
* @param {NonNegativeInteger} M - number of rows in the matrix `A`
3333
* @param {NonNegativeInteger} N - number of columns in the matrix `A`
@@ -66,10 +66,10 @@ function sger( M, N, alpha, x, strideX, offsetX, y, strideY, offsetY, A, strideA
6666
throw new RangeError( format( 'invalid argument. Second argument must be a nonnegative integer. Value: `%d`.', N ) );
6767
}
6868
if ( strideX === 0 ) {
69-
throw new RangeError( format( 'invalid argument. Fifth argument must be non-zero.' ) );
69+
throw new RangeError( format( 'invalid argument. Fifth argument must be non-zero. Value: `%d`.', strideX ) );
7070
}
7171
if ( strideY === 0 ) {
72-
throw new RangeError( format( 'invalid argument. Eighth argument must be non-zero.' ) );
72+
throw new RangeError( format( 'invalid argument. Eighth argument must be non-zero. Value: `%d`.', strideY ) );
7373
}
7474
// Check if we can early return...
7575
if ( M === 0 || N === 0 || alpha === 0.0 ) {

lib/node_modules/@stdlib/blas/base/sger/lib/sger.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020

2121
// MODULES //
2222

23-
var max = require( '@stdlib/math/base/special/fast/max' );
24-
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
25-
var isLayout = require( '@stdlib/blas/base/assert/is-layout' );
2623
var isColumnMajor = require( '@stdlib/ndarray/base/assert/is-column-major-string' );
24+
var isLayout = require( '@stdlib/blas/base/assert/is-layout' );
25+
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
26+
var max = require( '@stdlib/math/base/special/fast/max' );
2727
var format = require( '@stdlib/string/format' );
2828
var base = require( './base.js' );
2929

lib/node_modules/@stdlib/blas/base/sger/test/fixtures/column_major_complex_access_pattern.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"order": "column-major",
23
"M": 2,
34
"N": 3,
45
"alpha": 1.0,

lib/node_modules/@stdlib/blas/base/sger/test/fixtures/column_major_oa.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"order": "column-major",
23
"M": 2,
34
"N": 3,
45
"alpha": 1.0,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"order": "column-major",
3+
"M": 2,
4+
"N": 3,
5+
"alpha": 1.0,
6+
"x": [ 0.0, 0.0, 1.0, 1.0 ],
7+
"strideX": 1,
8+
"offsetX": 2,
9+
"y": [ 1.0, 1.0, 1.0 ],
10+
"strideY": 1,
11+
"offsetY": 0,
12+
"A": [ 1.0, 4.0, 2.0, 5.0, 3.0, 6.0 ],
13+
"A_mat": [
14+
[ 1.0, 2.0, 3.0 ],
15+
[ 4.0, 5.0, 6.0 ]
16+
],
17+
"lda": 2,
18+
"strideA1": 1,
19+
"strideA2": 2,
20+
"offsetA": 0,
21+
"A_out": [ 2.0, 5.0, 3.0, 6.0, 4.0, 7.0 ]
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"order": "column-major",
3+
"M": 2,
4+
"N": 3,
5+
"alpha": 1.0,
6+
"x": [ 1.0, 1.0 ],
7+
"strideX": 1,
8+
"offsetX": 0,
9+
"y": [ 0.0, 0.0, 1.0, 1.0, 1.0 ],
10+
"strideY": 1,
11+
"offsetY": 2,
12+
"A": [ 1.0, 4.0, 2.0, 5.0, 3.0, 6.0 ],
13+
"A_mat": [
14+
[ 1.0, 2.0, 3.0 ],
15+
[ 4.0, 5.0, 6.0 ]
16+
],
17+
"lda": 2,
18+
"strideA1": 1,
19+
"strideA2": 2,
20+
"offsetA": 0,
21+
"A_out": [ 2.0, 5.0, 3.0, 6.0, 4.0, 7.0 ]
22+
}

lib/node_modules/@stdlib/blas/base/sger/test/fixtures/column_major_sa1_sa2.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"order": "column-major",
23
"M": 2,
34
"N": 3,
45
"alpha": 1.0,

lib/node_modules/@stdlib/blas/base/sger/test/fixtures/column_major_sa1_sa2n.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"order": "column-major",
23
"M": 2,
34
"N": 3,
45
"alpha": 1.0,

0 commit comments

Comments
 (0)