Skip to content

feat: add support for accessor arrays blas/base/gaxpy #7244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 7, 2025
9 changes: 5 additions & 4 deletions lib/node_modules/@stdlib/blas/base/gaxpy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ The function has the following parameters:

- **N**: number of indexed elements.
- **alpha**: `numeric` constant.
- **x**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array].
- **x**: first input array.
- **strideX**: index increment for `x`.
- **y**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array].
- **y**: second input array.
- **strideY**: index increment for `y`.

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,
Expand Down Expand Up @@ -119,6 +119,7 @@ gaxpy.ndarray( 3, 5.0, x, 2, 1, y, -1, y.length-1 );

- If `N <= 0` or `alpha == 0`, both functions return `y` unchanged.
- `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.
- 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]).

</section>

Expand Down Expand Up @@ -174,14 +175,14 @@ console.log( y );

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

[mdn-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

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

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

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

[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor

<!-- <related-links> -->

<!-- </related-links> -->
Expand Down
12 changes: 6 additions & 6 deletions lib/node_modules/@stdlib/blas/base/gaxpy/docs/repl.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@
Constant.

x: Array<number>|TypedArray
Input array.
First input array.

strideX: integer
Index increment for `x`.

y: Array<number>|TypedArray
Output array.
Second input array.

strideY: integer
Index increment for `y`.

Returns
-------
y: Array<number>|TypedArray
Output array.
Input array `y`.

Examples
--------
Expand Down Expand Up @@ -77,7 +77,7 @@
Constant.

x: Array<number>|TypedArray
Input array.
First input array.

strideX: integer
Index increment for `x`.
Expand All @@ -86,7 +86,7 @@
Starting index for `x`.

y: Array<number>|TypedArray
Output array.
Second input array.

strideY: integer
Index increment for `y`.
Expand All @@ -97,7 +97,7 @@
Returns
-------
y: Array<number>|TypedArray
Output array.
Input array `y`.

Examples
--------
Expand Down
11 changes: 8 additions & 3 deletions lib/node_modules/@stdlib/blas/base/gaxpy/docs/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@

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

import { NumericArray } from '@stdlib/types/array';
import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array';

/**
* Input array.
*/
type InputArray = NumericArray | Collection<number> | AccessorArrayLike<number>;

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

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

/**
Expand Down
8 changes: 4 additions & 4 deletions lib/node_modules/@stdlib/blas/base/gaxpy/docs/types/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ import gaxpy = require( './index' );

// TESTS //

// The function returns a numeric array...
// The function returns an array...
{
const x = new Float64Array( 10 );
const y = new Float64Array( 10 );

gaxpy( x.length, 5.0, x, 1, y, 1 ); // $ExpectType NumericArray
gaxpy( x.length, 5.0, x, 1, y, 1 ); // $ExpectType Float64Array
}

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

// Attached to main export is an `ndarray` method which returns a numeric array...
// Attached to main export is an `ndarray` method which returns an array...
{
const x = new Float64Array( 10 );
const y = new Float64Array( 10 );

gaxpy.ndarray( x.length, 5.0, x, 1, 0, y, 1, 0 ); // $ExpectType NumericArray
gaxpy.ndarray( x.length, 5.0, x, 1, 0, y, 1, 0 ); // $ExpectType Float64Array
}

// The compiler throws an error if the `ndarray` method is provided a first argument which is not a number...
Expand Down
81 changes: 81 additions & 0 deletions lib/node_modules/@stdlib/blas/base/gaxpy/lib/accessors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @license Apache-2.0
*
* Copyright (c) 2025 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MAIN //

/**
* Multiplies a vector `x` by a constant and adds the result to `y`.
*
* @private
* @param {PositiveInteger} N - number of indexed elements
* @param {number} alpha - scalar
* @param {Object} x - input array object
* @param {Collection} x.data - input array data
* @param {Array<Function>} x.accessors - array element accessors
* @param {integer} strideX - `x` stride length
* @param {NonNegativeInteger} offsetX - starting `x` index
* @param {Object} y - output array object
* @param {Collection} y.data - output array data
* @param {Array<Function>} y.accessors - array element accessors
* @param {integer} strideY - `y` stride length
* @param {NonNegativeInteger} offsetY - starting `y` index
* @returns {Object} output array object
*
* @example
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
* var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
*
* var x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ];
* var y = [ 1.0, 1.0, 1.0, 1.0, 1.0 ];
*
* gaxpy( x.length, 5.0, arraylike2object( toAccessorArray( x ) ), 1, 0, arraylike2object( toAccessorArray( y ) ), 1, 0 );
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
*/
function gaxpy( N, alpha, x, strideX, offsetX, y, strideY, offsetY ) {
var xbuf;
var ybuf;
var set;
var get;
var ix;
var iy;
var i;

// Cache references to array data:
xbuf = x.data;
ybuf = y.data;

// Cache references to element accessors:
get = x.accessors[ 0 ];
set = y.accessors[ 1 ];

ix = offsetX;
iy = offsetY;
for ( i = 0; i < N; i++ ) {
set( ybuf, iy, get( ybuf, iy ) + ( alpha * get( xbuf, ix ) ) );
ix += strideX;
iy += strideY;
}
return y;
}


// EXPORTS //

module.exports = gaxpy;
50 changes: 4 additions & 46 deletions lib/node_modules/@stdlib/blas/base/gaxpy/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

'use strict';

// VARIABLES //
// MODULES //

var M = 4;
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
var ndarray = require( './ndarray.js' );


// MAIN //
Expand All @@ -45,50 +46,7 @@ var M = 4;
* // y => [ 6.0, 11.0, 16.0, 21.0, 26.0 ]
*/
function gaxpy( N, alpha, x, strideX, y, strideY ) {
var ix;
var iy;
var m;
var i;
if ( N <= 0 || alpha === 0.0 ) {
return y;
}
// Use unrolled loops if both strides are equal to `1`...
if ( strideX === 1 && strideY === 1 ) {
m = N % M;

// If we have a remainder, run a clean-up loop...
if ( m > 0 ) {
for ( i = 0; i < m; i++ ) {
y[ i ] += alpha * x[ i ];
}
}
if ( N < M ) {
return y;
}
for ( i = m; i < N; i += M ) {
y[ i ] += alpha * x[ i ];
y[ i+1 ] += alpha * x[ i+1 ];
y[ i+2 ] += alpha * x[ i+2 ];
y[ i+3 ] += alpha * x[ i+3 ];
}
return y;
}
if ( strideX < 0 ) {
ix = (1-N) * strideX;
} else {
ix = 0;
}
if ( strideY < 0 ) {
iy = (1-N) * strideY;
} else {
iy = 0;
}
for ( i = 0; i < N; i++ ) {
y[ iy ] += alpha * x[ ix ];
ix += strideX;
iy += strideY;
}
return y;
return ndarray( N, alpha, x, strideX, stride2offset( N, strideX ), y, strideY, stride2offset( N, strideY ) ); // eslint-disable-line max-len
}


Expand Down
14 changes: 14 additions & 0 deletions lib/node_modules/@stdlib/blas/base/gaxpy/lib/ndarray.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@

'use strict';

// MODULES //

var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
var accessors = require( './accessors.js' );


// VARIABLES //

var M = 4;
Expand Down Expand Up @@ -49,11 +55,19 @@ var M = 4;
function gaxpy( N, alpha, x, strideX, offsetX, y, strideY, offsetY ) {
var ix;
var iy;
var ox;
var oy;
var m;
var i;
if ( N <= 0 || alpha === 0.0 ) {
return y;
}
ox = arraylike2object( x );
oy = arraylike2object( y );
if ( ox.accessorProtocol || oy.accessorProtocol ) {
accessors( N, alpha, ox, strideX, offsetX, oy, strideY, offsetY );
return oy.data;
}
ix = offsetX;
iy = offsetY;

Expand Down
Loading