Skip to content

Commit cb8489a

Browse files
ShabiShett07kgryte
andauthored
feat: add support for accessor arrays blas/base/gaxpy
PR-URL: #7244 Co-authored-by: Athan Reines <kgryte@gmail.com> Reviewed-by: Athan Reines <kgryte@gmail.com>
1 parent 7531b27 commit cb8489a

File tree

9 files changed

+603
-77
lines changed

9 files changed

+603
-77
lines changed

lib/node_modules/@stdlib/blas/base/gaxpy/README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ The function has the following parameters:
4747

4848
- **N**: number of indexed elements.
4949
- **alpha**: `numeric` constant.
50-
- **x**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array].
50+
- **x**: first input array.
5151
- **strideX**: index increment for `x`.
52-
- **y**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array].
52+
- **y**: second input array.
5353
- **strideY**: index increment for `y`.
5454

5555
The `N` and stride parameters determine which elements in the strided arrays are accessed at runtime. For example, to multiply every other value in `x` by `alpha` and add the result to the first `N` elements of `y` in reverse order,
@@ -119,6 +119,7 @@ gaxpy.ndarray( 3, 5.0, x, 2, 1, y, -1, y.length-1 );
119119

120120
- If `N <= 0` or `alpha == 0`, both functions return `y` unchanged.
121121
- `gaxpy()` corresponds to the [BLAS][blas] level 1 function [`daxpy`][daxpy] with the exception that this implementation works with any array type, not just Float64Arrays. Depending on the environment, the typed versions ([`daxpy`][@stdlib/blas/base/daxpy], [`saxpy`][@stdlib/blas/base/saxpy], etc.) are likely to be significantly more performant.
122+
- Both functions support array-like objects having getter and setter accessors for array element access (e.g., [`@stdlib/array/base/accessor`][@stdlib/array/base/accessor]).
122123

123124
</section>
124125

@@ -174,14 +175,14 @@ console.log( y );
174175

175176
[daxpy]: http://www.netlib.org/lapack/explore-html/de/da4/group__double__blas__level1.html
176177

