Skip to content

Commit 9ce3d01

Browse files
headlessNodekgryte
andauthored
feat: add accessor arrays support to blas/ext/base/gnansumors
PR-URL: #5036 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]>
1 parent 6f8898d commit 9ce3d01

File tree

7 files changed

+341
-3
lines changed

7 files changed

+341
-3
lines changed

lib/node_modules/@stdlib/blas/ext/base/gnansumors/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ var v = gnansumors.ndarray( 5, x, 2, 1 );
109109
## Notes
110110

111111
- If `N <= 0`, both functions return `0.0`.
112+
- 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])
112113
- Ordinary recursive summation (i.e., a "simple" sum) is performant, but can incur significant numerical error. If performance is paramount and error tolerated, using ordinary recursive summation is acceptable; in all other cases, exercise due caution.
113114
- Depending on the environment, the typed versions ([`dnansumors`][@stdlib/blas/ext/base/dnansumors], [`snansumors`][@stdlib/blas/ext/base/snansumors], etc.) are likely to be significantly more performant.
114115

@@ -173,6 +174,8 @@ console.log( v );
173174

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

177+
[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor
178+
176179
<!-- <related-links> -->
177180

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

lib/node_modules/@stdlib/blas/ext/base/gnansumors/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 `gnansumors`.
@@ -40,7 +45,7 @@ interface Routine {
4045
* var v = gnansumors( x.length, x, 1 );
4146
* // returns 1.0
4247
*/
43-
( N: number, x: NumericArray, strideX: number ): number;
48+
( N: number, x: InputArray, strideX: number ): number;
4449

4550
/**
4651
* Computes the sum of strided array elements, ignoring `NaN` values and using ordinary recursive summation and alternative indexing semantics.
@@ -57,7 +62,7 @@ interface Routine {
5762
* var v = gnansumors.ndarray( x.length, x, 1, 0 );
5863
* // returns 1.0
5964
*/
60-
ndarray( N: number, x: NumericArray, strideX: number, offsetX: number ): number;
65+
ndarray( N: number, x: InputArray, strideX: number, offsetX: number ): number;
6166
}
6267

6368
/**

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
* limitations under the License.
1717
*/
1818

19+
import AccessorArray = require( '@stdlib/array/base/accessor' );
1920
import gnansumors = require( './index' );
2021

2122

@@ -26,6 +27,7 @@ import gnansumors = require( './index' );
2627
const x = new Float64Array( 10 );
2728

2829
gnansumors( x.length, x, 1 ); // $ExpectType number
30+
gnansumors( x.length, new AccessorArray( x ), 1 ); // $ExpectType number
2931
}
3032

3133
// The compiler throws an error if the function is provided a first argument which is not a number...
@@ -85,6 +87,7 @@ import gnansumors = require( './index' );
8587
const x = new Float64Array( 10 );
8688

8789
gnansumors.ndarray( x.length, x, 1, 0 ); // $ExpectType number
90+
gnansumors.ndarray( x.length, new AccessorArray( x ), 1, 0 ); // $ExpectType number
8891
}
8992

9093
// The compiler throws an error if the `ndarray` method is provided a first argument which is not a number...
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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+
// MODULES //
22+
23+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
24+
25+
26+
// MAIN //
27+
28+
/**
29+
* Computes the sum of strided array elements, ignoring `NaN` values and using ordinary recursive summation.
30+
*
31+
* @private
32+
* @param {PositiveInteger} N - number of indexed elements
33+
* @param {Object} x - input array object
34+
* @param {Collection} x.data - input array data
35+
* @param {Array<Function>} x.accessors - array element accessors
36+
* @param {integer} strideX - stride length for `x`
37+
* @param {NonNegativeInteger} offsetX - starting index for `x`
38+
* @returns {number} sum
39+
*
40+
* @example
41+
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
42+
* var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
43+
*
44+
* var x = toAccessorArray( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] );
45+
*
46+
* var v = gnansumors( 4, arraylike2object( x ), 2, 1 );
47+
* // returns 5.0
48+
*/
49+
function gnansumors( N, x, strideX, offsetX ) {
50+
var xbuf;
51+
var xget;
52+
var sum;
53+
var ix;
54+
var v;
55+
var i;
56+
57+
// Cache reference to array data:
58+
xbuf = x.data;
59+
60+
// Cache reference to the element accessors:
61+
xget = x.accessors[ 0 ];
62+
63+
ix = offsetX;
64+
if ( strideX === 0 ) {
65+
v = xget( xbuf, ix );
66+
if ( isnan( v ) ) {
67+
return 0.0;
68+
}
69+
return N * v;
70+
}
71+
sum = 0.0;
72+
for ( i = 0; i < N; i++ ) {
73+
v = xget( xbuf, ix );
74+
if ( isnan( v ) === false ) {
75+
sum += v;
76+
}
77+
ix += strideX;
78+
}
79+
return sum;
80+
}
81+
82+
83+
// EXPORTS //
84+
85+
module.exports = gnansumors;

lib/node_modules/@stdlib/blas/ext/base/gnansumors/lib/ndarray.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020

2121
// MODULES //
2222

23+
var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
2324
var isnan = require( '@stdlib/math/base/assert/is-nan' );
25+
var accessors = require( './accessors.js' );
2426

2527

