diff --git a/lib/node_modules/@stdlib/blas/base/gscal/README.md b/lib/node_modules/@stdlib/blas/base/gscal/README.md index 716a776efe8f..b77e4f06c024 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/README.md +++ b/lib/node_modules/@stdlib/blas/base/gscal/README.md @@ -109,6 +109,7 @@ gscal.ndarray( 3, 5.0, x, 1, x.length-3 ); - If `N <= 0`, both functions return `x` unchanged. - `gscal()` corresponds to the [BLAS][blas] level 1 function [`dscal`][dscal] with the exception that this implementation works with any array type, not just Float64Arrays. Depending on the environment, the typed versions ([`dscal`][@stdlib/blas/base/dscal], [`sscal`][@stdlib/blas/base/sscal], 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]). @@ -166,6 +167,8 @@ console.log( x ); [mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray +[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor + [@stdlib/blas/base/dscal]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/dscal [@stdlib/blas/base/sscal]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/sscal diff --git a/lib/node_modules/@stdlib/blas/base/gscal/docs/types/index.d.ts b/lib/node_modules/@stdlib/blas/base/gscal/docs/types/index.d.ts index 32c56f8367d4..8453ebed2020 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/blas/base/gscal/docs/types/index.d.ts @@ -20,7 +20,12 @@ /// -import { NumericArray } from '@stdlib/types/array'; +import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array'; + +/** +* Input array. +*/ +type InputArray = NumericArray | Collection | AccessorArrayLike; /** * Interface describing `gscal`. @@ -41,7 +46,7 @@ interface Routine { * gscal( x.length, 5.0, x, 1 ); * // x => [ -10.0, 5.0, 15.0, -25.0, 20.0, 0.0, -5.0, -15.0 ] */ - ( N: number, alpha: number, x: NumericArray, stride: number ): NumericArray; + ( N: number, alpha: number, x: T, stride: number ): T; /** * Multiplies a vector `x` by a constant `alpha` using alternative indexing semantics. @@ -59,7 +64,7 @@ interface Routine { * gscal.ndarray( x.length, 5.0, x, 1, 0 ); * // x => [ -10.0, 5.0, 15.0, -25.0, 20.0, 0.0, -5.0, -15.0 ] */ - ndarray( N: number, alpha: number, x: NumericArray, stride: number, offset: number ): NumericArray; + ndarray( N: number, alpha: number, x: T, stride: number, offset: number ): T; } /** diff --git a/lib/node_modules/@stdlib/blas/base/gscal/docs/types/test.ts b/lib/node_modules/@stdlib/blas/base/gscal/docs/types/test.ts index 4601b139a1dd..08bfd85784e6 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/docs/types/test.ts +++ b/lib/node_modules/@stdlib/blas/base/gscal/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import gscal = require( './index' ); @@ -25,7 +26,8 @@ import gscal = require( './index' ); { const x = new Float64Array( 10 ); - gscal( x.length, 5.0, x, 1 ); // $ExpectType NumericArray + gscal( x.length, 5.0, x, 1 ); // $ExpectType Float64Array + gscal( x.length, 5.0, new AccessorArray( x ), 1 ); // $ExpectType AccessorArray } // The compiler throws an error if the function is provided a first argument which is not a number... @@ -100,7 +102,8 @@ import gscal = require( './index' ); { const x = new Float64Array( 10 ); - gscal.ndarray( x.length, 5.0, x, 1, 0 ); // $ExpectType NumericArray + gscal.ndarray( x.length, 5.0, x, 1, 0 ); // $ExpectType Float64Array + gscal.ndarray( x.length, 5.0, new AccessorArray( x ), 1, 0 ); // $ExpectType AccessorArray } // The compiler throws an error if the `ndarray` method is provided a first argument which is not a number... diff --git a/lib/node_modules/@stdlib/blas/base/gscal/lib/accessors.js b/lib/node_modules/@stdlib/blas/base/gscal/lib/accessors.js new file mode 100644 index 000000000000..4a672190318a --- /dev/null +++ b/lib/node_modules/@stdlib/blas/base/gscal/lib/accessors.js @@ -0,0 +1,101 @@ +/** +* @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'; + +// VARIABLES // + +var M = 5; + + +// MAIN // + +/** +* Multiplies `x` by a scalar `alpha`. +* +* @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} x.accessors - array element accessors +* @param {integer} stride - index increment +* @param {NonNegativeInteger} offset - starting index +* @returns {NumericArray} input array +* +* @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, -6.0 ]; +* +* gscal( 3, 5.0, arraylike2object( toAccessorArray( x ) ), 1, x.length-3 ); +* // x => [ 1.0, -2.0, 3.0, -20.0, 25.0, -30.0 ] +*/ +function gscal( N, alpha, x, stride, offset ) { + var xbuf; + var xget; + var xset; + var ix; + var m; + var i; + + xbuf = x.data; + xget = x.accessors[ 0 ]; + xset = x.accessors[ 1 ]; + + ix = offset; + if ( stride === 0 ) { + xset( xbuf, ix, xget( xbuf, ix ) * N * alpha ); + return x; + } + + // Use loop unrolling if the stride is equal to `1`... + if ( stride === 1 ) { + m = N % M; + + // If we have a remainder, run a clean-up loop... + if ( m > 0 ) { + for ( i = 0; i < m; i++ ) { + xset( xbuf, ix, xget( xbuf, ix ) * alpha ); + ix += stride; + } + } + if ( N < M ) { + return x; + } + for ( i = m; i < N; i += M ) { + xset( xbuf, ix, xget( xbuf, ix ) * alpha ); + xset( xbuf, ix+1, xget( xbuf, ix+1 ) * alpha ); + xset( xbuf, ix+2, xget( xbuf, ix+2 ) * alpha ); + xset( xbuf, ix+3, xget( xbuf, ix+3 ) * alpha ); + xset( xbuf, ix+4, xget( xbuf, ix+4 ) * alpha ); + ix += M; + } + return x; + } + for ( i = 0; i < N; i++ ) { + xset( xbuf, ix, xget( xbuf, ix ) * alpha ); + ix += stride; + } + return x; +} + + +// EXPORTS // + +module.exports = gscal; diff --git a/lib/node_modules/@stdlib/blas/base/gscal/lib/main.js b/lib/node_modules/@stdlib/blas/base/gscal/lib/main.js index fc9e825aebbf..7b71f23c01b7 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/lib/main.js +++ b/lib/node_modules/@stdlib/blas/base/gscal/lib/main.js @@ -18,9 +18,10 @@ 'use strict'; -// VARIABLES // +// MODULES // -var M = 5; +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -41,39 +42,7 @@ var M = 5; * // x => [ -10.0, 5.0, 15.0, -25.0, 20.0, 0.0, -5.0, -15.0 ] */ function gscal( N, alpha, x, stride ) { - var m; - var i; - - if ( N <= 0 || stride <= 0|| alpha === 1.0 ) { - return x; - } - // Use loop unrolling if the stride is equal to `1`... - if ( stride === 1 ) { - m = N % M; - - // If we have a remainder, run a clean-up loop... - if ( m > 0 ) { - for ( i = 0; i < m; i += 1 ) { - x[ i ] *= alpha; - } - } - if ( N < M ) { - return x; - } - for ( i = m; i < N; i += M ) { - x[ i ] *= alpha; - x[ i+1 ] *= alpha; - x[ i+2 ] *= alpha; - x[ i+3 ] *= alpha; - x[ i+4 ] *= alpha; - } - return x; - } - N *= stride; - for ( i = 0; i < N; i += stride ) { - x[ i ] *= alpha; - } - return x; + return ndarray( N, alpha, x, stride, stride2offset( N, stride ) ); } diff --git a/lib/node_modules/@stdlib/blas/base/gscal/lib/ndarray.js b/lib/node_modules/@stdlib/blas/base/gscal/lib/ndarray.js index b50f831fbf9c..4a1085fb8b05 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/gscal/lib/ndarray.js @@ -18,6 +18,12 @@ 'use strict'; +// MODULES // + +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +var accessors = require( './accessors.js' ); + + // VARIABLES // var M = 5; @@ -44,12 +50,23 @@ var M = 5; function gscal( N, alpha, x, stride, offset ) { var ix; var m; + var o; var i; if ( N <= 0 || alpha === 1.0 ) { return x; } + o = arraylike2object( x ); + if ( o.accessorProtocol ) { + accessors( N, alpha, o, stride, offset ); + return x; + } + ix = offset; + if ( stride === 0 ) { + x[ ix ] *= alpha * N; + return x; + } // Use loop unrolling if the stride is equal to `1`... if ( stride === 1 ) { @@ -66,11 +83,12 @@ function gscal( N, alpha, x, stride, offset ) { return x; } for ( i = m; i < N; i += M ) { - x[ i ] *= alpha; - x[ i+1 ] *= alpha; - x[ i+2 ] *= alpha; - x[ i+3 ] *= alpha; - x[ i+4 ] *= alpha; + x[ ix ] *= alpha; + x[ ix+1 ] *= alpha; + x[ ix+2 ] *= alpha; + x[ ix+3 ] *= alpha; + x[ ix+4 ] *= alpha; + ix += M; } return x; } diff --git a/lib/node_modules/@stdlib/blas/base/gscal/test/test.main.js b/lib/node_modules/@stdlib/blas/base/gscal/test/test.main.js index f27ce59e9cce..83136a5a86e7 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/base/gscal/test/test.main.js @@ -22,6 +22,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var gscal = require( './../lib/main.js' ); @@ -75,6 +76,43 @@ tape( 'the function multiplies `x` by a constant', function test( t ) { t.end(); }); +tape( 'the function multiplies `x` by a constant (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 4.0, + 2.0, + -3.0, + 5.0, + -1.0, + 2.0, + -5.0, + 6.0 + ]; + expected = [ + 20.0, + 10.0, + -15.0, + 25.0, + -5.0, + 10.0, + -25.0, + 30.0 + ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 1 ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1.0, 2.0 ]; + expected = [ 5.0, 10.0 ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 1 ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + tape( 'the function returns a reference to the input array', function test( t ) { var out; var x; @@ -86,6 +124,17 @@ tape( 'the function returns a reference to the input array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the input array (accessors)', function test( t ) { + var out; + var x; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + out = gscal( x.length, 3.0, x, 1 ); + + t.strictEqual( out, x, 'returns expected value' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `x` unchanged', function test( t ) { var expected; var x; @@ -139,17 +188,99 @@ tape( 'the function supports specifying a stride', function test( t ) { t.end(); }); -tape( 'if provided a `stride` less than or equal to `0`, the function returns `x` unchanged', function test( t ) { +tape( 'the function supports specifying a stride (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + 10.0, // 0 + -3.0, + -25.0, // 1 + 7.0, + 30.0 // 2 + ]; + + gscal( 3, 5.0, toAccessorArray( x ), 2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a negative stride', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + 10.0, // 2 + -3.0, + -25.0, // 1 + 7.0, + 30.0 // 0 + ]; + + gscal( 3, 5.0, x, -2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a negative stride (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + 10.0, // 2 + -3.0, + -25.0, // 1 + 7.0, + 30.0 // 0 + ]; + + gscal( 3, 5.0, toAccessorArray( x ), -2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'if provided a `stride` equal to `0`, the function multiplies first element of `x` by a constant `N` times', function test( t ) { var expected; var x; x = [ 3.0, -4.0, 1.0 ]; - expected = [ 3.0, -4.0, 1.0 ]; + expected = [ 45.0, -4.0, 1.0 ]; gscal( x.length, 5.0, x, 0 ); t.deepEqual( x, expected, 'returns expected value' ); - gscal( x.length, 5.0, x, -1 ); + t.end(); +}); + +tape( 'if provided a `stride` equal to `0`, the function multiplies first element of `x` by a constant `N` times (accessors)', function test( t ) { + var expected; + var x; + + x = [ 3.0, -4.0, 1.0 ]; + expected = [ 45.0, -4.0, 1.0 ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 0 ); t.deepEqual( x, expected, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/blas/base/gscal/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/gscal/test/test.ndarray.js index 73984ab3b6f7..7bb77dbc7a91 100644 --- a/lib/node_modules/@stdlib/blas/base/gscal/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/gscal/test/test.ndarray.js @@ -22,6 +22,7 @@ var tape = require( 'tape' ); var Float64Array = require( '@stdlib/array/float64' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var gscal = require( './../lib/ndarray.js' ); @@ -75,6 +76,43 @@ tape( 'the function multiplies `x` by a constant', function test( t ) { t.end(); }); +tape( 'the function multiplies `x` by a constant (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 4.0, + 2.0, + -3.0, + 5.0, + -1.0, + 2.0, + -5.0, + 6.0 + ]; + expected = [ + 20.0, + 10.0, + -15.0, + 25.0, + -5.0, + 10.0, + -25.0, + 30.0 + ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 1, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1.0, 2.0 ]; + expected = [ 5.0, 10.0 ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 1, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + tape( 'the function returns a reference to the input array', function test( t ) { var out; var x; @@ -86,6 +124,17 @@ tape( 'the function returns a reference to the input array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the input array (accessors)', function test( t ) { + var out; + var x; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + out = gscal( x.length, 3.0, x, 1, 0 ); + + t.strictEqual( out, x, 'returns expected value' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `x` unchanged', function test( t ) { var expected; var x; @@ -115,6 +164,32 @@ tape( 'if `alpha` equals `1`, the function returns `x` unchanged', function test t.end(); }); +tape( 'if provided a `stride` equal to `0`, the function multiplies first element of `x` by a constant `N` times', function test( t ) { + var expected; + var x; + + x = [ 3.0, -4.0, 1.0 ]; + expected = [ 45.0, -4.0, 1.0 ]; + + gscal( x.length, 5.0, x, 0, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'if provided a `stride` equal to `0`, the function multiplies first element of `x` by a constant `N` times (accessors)', function test( t ) { + var expected; + var x; + + x = [ 3.0, -4.0, 1.0 ]; + expected = [ 45.0, -4.0, 1.0 ]; + + gscal( x.length, 5.0, toAccessorArray( x ), 0, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + tape( 'the function supports specifying a stride', function test( t ) { var expected; var x; @@ -139,6 +214,30 @@ tape( 'the function supports specifying a stride', function test( t ) { t.end(); }); +tape( 'the function supports specifying a stride (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + 10.0, // 0 + -3.0, + -25.0, // 1 + 7.0, + 30.0 // 2 + ]; + + gscal( 3, 5.0, toAccessorArray( x ), 2, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a negative stride', function test( t ) { var expected; var x; @@ -151,11 +250,11 @@ tape( 'the function supports specifying a negative stride', function test( t ) { 6.0 // 0 ]; expected = [ - 10.0, // 0 + 10.0, // 2 -3.0, -25.0, // 1 7.0, - 30.0 // 2 + 30.0 // 0 ]; gscal( 3, 5.0, x, -2, x.length-1 ); @@ -163,6 +262,30 @@ tape( 'the function supports specifying a negative stride', function test( t ) { t.end(); }); +tape( 'the function supports specifying a negative stride (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + 10.0, // 2 + -3.0, + -25.0, // 1 + 7.0, + 30.0 // 0 + ]; + + gscal( 3, 5.0, toAccessorArray( x ), -2, x.length-1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports an offset parameter', function test( t ) { var expected; var x; @@ -177,11 +300,11 @@ tape( 'the function supports an offset parameter', function test( t ) { ]; expected = [ 1.0, - 10.0, + 10.0, // 0 3.0, - 20.0, + 20.0, // 1 5.0, - 30.0 + 30.0 // 2 ]; gscal( 3, 5.0, x, 2, 1 ); @@ -189,6 +312,32 @@ tape( 'the function supports an offset parameter', function test( t ) { t.end(); }); +tape( 'the function supports an offset parameter (accessors)', function test( t ) { + var expected; + var x; + + x = [ + 1.0, + 2.0, // 0 + 3.0, + 4.0, // 1 + 5.0, + 6.0 // 2 + ]; + expected = [ + 1.0, + 10.0, // 0 + 3.0, + 20.0, // 1 + 5.0, + 30.0 // 2 + ]; + + gscal( 3, 5.0, toAccessorArray( x ), 2, 1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'if `stride` is equal to `1`, the function efficiently multiplies `x` by a constant', function test( t ) { var expected; var alpha;