177-
[mdn-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
178-
179178
[mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
180179

181180
[@stdlib/blas/base/daxpy]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/daxpy
182181

183182
[@stdlib/blas/base/saxpy]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/saxpy
184183

184+
[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor
185+
185186
<!-- <related-links> -->
186187

187188
<!-- </related-links> -->

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,21 @@
1919
Constant.
2020

2121
x: Array<number>|TypedArray
22-
Input array.
22+
First input array.
2323

2424
strideX: integer
2525
Index increment for `x`.
2626

2727
y: Array<number>|TypedArray
28-
Output array.
28+
Second input array.
2929

3030
strideY: integer
3131
Index increment for `y`.
3232

3333
Returns
3434
-------
3535
y: Array<number>|TypedArray
36-
Output array.
36+
Input array `y`.
3737

3838
Examples
3939
--------
@@ -77,7 +77,7 @@
7777
Constant.
7878

7979
x: Array<number>|TypedArray
80-
Input array.
80+
First input array.
8181

8282
strideX: integer
8383
Index increment for `x`.
@@ -86,7 +86,7 @@
8686
Starting index for `x`.
8787

8888
y: Array<number>|TypedArray
89-
Output array.
89+
Second input array.
9090

9191
strideY: integer
9292
Index increment for `y`.
@@ -97,7 +97,7 @@
9797
Returns
9898
-------
9999
y: Array<number>|TypedArray
100-
Output array.
100+
Input array `y`.
101101

102102
Examples
103103
--------

lib/node_modules/@stdlib/blas/base/gaxpy/docs/types/index.d.ts

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

2121
/// <reference types="@stdlib/types"/>
2222

23-
import { NumericArray } from '@stdlib/types/array';
23+
import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array';
24+
25+
/**
26+
* Input array.
27+
*/
28+
type InputArray = NumericArray | Collection<number> | AccessorArrayLike<number>;
2429

2530
/**
2631
* Interface describing `gaxpy`.
@@ -44,7 +49,7 @@ interface Routine {
4449
* gaxpy( x.length, 5.0, x, 1, y, 1 );
4550
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
4651
*/
47-
( N: number, alpha: number, x: NumericArray, strideX: number, y: NumericArray, strideY: number ): NumericArray;
52+
<T extends InputArray = InputArray>( N: number, alpha: number, x: InputArray, strideX: number, y: T, strideY: number ): T;
4853

4954
/**
5055
* Multiplies `x` by a constant `alpha` and adds the result to `y` using alternative indexing semantics.
@@ -66,7 +71,7 @@ interface Routine {
6671
* gaxpy.ndarray( x.length, 5.0, x, 1, 0, y, 1, 0 );
6772
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
6873
*/
69-
ndarray( N: number, alpha: number, x: NumericArray, strideX: number, offsetX: number, y: NumericArray, strideY: number, offsetY: number ): NumericArray;
74+
ndarray<T extends InputArray = InputArray>( N: number, alpha: number, x: InputArray, strideX: number, offsetX: number, y: T, strideY: number, offsetY: number ): T;
7075
}
7176

7277
/**

lib/node_modules/@stdlib/blas/base/gaxpy/docs/types/test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ import gaxpy = require( './index' );
2121

2222
// TESTS //
2323

24-
// The function returns a numeric array...
24+
// The function returns an array...
2525
{
2626
const x = new Float64Array( 10 );
2727
const y = new Float64Array( 10 );
2828

29-
gaxpy( x.length, 5.0, x, 1, y, 1 ); // $ExpectType NumericArray
29+
gaxpy( x.length, 5.0, x, 1, y, 1 ); // $ExpectType Float64Array
3030
}
3131

3232
// The compiler throws an error if the function is provided a first argument which is not a number...
@@ -134,12 +134,12 @@ import gaxpy = require( './index' );
134134
gaxpy( x.length, 5.0, x, 1, y, 1, 10 ); // $ExpectError
135135
}
136136

137-
// Attached to main export is an `ndarray` method which returns a numeric array...
137+
// Attached to main export is an `ndarray` method which returns an array...
138138
{
139139
const x = new Float64Array( 10 );
140140
const y = new Float64Array( 10 );
141141

142-
gaxpy.ndarray( x.length, 5.0, x, 1, 0, y, 1, 0 ); // $ExpectType NumericArray
142+
gaxpy.ndarray( x.length, 5.0, x, 1, 0, y, 1, 0 ); // $ExpectType Float64Array
143143
}
144144

145145
// The compiler throws an error if the `ndarray` method is provided a first argument which is not a number...
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MAIN //
22+
23+
/**
24+
* Multiplies a vector `x` by a constant and adds the result to `y`.
25+
*
26+
* @private
27+
* @param {PositiveInteger} N - number of indexed elements
28+
* @param {number} alpha - scalar
29+
* @param {Object} x - input array object
30+
* @param {Collection} x.data - input array data
31+
* @param {Array<Function>} x.accessors - array element accessors
32+
* @param {integer} strideX - `x` stride length
33+
* @param {NonNegativeInteger} offsetX - starting `x` index
34+
* @param {Object} y - output array object
35+
* @param {Collection} y.data - output array data
36+
* @param {Array<Function>} y.accessors - array element accessors
37+
* @param {integer} strideY - `y` stride length
38+
* @param {NonNegativeInteger} offsetY - starting `y` index
39+
* @returns {Object} output array object
40+
*
41+
* @example
42+
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
43+
* var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
44+
*
45+
* var x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ];
46+
* var y = [ 1.0, 1.0, 1.0, 1.0, 1.0 ];
47+
*
48+
* gaxpy( x.length, 5.0, arraylike2object( toAccessorArray( x ) ), 1, 0, arraylike2object( toAccessorArray( y ) ), 1, 0 );
49+
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
50+
*/
51+
function gaxpy( N, alpha, x, strideX, offsetX, y, strideY, offsetY ) {
52+
var xbuf;
53+
var ybuf;
54+
var set;
55+
var get;
56+
var ix;
57+
var iy;
58+
var i;
59+
60+
// Cache references to array data:
61+
xbuf = x.data;
62+
ybuf = y.data;
63+
64+
// Cache references to element accessors:
65+
get = x.accessors[ 0 ];
66+
set = y.accessors[ 1 ];
67+
68+
ix = offsetX;
69+
iy = offsetY;
70+
for ( i = 0; i < N; i++ ) {
71+
set( ybuf, iy, get( ybuf, iy ) + ( alpha * get( xbuf, ix ) ) );
72+
ix += strideX;
73+
iy += strideY;
74+
}
75+
return y;
76+
}
77+
78+
79+
// EXPORTS //
80+
81+
module.exports = gaxpy;

lib/node_modules/@stdlib/blas/base/gaxpy/lib/main.js

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818

1919
'use strict';
2020

21-
// VARIABLES //
21+
// MODULES //
2222

23-
var M = 4;
23+
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
24+
var ndarray = require( './ndarray.js' );
2425

2526

2627
// MAIN //
@@ -45,50 +46,7 @@ var M = 4;
4546
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
4647
*/
4748
function gaxpy( N, alpha, x, strideX, y, strideY ) {
48-
var ix;
49-
var iy;
50-
var m;
51-
var i;
52-
if ( N <= 0 || alpha === 0.0 ) {
53-
return y;
54-
}
55-
// Use unrolled loops if both strides are equal to `1`...
56-
if ( strideX === 1 && strideY === 1 ) {
57-
m = N % M;
58-
59-
// If we have a remainder, run a clean-up loop...
60-
if ( m > 0 ) {
61-
for ( i = 0; i < m; i++ ) {
62-
y[ i ] += alpha * x[ i ];
63-
}
64-
}
65-
if ( N < M ) {
66-
return y;
67-
}
68-
for ( i = m; i < N; i += M ) {
69-
y[ i ] += alpha * x[ i ];
70-
y[ i+1 ] += alpha * x[ i+1 ];
71-
y[ i+2 ] += alpha * x[ i+2 ];
72-
y[ i+3 ] += alpha * x[ i+3 ];
73-
}
74-
return y;
75-
}
76-
if ( strideX < 0 ) {
77-
ix = (1-N) * strideX;
78-
} else {
79-
ix = 0;
80-
}
81-
if ( strideY < 0 ) {
82-
iy = (1-N) * strideY;
83-
} else {
84-
iy = 0;
85-
}
86-
for ( i = 0; i < N; i++ ) {
87-
y[ iy ] += alpha * x[ ix ];
88-
ix += strideX;
89-
iy += strideY;
90-
}
91-
return y;
49+
return ndarray( N, alpha, x, strideX, stride2offset( N, strideX ), y, strideY, stride2offset( N, strideY ) ); // eslint-disable-line max-len
9250
}
9351

9452

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818

1919
'use strict';
2020

21+
// MODULES //
22+
23+
var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
24+
var accessors = require( './accessors.js' );
25+
26+
2127
// VARIABLES //
2228

2329
var M = 4;
@@ -49,11 +55,19 @@ var M = 4;
4955
function gaxpy( N, alpha, x, strideX, offsetX, y, strideY, offsetY ) {
5056
var ix;
5157
var iy;
58+
var ox;
59+
var oy;
5260
var m;
5361
var i;
5462
if ( N <= 0 || alpha === 0.0 ) {
5563
return y;
5664
}
65+
ox = arraylike2object( x );
66+
oy = arraylike2object( y );
67+
if ( ox.accessorProtocol || oy.accessorProtocol ) {
68+
accessors( N, alpha, ox, strideX, offsetX, oy, strideY, offsetY );
69+
return oy.data;
70+
}
5771
ix = offsetX;
5872
iy = offsetY;
5973

0 commit comments

Comments
 (0)