diff --git a/lib/node_modules/@stdlib/blas/base/gasum/README.md b/lib/node_modules/@stdlib/blas/base/gasum/README.md index d4df1f5dd4de..0399673049a5 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/README.md +++ b/lib/node_modules/@stdlib/blas/base/gasum/README.md @@ -135,6 +135,7 @@ sum = gasum.ndarray( 3, x, -1, x.length-1 ); - If `N <= 0`, both functions return `0`. - `gasum()` corresponds to the [BLAS][blas] level 1 function [`dasum`][dasum] with the exception that this implementation works with any array type, not just Float64Arrays. Depending on the environment, the typed versions ([`dasum`][@stdlib/blas/base/dasum], [`sasum`][@stdlib/blas/base/sasum], 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]). @@ -199,6 +200,8 @@ console.log( y ); [@stdlib/blas/base/sasum]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/base/sasum +[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor + diff --git a/lib/node_modules/@stdlib/blas/base/gasum/docs/types/index.d.ts b/lib/node_modules/@stdlib/blas/base/gasum/docs/types/index.d.ts index 04306317feec..9a93cc539c19 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/blas/base/gasum/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 `gasum`. @@ -40,7 +45,7 @@ interface Routine { * var z = gasum( x.length, x, 1 ); * // returns 15.0 */ - ( N: number, x: NumericArray, stride: number ): number; + ( N: number, x: InputArray, stride: number ): number; /** * Computes the sum of the absolute values using alternative indexing semantics. @@ -57,7 +62,7 @@ interface Routine { * var z = gasum.ndarray( x.length, x, 1, 0 ); * // returns 21.0 */ - ndarray( N: number, x: NumericArray, stride: number, offset: number ): number; + ndarray( N: number, x: InputArray, stride: number, offset: number ): number; } /** diff --git a/lib/node_modules/@stdlib/blas/base/gasum/docs/types/test.ts b/lib/node_modules/@stdlib/blas/base/gasum/docs/types/test.ts index 11ab6a9d7d33..e18fef28bcdf 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/docs/types/test.ts +++ b/lib/node_modules/@stdlib/blas/base/gasum/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import gasum = require( './index' ); @@ -26,6 +27,7 @@ import gasum = require( './index' ); const x = new Float64Array( 10 ); gasum( x.length, x, 1 ); // $ExpectType number + gasum( x.length, new AccessorArray( x ), 1 ); // $ExpectType number } // The compiler throws an error if the function is provided a first argument which is not a number... @@ -86,6 +88,7 @@ import gasum = require( './index' ); const x = new Float64Array( 10 ); gasum.ndarray( x.length, x, 1, 0 ); // $ExpectType number + gasum.ndarray( x.length, new AccessorArray( x ), 1, 0 ); // $ExpectType number } // 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/gasum/lib/accessors.js b/lib/node_modules/@stdlib/blas/base/gasum/lib/accessors.js new file mode 100644 index 000000000000..50ca60dd977c --- /dev/null +++ b/lib/node_modules/@stdlib/blas/base/gasum/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'; + +// MODULES // + +var abs = require( '@stdlib/math/base/special/abs' ); + + +// VARIABLES // + +var M = 6; + + +// MAIN // + +/** +* Computes the sum of absolute values. +* +* @param {PositiveInteger} N - number of indexed elements +* @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 {number} sum +* +* @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 s = gasum( x.length, arraylike2object( toAccessorArray( x ) ), 1, 0 ); +* // returns 15.0 +*/ +function gasum( N, x, stride, offset ) { + var buf; + var get; + var sum; + var ix; + var m; + var i; + + buf = x.data; + get = x.accessors[ 0 ]; + + sum = 0.0; + ix = offset; + if ( stride === 0 ) { + sum = abs( get( buf, ix ) * N ); + return sum; + } + + // Use unrolled loops 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++ ) { + sum += abs( get( buf, ix ) ); + ix += stride; + } + } + if ( N < M ) { + return sum; + } + for ( i = m; i < N; i += M ) { + sum += abs( get( buf, ix ) ) + abs( get( buf, ix+1 ) ) + abs( get( buf, ix+2 ) ) + abs( get( buf, ix+3 ) ) + abs( get( buf, ix+4 ) ) + abs( get( buf, ix+5 ) ); // eslint-disable-line max-len + ix += M; + } + return sum; + } + for ( i = 0; i < N; i++ ) { + sum += abs( get( buf, ix ) ); + ix += stride; + } + return sum; +} + + +// EXPORTS // + +module.exports = gasum; diff --git a/lib/node_modules/@stdlib/blas/base/gasum/lib/main.js b/lib/node_modules/@stdlib/blas/base/gasum/lib/main.js index cb30ead3355b..bc14f1e1223d 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/lib/main.js +++ b/lib/node_modules/@stdlib/blas/base/gasum/lib/main.js @@ -20,12 +20,8 @@ // MODULES // -var abs = require( '@stdlib/math/base/special/abs' ); - - -// VARIABLES // - -var M = 6; +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -42,40 +38,10 @@ var M = 6; * var x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] ); * * var s = gasum( x.length, x, 1 ); -* // 15.0 +* // returns 15.0 */ function gasum( N, x, stride ) { - var sum; - var m; - var i; - - sum = 0.0; - if ( N <= 0 || stride <= 0 ) { - return sum; - } - // Use unrolled loops 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++ ) { - sum += abs( x[i] ); - } - } - if ( N < M ) { - return sum; - } - for ( i = m; i < N; i += M ) { - sum += abs(x[i]) + abs(x[i+1]) + abs(x[i+2]) + abs(x[i+3]) + abs(x[i+4]) + abs(x[i+5]); // eslint-disable-line max-len - } - return sum; - } - N *= stride; - for ( i = 0; i < N; i += stride ) { - sum += abs( x[i] ); - } - return sum; + return ndarray( N, x, stride, stride2offset( N, stride ) ); } diff --git a/lib/node_modules/@stdlib/blas/base/gasum/lib/ndarray.js b/lib/node_modules/@stdlib/blas/base/gasum/lib/ndarray.js index 9daa416d9beb..adf23264320e 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/gasum/lib/ndarray.js @@ -21,6 +21,8 @@ // MODULES // var abs = require( '@stdlib/math/base/special/abs' ); +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +var accessors = require( './accessors.js' ); // VARIABLES // @@ -43,19 +45,29 @@ var M = 6; * var x = new Float64Array( [ 1.0, -2.0, 3.0, -4.0, 5.0 ] ); * * var s = gasum( x.length, x, 1, 0 ); -* // 15.0 +* // returns 15.0 */ function gasum( N, x, stride, offset ) { var sum; var ix; var m; var i; + var o; sum = 0.0; if ( N <= 0 ) { return sum; } + o = arraylike2object( x ); + if ( o.accessorProtocol ) { + return accessors( N, o, stride, offset ); + } + ix = offset; + if ( stride === 0 ) { + sum = abs( x[ix] * N ); + return sum; + } // Use unrolled loops if the stride is equal to `1`... if ( stride === 1 ) { diff --git a/lib/node_modules/@stdlib/blas/base/gasum/test/test.main.js b/lib/node_modules/@stdlib/blas/base/gasum/test/test.main.js index 1da7d9bf84e8..1e7f2aaee210 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/base/gasum/test/test.main.js @@ -23,19 +23,20 @@ var tape = require( 'tape' ); var randu = require( '@stdlib/random/base/randu' ); var Float64Array = require( '@stdlib/array/float64' ); -var asum = require( './../lib/main.js' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +var gasum = require( './../lib/main.js' ); // TESTS // tape( 'main export is a function', function test( t ) { t.ok( true, __filename ); - t.strictEqual( typeof asum, 'function', 'main export is a function' ); + t.strictEqual( typeof gasum, 'function', 'main export is a function' ); t.end(); }); tape( 'the function has an arity of 3', function test( t ) { - t.strictEqual( asum.length, 3, 'returns expected value' ); + t.strictEqual( gasum.length, 3, 'returns expected value' ); t.end(); }); @@ -44,21 +45,53 @@ tape( 'the function computes the sum of absolute values', function test( t ) { var y; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - y = asum( x.length, x, 1 ); + y = gasum( x.length, x, 1 ); t.strictEqual( y, 15.0, 'returns expected value' ); t.end(); }); -tape( 'the function supports an `x` stride', function test( t ) { +tape( 'the function computes the sum of absolute values (accessors)', function test( t ) { var x; var y; - var N; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - N = 3; + y = gasum( x.length, toAccessorArray( x ), 1 ); - y = asum( N, x, 2 ); + t.strictEqual( y, 15.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing a stride parameter', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 0 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 2 + ]; + + y = gasum( 3, x, 2 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing a stride parameter (accessors)', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 0 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 2 + ]; + y = gasum( 3, toAccessorArray( x ), 2 ); t.strictEqual( y, 9.0, 'returns expected value' ); t.end(); @@ -70,21 +103,67 @@ tape( 'if provided an `N` parameter less than or equal to `0`, the function retu x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - y = asum( 0, x, 1 ); + y = gasum( 0, x, 1 ); t.strictEqual( y, 0.0, 'returns expected value' ); t.end(); }); -tape( 'if provided a `stride` parameter less than or equal to `0`, the function returns `0`', function test( t ) { +tape( 'if provided a stride parameter equal to `0` the function returns the sum of the first element repeated `N` times', function test( t ) { var x; var y; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; + y = gasum( x.length, x, 0 ); - y = asum( x.length, x, -1 ); + t.strictEqual( y, 5.0, 'returns expected value' ); + t.end(); +}); - t.strictEqual( y, 0.0, 'returns expected value' ); +tape( 'if provided a stride parameter equal to `0` the function returns the sum of the first element repeated `N` times (accessors)', function test( t ) { + var x; + var y; + + x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; + y = gasum( x.length, x, 0 ); + + t.strictEqual( y, 5.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing a negative stride', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 2 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 0 + ]; + + y = gasum( 3, x, -2 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing a negative stride (accessors)', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 2 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 0 + ]; + + y = gasum( 3, toAccessorArray( x ), -2 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); t.end(); }); @@ -99,7 +178,7 @@ tape( 'the function supports view offsets', function test( t ) { // Create an offset view... x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // begin at 2nd element - y = asum( 3, x1, 2 ); + y = gasum( 3, x1, 2 ); t.strictEqual( y, 12.0, 'returns expected value' ); t.end(); @@ -122,7 +201,48 @@ tape( 'if the stride equals `1`, the function efficiently sums the absolute valu x[ i ] = sign * (i+1); } - y = asum( x.length, x, 1 ); + y = gasum( x.length, x, 1 ); + + // Compare to closed-form formula: + t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); + + x = new Array( 240 ); + for ( i = 0; i < x.length; i++ ) { + sign = randu(); + if ( sign < 0.5 ) { + sign = -1.0; + } else { + sign = 1.0; + } + x[ i ] = sign * (i+1); + } + + y = gasum( x.length, x, 1 ); + + // Compare to closed-form formula: + t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); + + t.end(); +}); + +tape( 'if the stride equals `1`, the function efficiently sums the absolute values (accessors)', function test( t ) { + var sign; + var x; + var y; + var i; + + x = new Array( 100 ); + for ( i = 0; i < x.length; i++ ) { + sign = randu(); + if ( sign < 0.5 ) { + sign = -1.0; + } else { + sign = 1.0; + } + x[ i ] = sign * (i+1); + } + + y = gasum( x.length, toAccessorArray( x ), 1 ); // Compare to closed-form formula: t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); @@ -138,7 +258,7 @@ tape( 'if the stride equals `1`, the function efficiently sums the absolute valu x[ i ] = sign * (i+1); } - y = asum( x.length, x, 1 ); + y = gasum( x.length, toAccessorArray( x ), 1 ); // Compare to closed-form formula: t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); diff --git a/lib/node_modules/@stdlib/blas/base/gasum/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/gasum/test/test.ndarray.js index b400b965f03a..8a0223524c71 100644 --- a/lib/node_modules/@stdlib/blas/base/gasum/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/gasum/test/test.ndarray.js @@ -22,19 +22,20 @@ var tape = require( 'tape' ); var randu = require( '@stdlib/random/base/randu' ); -var asum = require( './../lib/ndarray.js' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +var gasum = require( './../lib/ndarray.js' ); // TESTS // tape( 'main export is a function', function test( t ) { t.ok( true, __filename ); - t.strictEqual( typeof asum, 'function', 'main export is a function' ); + t.strictEqual( typeof gasum, 'function', 'main export is a function' ); t.end(); }); tape( 'the function has an arity of 4', function test( t ) { - t.strictEqual( asum.length, 4, 'returns expected value' ); + t.strictEqual( gasum.length, 4, 'returns expected value' ); t.end(); }); @@ -44,35 +45,76 @@ tape( 'the function computes the sum of absolute values', function test( t ) { x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - y = asum( x.length, x, 1, 0 ); + y = gasum( x.length, x, 1, 0 ); t.strictEqual( y, 15.0, 'returns expected value' ); t.end(); }); -tape( 'the function supports an `x` stride', function test( t ) { +tape( 'the function computes the sum of absolute values (accessors)', function test( t ) { var x; var y; - var N; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - N = 3; - y = asum( N, x, 2, 0 ); + y = gasum( x.length, toAccessorArray( x ), 1, 0 ); + + t.strictEqual( y, 15.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing a stride parameter', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 0 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 2 + ]; + + y = gasum( 3, x, 2, 0 ); t.strictEqual( y, 9.0, 'returns expected value' ); t.end(); }); -tape( 'the function supports an `x` offset', function test( t ) { +tape( 'the function supports providing a stride parameter (accessors)', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 0 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 2 + ]; + y = gasum( 3, toAccessorArray( x ), 2, 0 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing an offset', function test( t ) { var x; var y; - var N; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - N = 3; + y = gasum( 3, x, 1, 2 ); - y = asum( N, x, 1, 2 ); + t.strictEqual( y, 12.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports providing an offset (accessors)', function test( t ) { + var x; + var y; + + x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; + y = gasum( 3, toAccessorArray( x ), 1, 2 ); t.strictEqual( y, 12.0, 'returns expected value' ); t.end(); @@ -84,26 +126,68 @@ tape( 'if provided an `N` parameter less than or equal to `0`, the function retu x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - y = asum( -1, x, 1, 0 ); + y = gasum( -1, x, 1, 0 ); t.strictEqual( y, 0.0, 'returns expected value' ); - y = asum( 0, x, 1, 0 ); + y = gasum( 0, x, 1, 0 ); t.strictEqual( y, 0.0, 'returns expected value' ); t.end(); }); -tape( 'the function supports negative strides', function test( t ) { +tape( 'if provided a stride parameter equal to `0` the function returns the sum of the first element repeated `N` times', function test( t ) { var x; var y; - var N; x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; - N = 2; + y = gasum( x.length, x, 0, 0 ); + + t.strictEqual( y, 5.0, 'returns expected value' ); + t.end(); +}); + +tape( 'if provided a stride parameter equal to `0` the function returns the sum of the first element repeated `N` times (accessors)', function test( t ) { + var x; + var y; - y = asum( N, x, -2, x.length-2 ); + x = [ 1.0, -2.0, 3.0, -4.0, 5.0 ]; + y = gasum( x.length, toAccessorArray( x ), 0, 0 ); - t.strictEqual( y, 6.0, 'returns expected value' ); + t.strictEqual( y, 5.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports negative strides', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 2 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 0 + ]; + y = gasum( 3, x, -2, x.length-1 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports negative strides (accessors)', function test( t ) { + var x; + var y; + + x = [ + 1.0, // 2 + -2.0, + 3.0, // 1 + -4.0, + 5.0 // 0 + ]; + y = gasum( 3, toAccessorArray( x ), -2, x.length-1 ); + + t.strictEqual( y, 9.0, 'returns expected value' ); t.end(); }); @@ -125,7 +209,50 @@ tape( 'if the stride equals `1`, the function efficiently sums the absolute valu x[ i ] = sign * (i+1); } - y = asum( x.length, x, 1, 0 ); + y = gasum( x.length, x, 1, 0 ); + + // Compare to closed-form formula: + t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); + + x = new Array( 240 ); + for ( i = 0; i < x.length; i++ ) { + sign = randu(); + if ( sign < 0.5 ) { + sign = -1.0; + } else { + sign = 1.0; + } + x[ i ] = sign * (i-5); + } + + N = x.length - 6; + y = gasum( N, x, 1, 6 ); + + // Compare to closed-form formula: + t.strictEqual( y, N*(N+1)/2, 'returns expected value' ); + + t.end(); +}); + +tape( 'if the stride equals `1`, the function efficiently sums the absolute values (accessors)', function test( t ) { + var sign; + var N; + var x; + var y; + var i; + + x = new Array( 100 ); + for ( i = 0; i < x.length; i++ ) { + sign = randu(); + if ( sign < 0.5 ) { + sign = -1.0; + } else { + sign = 1.0; + } + x[ i ] = sign * (i+1); + } + + y = gasum( x.length, toAccessorArray( x ), 1, 0 ); // Compare to closed-form formula: t.strictEqual( y, x.length*(x.length+1)/2, 'returns expected value' ); @@ -142,7 +269,7 @@ tape( 'if the stride equals `1`, the function efficiently sums the absolute valu } N = x.length - 6; - y = asum( N, x, 1, 6 ); + y = gasum( N, toAccessorArray( x ), 1, 6 ); // Compare to closed-form formula: t.strictEqual( y, N*(N+1)/2, 'returns expected value' );