diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/README.md b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/README.md index d440bee86270..5d3b3d0f6ec1 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/README.md @@ -129,6 +129,7 @@ gcusumpw.ndarray( 4, 0.0, x, 2, 1, y, -1, y.length-1 ); - If `N <= 0`, both functions return `y` unchanged. - In general, pairwise summation is more numerically stable than ordinary recursive summation (i.e., "simple" summation), with slightly worse performance. While not the most numerically stable summation technique (e.g., compensated summation techniques such as the Kahan–Babuška-Neumaier algorithm are generally more numerically stable), pairwise summation strikes a reasonable balance between numerical stability and performance. If either numerical stability or performance is more desirable for your use case, consider alternative summation techniques. +- 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]) - Depending on the environment, the typed versions ([`dcusumpw`][@stdlib/blas/ext/base/dcusumpw], [`scusumpw`][@stdlib/blas/ext/base/scusumpw], etc.) are likely to be significantly more performant. @@ -197,6 +198,8 @@ console.log( y ); [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 + [@higham:1993a]: https://doi.org/10.1137/0914050 diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/index.d.ts b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/index.d.ts index b020bdf932f1..bb75facb92ca 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/index.d.ts @@ -20,7 +20,17 @@ /// -import { NumericArray } from '@stdlib/types/array'; +import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array'; + +/** +* Input array. +*/ +type InputArray = NumericArray | Collection | AccessorArrayLike; + +/** +* Output array. +*/ +type OutputArray = NumericArray | Collection | AccessorArrayLike; /** * Interface describing `gcusumpw`. @@ -44,7 +54,7 @@ interface Routine { * gcusumpw( x.length, 0.0, x, 1, y, 1 ); * // y => [ 1.0, -1.0, 1.0 ] */ - ( N: number, sum: number, x: NumericArray, strideX: number, y: NumericArray, strideY: number ): NumericArray; + ( N: number, sum: number, x: InputArray, strideX: number, y: T, strideY: number ): T; /** * Computes the cumulative sum of strided array elements using pairwise summation and alternative indexing semantics. @@ -66,7 +76,7 @@ interface Routine { * gcusumpw.ndarray( x.length, 0.0, x, 1, 0, y, 1, 0 ); * // y => [ 1.0, -1.0, 1.0 ] */ - ndarray( N: number, sum: number, x: NumericArray, strideX: number, offsetX: number, y: NumericArray, strideY: number, offsetY: number ): NumericArray; + ndarray( N: number, sum: number, x: InputArray, strideX: number, offsetX: number, y: T, strideY: number, offsetY: number ): T; } /** diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/test.ts b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/test.ts index fc7347f15937..0bd6cddb1d6a 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/test.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import gcusumpw = require( './index' ); @@ -26,7 +27,8 @@ import gcusumpw = require( './index' ); const x = new Float64Array( 10 ); const y = new Float64Array( 10 ); - gcusumpw( x.length, 0.0, x, 1, y, 1 ); // $ExpectType NumericArray + gcusumpw( x.length, 0.0, x, 1, y, 1 ); // $ExpectType Float64Array + gcusumpw( x.length, 0.0, new AccessorArray( x ), 1, new AccessorArray( y ), 1 ); // $ExpectType AccessorArray } // The compiler throws an error if the function is provided a first argument which is not a number... @@ -139,7 +141,8 @@ import gcusumpw = require( './index' ); const x = new Float64Array( 10 ); const y = new Float64Array( 10 ); - gcusumpw.ndarray( x.length, 0.0, x, 1, 0, y, 1, 0 ); // $ExpectType NumericArray + gcusumpw.ndarray( x.length, 0.0, x, 1, 0, y, 1, 0 ); // $ExpectType Float64Array + gcusumpw.ndarray( x.length, 0.0, new AccessorArray( x ), 1, 0, new AccessorArray( y ), 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/ext/base/gcusumpw/lib/accessors.js b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/accessors.js new file mode 100644 index 000000000000..6db272d06c1e --- /dev/null +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/accessors.js @@ -0,0 +1,113 @@ +/** +* @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 floor = require( '@stdlib/math/base/special/floor' ); + + +// VARIABLES // + +// Blocksize for pairwise summation: +var BLOCKSIZE = 128; + + +// MAIN // + +/** +* Computes the cumulative sum of strided array elements using pairwise summation. +* +* ## Method +* +* - This implementation uses pairwise summation, which accrues rounding error `O(log2 N)` instead of `O(N)`. The recursion depth is also `O(log2 N)`. +* +* ## References +* +* - Higham, Nicholas J. 1993. "The Accuracy of Floating Point Summation." _SIAM Journal on Scientific Computing_ 14 (4): 783–99. doi:[10.1137/0914050](https://doi.org/10.1137/0914050). +* +* @private +* @param {PositiveInteger} N - number of indexed elements +* @param {number} sum - initial sum +* @param {Object} x - input array object +* @param {Collection} x.data - input array data +* @param {Array} x.accessors - array element accessors +* @param {integer} strideX - stride length for `x` +* @param {NonNegativeInteger} offsetX - starting index for `x` +* @param {Object} y - output array object +* @param {Collection} y.data - output array data +* @param {Array} y.accessors - array element accessors +* @param {integer} strideY - stride length for `y` +* @param {NonNegativeInteger} offsetY - starting index for `y` +* @returns {Object} output array object +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +* +* var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ]; +* var y = [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ]; +* +* gcusumpw( 4, 0.0, arraylike2object( toAccessorArray( x ) ), 2, 1, arraylike2object( toAccessorArray( y ) ), 1, 0 ); +* // y => [ 1.0, -1.0, 1.0, 5.0, 0.0, 0.0, 0.0, 0.0 ] +*/ +function gcusumpw( N, sum, x, strideX, offsetX, y, strideY, offsetY ) { + var xbuf; + var ybuf; + var xget; + var yget; + var yset; + var ix; + var iy; + var s; + var n; + var i; + + // Cache reference to array data: + xbuf = x.data; + ybuf = y.data; + + // Cache reference to the element accessors: + xget = x.accessors[ 0 ]; + yget = y.accessors[ 0 ]; + yset = y.accessors[ 1 ]; + + ix = offsetX; + iy = offsetY; + if ( N <= BLOCKSIZE ) { + s = 0.0; + for ( i = 0; i < N; i++ ) { + s += xget( xbuf, ix ); + yset( ybuf, iy, sum + s); + ix += strideX; + iy += strideY; + } + return y; + } + n = floor( N/2 ); + gcusumpw( n, sum, x, strideX, ix, y, strideY, iy ); + iy += (n-1) * strideY; + gcusumpw( N-n, yget( ybuf, iy ), x, strideX, ix+(n*strideX), y, strideY, iy+strideY ); // eslint-disable-line max-len + return y; +} + + +// EXPORTS // + +module.exports = gcusumpw; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/ndarray.js index a8ddbf1fc7b4..186af6732f46 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/lib/ndarray.js @@ -20,7 +20,9 @@ // MODULES // +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); var floor = require( '@stdlib/math/base/special/floor' ); +var accessors = require( './accessors.js' ); // VARIABLES // @@ -62,6 +64,8 @@ var BLOCKSIZE = 128; function gcusumpw( N, sum, x, strideX, offsetX, y, strideY, offsetY ) { var ix; var iy; + var ox; + var oy; var s; var n; var i; @@ -69,6 +73,12 @@ function gcusumpw( N, sum, x, strideX, offsetX, y, strideY, offsetY ) { if ( N <= 0 ) { return y; } + ox = arraylike2object( x ); + oy = arraylike2object( y ); + if ( ox.accessorProtocol || oy.accessorProtocol ) { + accessors( N, sum, ox, strideX, offsetX, oy, strideY, offsetY ); + return y; + } ix = offsetX; iy = offsetY; if ( N <= BLOCKSIZE ) { diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.main.js b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.main.js index 9dded209f761..a10e0bddaead 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.main.js @@ -21,8 +21,8 @@ // MODULES // var tape = require( 'tape' ); -var floor = require( '@stdlib/math/base/special/floor' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var Float64Array = require( '@stdlib/array/float64' ); var gcusumpw = require( './../lib' ); @@ -128,6 +128,94 @@ tape( 'the function computes the cumulative sum', function test( t ) { t.end(); }); +tape( 'the function computes the cumulative sum (accessors)', function test( t ) { + var expected; + var x; + var y; + var i; + + x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + y = [ 0.0, 0.0, 0.0, 0.0, 0.0 ]; + + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + expected = [ + 1.0, + 3.0, + 6.0, + 10.0, + 15.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + y = [ 0.0, 0.0, 0.0, 0.0, 0.0 ]; + + gcusumpw( x.length, 10.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + expected = [ + 11.0, + 13.0, + 16.0, + 20.0, + 25.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ NaN, NaN ]; + y = [ 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + + for ( i = 0; i < y.length; i++ ) { + t.strictEqual( isnan( y[ i ] ), true, 'returns expected value. i: ' + i ); + } + + x = [ 1.0, NaN, 3.0, NaN ]; + y = [ 0.0, 0.0, 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + + expected = [ + 1.0, + NaN, + NaN, + NaN + ]; + for ( i = 0; i < y.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( y[ i ] ), true, 'returns expected value. i: ' + i ); + } else { + t.strictEqual( y[ i ], expected[ i ], true, 'returns expected value. i: ' + i ); + } + } + + x = [ 1.0, 1.0e100, 1.0, -1.0e100 ]; + y = [ 0.0, 0.0, 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + + expected = [ + 1.0, + 1.0e100, + 1.0e100, + 0.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = []; + y = []; + expected = []; + for ( i = 0; i < 1e3; i++ ) { + x.push( i+1 ); + y.push( 0.0 ); + if ( i === 0 ) { + expected.push( x[ i ] ); + } else { + expected.push( expected[ i-1 ] + x[ i ] ); + } + } + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 1 ); + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + tape( 'the function returns a reference to the output array', function test( t ) { var out; var x; @@ -142,6 +230,20 @@ tape( 'the function returns a reference to the output array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the output array (accessors)', function test( t ) { + var out; + var x; + var y; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + y = toAccessorArray( [ 0.0, 0.0, 0.0, 0.0, 0.0 ] ); + + out = gcusumpw( x.length, 0.0, x, 1, y, 1 ); + + t.strictEqual( out, y, 'same reference' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `y` unchanged', function test( t ) { var expected; var x; @@ -165,7 +267,6 @@ tape( 'the function supports an `x` stride', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -181,9 +282,36 @@ tape( 'the function supports an `x` stride', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, 2, y, 1 ); + gcusumpw( 3, 0.0, x, 2, y, 1 ); + + expected = [ 1.0, 4.0, 9.0, 0.0, 0.0 ]; + + t.deepEqual( y, expected, 'deep equal' ); + t.end(); +}); + +tape( 'the function supports an `x` stride (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 0 + 2.0, + 3.0, // 1 + 4.0, + 5.0 // 2 + ]; + y = [ + 0.0, // 0 + 0.0, // 1 + 0.0, // 2 + 0.0, + 0.0 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), 2, toAccessorArray( y ), 1 ); expected = [ 1.0, 4.0, 9.0, 0.0, 0.0 ]; @@ -195,7 +323,6 @@ tape( 'the function supports a `y` stride', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -211,9 +338,36 @@ tape( 'the function supports a `y` stride', function test( t ) { 0.0, 0.0 // 2 ]; - N = 3; - gcusumpw( N, 0.0, x, 1, y, 2 ); + gcusumpw( 3, 0.0, x, 1, y, 2 ); + + expected = [ 1.0, 0.0, 3.0, 0.0, 6.0 ]; + + t.deepEqual( y, expected, 'deep equal' ); + t.end(); +}); + +tape( 'the function supports a `y` stride (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 0 + 2.0, // 1 + 3.0, // 2 + 4.0, + 5.0 + ]; + y = [ + 0.0, // 0 + 0.0, + 0.0, // 1 + 0.0, + 0.0 // 2 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), 1, toAccessorArray( y ), 2 ); expected = [ 1.0, 0.0, 3.0, 0.0, 6.0 ]; @@ -225,7 +379,6 @@ tape( 'the function supports negative strides', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 2 @@ -241,9 +394,36 @@ tape( 'the function supports negative strides', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, -2, y, -1 ); + gcusumpw( 3, 0.0, x, -2, y, -1 ); + + expected = [ 9.0, 8.0, 5.0, 0.0, 0.0 ]; + + t.deepEqual( y, expected, 'deep equal' ); + t.end(); +}); + +tape( 'the function supports negative strides (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 2 + 2.0, + 3.0, // 1 + 4.0, + 5.0 // 0 + ]; + y = [ + 0.0, // 2 + 0.0, // 1 + 0.0, // 0 + 0.0, + 0.0 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), -2, toAccessorArray( y ), -1 ); expected = [ 9.0, 8.0, 5.0, 0.0, 0.0 ]; @@ -255,7 +435,6 @@ tape( 'the function supports complex access patterns', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -273,9 +452,8 @@ tape( 'the function supports complex access patterns', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, 2, y, -1 ); + gcusumpw( 3, 0.0, x, 2, y, -1 ); expected = [ 9.0, 4.0, 1.0, 0.0, 0.0, 0.0 ]; @@ -289,7 +467,6 @@ tape( 'the function supports view offsets', function test( t ) { var y0; var x1; var y1; - var N; // Initial arrays... x0 = new Float64Array([ @@ -313,9 +490,7 @@ tape( 'the function supports view offsets', function test( t ) { x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // begin at 2nd element y1 = new Float64Array( y0.buffer, y0.BYTES_PER_ELEMENT*3 ); // begin at the 4th element - N = floor( x0.length / 2 ); - - gcusumpw( N, 0.0, x1, -2, y1, 1 ); + gcusumpw( 3, 0.0, x1, -2, y1, 1 ); expected = new Float64Array( [ 0.0, 0.0, 0.0, 6.0, 10.0, 12.0 ] ); t.deepEqual( y0, expected, 'deep equal' ); diff --git a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.ndarray.js index f9cc204d07bb..b4536873cda7 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gcusumpw/test/test.ndarray.js @@ -21,8 +21,8 @@ // MODULES // var tape = require( 'tape' ); -var floor = require( '@stdlib/math/base/special/floor' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var gcusumpw = require( './../lib/ndarray.js' ); @@ -126,6 +126,93 @@ tape( 'the function calculates the cumulative sum', function test( t ) { t.end(); }); +tape( 'the function calculates the cumulative sum (accessors)', function test( t ) { + var expected; + var x; + var y; + var i; + + x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + y = [ 0.0, 0.0, 0.0, 0.0, 0.0 ]; + + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + expected = [ + 1.0, + 3.0, + 6.0, + 10.0, + 15.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1.0, 2.0, 3.0, 4.0, 5.0 ]; + y = [ 0.0, 0.0, 0.0, 0.0, 0.0 ]; + + gcusumpw( x.length, 10.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + expected = [ + 11.0, + 13.0, + 16.0, + 20.0, + 25.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ NaN, NaN ]; + y = [ 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + + for ( i = 0; i < y.length; i++ ) { + t.strictEqual( isnan( y[ i ] ), true, 'returns expected value. i: ' + i ); + } + + x = [ 1.0, NaN, 3.0, NaN ]; + y = [ 0.0, 0.0, 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + + expected = [ + 1.0, + NaN, + NaN, + NaN + ]; + for ( i = 0; i < y.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( y[ i ] ), true, 'returns expected value. i: ' + i ); + } else { + t.strictEqual( y[ i ], expected[ i ], true, 'returns expected value. i: ' + i ); + } + } + + x = [ 1.0, 1.0e100, 1.0, -1.0e100 ]; + y = [ 0.0, 0.0, 0.0, 0.0 ]; + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + + expected = [ + 1.0, + 1.0e100, + 1.0e100, + 0.0 + ]; + t.deepEqual( y, expected, 'returns expected value' ); + + x = []; + y = []; + expected = []; + for ( i = 0; i < 1e3; i++ ) { + x.push( i+1 ); + if ( i === 0 ) { + expected.push( x[ i ] ); + } else { + expected.push( expected[ i-1 ] + x[ i ] ); + } + } + gcusumpw( x.length, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 1, 0 ); + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + tape( 'the function returns a reference to the output array', function test( t ) { var out; var x; @@ -140,6 +227,20 @@ tape( 'the function returns a reference to the output array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the output array (accessors)', function test( t ) { + var out; + var x; + var y; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + y = toAccessorArray( [ 0.0, 0.0, 0.0, 0.0, 0.0 ] ); + + out = gcusumpw( x.length, 0.0, x, 1, 0, y, 1, 0 ); + + t.strictEqual( out, y, 'same reference' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `y` unchanged', function test( t ) { var expected; var x; @@ -163,7 +264,6 @@ tape( 'the function supports an `x` stride', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -179,9 +279,36 @@ tape( 'the function supports an `x` stride', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, 2, 0, y, 1, 0 ); + gcusumpw( 3, 0.0, x, 2, 0, y, 1, 0 ); + + expected = [ 1.0, 4.0, 9.0, 0.0, 0.0 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports an `x` stride (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 0 + 2.0, + 3.0, // 1 + 4.0, + 5.0 // 2 + ]; + y = [ + 0.0, // 0 + 0.0, // 1 + 0.0, // 2 + 0.0, + 0.0 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), 2, 0, toAccessorArray( y ), 1, 0 ); expected = [ 1.0, 4.0, 9.0, 0.0, 0.0 ]; @@ -193,7 +320,6 @@ tape( 'the function supports a `y` stride', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -209,9 +335,36 @@ tape( 'the function supports a `y` stride', function test( t ) { 0.0, 0.0 // 2 ]; - N = 3; - gcusumpw( N, 0.0, x, 1, 0, y, 2, 0 ); + gcusumpw( 3, 0.0, x, 1, 0, y, 2, 0 ); + + expected = [ 1.0, 0.0, 3.0, 0.0, 6.0 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a `y` stride (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 0 + 2.0, // 1 + 3.0, // 2 + 4.0, + 5.0 + ]; + y = [ + 0.0, // 0 + 0.0, + 0.0, // 1 + 0.0, + 0.0 // 2 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 2, 0 ); expected = [ 1.0, 0.0, 3.0, 0.0, 6.0 ]; @@ -223,7 +376,6 @@ tape( 'the function supports negative strides', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 2 @@ -239,9 +391,36 @@ tape( 'the function supports negative strides', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, -2, x.length-1, y, -1, 2 ); + gcusumpw( 3, 0.0, x, -2, x.length-1, y, -1, 2 ); + + expected = [ 9.0, 8.0, 5.0, 0.0, 0.0 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports negative strides (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 1.0, // 2 + 2.0, + 3.0, // 1 + 4.0, + 5.0 // 0 + ]; + y = [ + 0.0, // 2 + 0.0, // 1 + 0.0, // 0 + 0.0, + 0.0 + ]; + + gcusumpw( 3, 0.0, toAccessorArray( x ), -2, x.length-1, toAccessorArray( y ), -1, 2 ); expected = [ 9.0, 8.0, 5.0, 0.0, 0.0 ]; @@ -251,7 +430,6 @@ tape( 'the function supports negative strides', function test( t ) { tape( 'the function supports an `x` offset', function test( t ) { var expected; - var N; var x; var y; @@ -275,9 +453,42 @@ tape( 'the function supports an `x` offset', function test( t ) { 0.0, 0.0 ]; - N = floor( x.length / 2 ); - gcusumpw( N, 0.0, x, 2, 1, y, 1, 0 ); + gcusumpw( 4, 0.0, x, 2, 1, y, 1, 0 ); + + expected = [ 1.0, -1.0, 1.0, 5.0, 0.0, 0.0, 0.0, 0.0 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports an `x` offset (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 2.0, + 1.0, // 0 + 2.0, + -2.0, // 1 + -2.0, + 2.0, // 2 + 3.0, + 4.0 // 3 + ]; + y = [ + 0.0, // 0 + 0.0, // 1 + 0.0, // 2 + 0.0, // 3 + 0.0, + 0.0, + 0.0, + 0.0 + ]; + + gcusumpw( 4, 0.0, toAccessorArray( x ), 2, 1, toAccessorArray( y ), 1, 0 ); expected = [ 1.0, -1.0, 1.0, 5.0, 0.0, 0.0, 0.0, 0.0 ]; @@ -287,7 +498,6 @@ tape( 'the function supports an `x` offset', function test( t ) { tape( 'the function supports a `y` offset', function test( t ) { var expected; - var N; var x; var y; @@ -311,9 +521,42 @@ tape( 'the function supports a `y` offset', function test( t ) { 0.0, 0.0 // 3 ]; - N = floor( x.length / 2 ); - gcusumpw( N, 0.0, x, 1, 0, y, 2, 1 ); + gcusumpw( 4, 0.0, x, 1, 0, y, 2, 1 ); + + expected = [ 0.0, 2.0, 0.0, 3.0, 0.0, 5.0, 0.0, 3.0 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a `y` offset (accessors)', function test( t ) { + var expected; + var x; + var y; + + x = [ + 2.0, // 0 + 1.0, // 1 + 2.0, // 2 + -2.0, // 3 + -2.0, + 2.0, + 3.0, + 4.0 + ]; + y = [ + 0.0, + 0.0, // 0 + 0.0, + 0.0, // 1 + 0.0, + 0.0, // 2 + 0.0, + 0.0 // 3 + ]; + + gcusumpw( 4, 0.0, toAccessorArray( x ), 1, 0, toAccessorArray( y ), 2, 1 ); expected = [ 0.0, 2.0, 0.0, 3.0, 0.0, 5.0, 0.0, 3.0 ]; @@ -325,7 +568,6 @@ tape( 'the function supports complex access patterns', function test( t ) { var expected; var x; var y; - var N; x = [ 1.0, // 0 @@ -343,9 +585,8 @@ tape( 'the function supports complex access patterns', function test( t ) { 0.0, 0.0 ]; - N = 3; - gcusumpw( N, 0.0, x, 2, 0, y, -1, 2 ); + gcusumpw( 3, 0.0, x, 2, 0, y, -1, 2 ); expected = [ 9.0, 4.0, 1.0, 0.0, 0.0, 0.0 ];