2628
// MAIN //
@@ -43,11 +45,16 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' );
4345
function gnansumors( N, x, strideX, offsetX ) {
4446
var sum;
4547
var ix;
48+
var o;
4649
var i;
4750

4851
if ( N <= 0 ) {
4952
return 0.0;
5053
}
54+
o = arraylike2object( x );
55+
if ( o.accessorProtocol ) {
56+
return accessors( N, o, strideX, offsetX );
57+
}
5158
ix = offsetX;
5259
if ( strideX === 0 ) {
5360
if ( isnan( x[ ix ] ) ) {

lib/node_modules/@stdlib/blas/ext/base/gnansumors/test/test.main.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
var tape = require( 'tape' );
2424
var Float64Array = require( '@stdlib/array/float64' );
25+
var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
2526
var gnansumors = require( './../lib' );
2627

2728

@@ -73,6 +74,41 @@ tape( 'the function calculates the sum of strided array elements (ignoring NaN v
7374
t.end();
7475
});
7576

77+
tape( 'the function calculates the sum of strided array elements (ignoring NaN values, accessors)', function test( t ) {
78+
var x;
79+
var v;
80+
81+
x = [ 1.0, -2.0, -4.0, 5.0, 0.0, NaN, 3.0, 0.0, -3.0, 3.0 ];
82+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
83+
t.strictEqual( v, 3.0, 'returns expected value' );
84+
85+
x = [ 1.0, -2.0, -4.0, NaN, 5.0, 0.0, 3.0 ];
86+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
87+
t.strictEqual( v, 3.0, 'returns expected value' );
88+
89+
x = [ -4.0, NaN, -4.0 ];
90+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
91+
t.strictEqual( v, -8.0, 'returns expected value' );
92+
93+
x = [ NaN, 4.0 ];
94+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
95+
t.strictEqual( v, 4.0, 'returns expected value' );
96+
97+
x = [ NaN, NaN ];
98+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
99+
t.strictEqual( v, 0.0, 'returns expected value' );
100+
101+
x = [ NaN ];
102+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
103+
t.strictEqual( v, 0.0, 'returns expected value' );
104+
105+
x = [ 1.0, 1.0e100, 1.0, -1.e100 ];
106+
v = gnansumors( x.length, toAccessorArray( x ), 1 );
107+
t.strictEqual( v, 0.0, 'returns expected value' );
108+
109+
t.end();
110+
});
111+
76112
tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `0.0`', function test( t ) {
77113
var x;
78114
var v;
@@ -123,6 +159,29 @@ tape( 'the function supports a `stride` parameter', function test( t ) {
123159
t.end();
124160
});
125161

162+
tape( 'the function supports a `stride` parameter (accessors)', function test( t ) {
163+
var x;
164+
var v;
165+
166+
x = [
167+
1.0, // 0
168+
2.0,
169+
2.0, // 1
170+
-7.0,
171+
-2.0, // 2
172+
3.0,
173+
4.0, // 3
174+
2.0,
175+
NaN, // 4
176+
NaN
177+
];
178+
179+
v = gnansumors( 5, toAccessorArray( x ), 2 );
180+
181+
t.strictEqual( v, 5.0, 'returns expected value' );
182+
t.end();
183+
});
184+
126185
tape( 'the function supports a negative `stride` parameter', function test( t ) {
127186
var x;
128187
var v;
@@ -146,6 +205,29 @@ tape( 'the function supports a negative `stride` parameter', function test( t )
146205
t.end();
147206
});
148207

208+
tape( 'the function supports a negative `stride` parameter (accessors)', function test( t ) {
209+
var x;
210+
var v;
211+
212+
x = [
213+
NaN, // 4
214+
NaN,
215+
1.0, // 3
216+
2.0,
217+
2.0, // 2
218+
-7.0,
219+
-2.0, // 1
220+
3.0,
221+
4.0, // 0
222+
2.0
223+
];
224+
225+
v = gnansumors( 5, toAccessorArray( x ), -2 );
226+
227+
t.strictEqual( v, 5.0, 'returns expected value' );
228+
t.end();
229+
});
230+
149231
tape( 'if provided a `stride` parameter equal to `0`, the function returns the sum of the first element repeated N times', function test( t ) {
150232
var x;
151233
var v;
@@ -158,6 +240,18 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns the s
158240
t.end();
159241
});
160242

243+
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 ) {
244+
var x;
245+
var v;
246+
247+
x = [ 1.0, -2.0, -4.0, 5.0, 3.0 ];
248+
249+
v = gnansumors( x.length, toAccessorArray( x ), 0 );
250+
t.strictEqual( v, 5.0, 'returns expected value' );
251+
252+
t.end();
253+
});
254+
161255
tape( 'if provided a `stride` parameter equal to `0` and the first element is NaN, the function returns 0', function test( t ) {
162256
var x;
163257
var v;
@@ -170,6 +264,18 @@ tape( 'if provided a `stride` parameter equal to `0` and the first element is Na
170264
t.end();
171265
});
172266

267+
tape( 'if provided a `stride` parameter equal to `0` and the first element is NaN, the function returns 0 (accessors)', function test( t ) {
268+
var x;
269+
var v;
270+
271+
x = [ NaN, -2.0, -4.0, 5.0, 3.0 ];
272+
273+
v = gnansumors( x.length, toAccessorArray( x ), 0 );
274+
t.strictEqual( v, 0.0, 'returns expected value' );
275+
276+
t.end();
277+
});
278+
173279
tape( 'the function supports view offsets', function test( t ) {
174280
var x0;
175281
var x1;

0 commit comments

Comments
 (0)