Skip to content

Commit 48e793e

Browse files
headlessNodekgryte
authored andcommitted
feat: add accessor arrays support to blas/ext/base/gnannsumkbn
PR-URL: stdlib-js#5023 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]>
1 parent 061c115 commit 48e793e

File tree

7 files changed

+574
-5
lines changed

7 files changed

+574
-5
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ var v = gnannsumkbn.ndarray( 4, x, 2, 1, out, 2, 1 );
119119
## Notes
120120

121121
- If `N <= 0`, both functions return a sum equal to `0.0`.
122+
- 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])
122123

123124
</section>
124125

@@ -190,6 +191,8 @@ console.log( out );
190191

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

194+
[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor
195+
193196
[@neumaier:1974a]: https://doi.org/10.1002/zamm.19740540106
194197

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

lib/node_modules/@stdlib/blas/ext/base/gnannsumkbn/docs/types/index.d.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,17 @@
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>;
29+
30+
/**
31+
* Output array.
32+
*/
33+
type OutputArray = NumericArray | Collection<number> | AccessorArrayLike<number>;
2434

2535
/**
2636
* Interface describing `gnannsumkbn`.
@@ -43,7 +53,7 @@ interface Routine {
4353
* var v = gnannsumkbn( x.length, x, 1, out, 1 );
4454
* // returns [ 1.0, 3 ]
4555
*/
46-
( N: number, x: NumericArray, strideX: number, out: NumericArray, strideOut: number ): NumericArray;
56+
<T extends OutputArray>( N: number, x: InputArray, strideX: number, out: T, strideOut: number ): T;
4757

4858
/**
4959
* Computes the sum of strided array elements, ignoring `NaN` values and using an improved Kahan–Babuška algorithm and alternative indexing semantics.
@@ -64,7 +74,7 @@ interface Routine {
6474
* var v = gnannsumkbn( x.length, x, 1, 0, out, 1, 0 );
6575
* // returns [ 1.0, 3 ]
6676
*/
67-
ndarray( N: number, x: NumericArray, strideX: number, offsetX: number, out: NumericArray, strideOut: number, offsetOut: number ): NumericArray;
77+
ndarray<T extends OutputArray>( N: number, x: InputArray, strideX: number, offsetX: number, out: T, strideOut: number, offsetOut: number ): T;
6878
}
6979

7080
/**

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

Lines changed: 5 additions & 2 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 gnannsumkbn = require( './index' );
2021

2122

@@ -26,7 +27,8 @@ import gnannsumkbn = require( './index' );
2627
const x = new Float64Array( 10 );
2728
const out = new Float64Array( 2 );
2829

29-
gnannsumkbn( x.length, x, 1, out, 1 ); // $ExpectType NumericArray
30+
gnannsumkbn( x.length, x, 1, out, 1 ); // $ExpectType Float64Array
31+
gnannsumkbn( x.length, new AccessorArray( x ), 1, new AccessorArray( out ), 1 ); // $ExpectType AccessorArray<number>
3032
}
3133

3234
// The compiler throws an error if the function is provided a first argument which is not a number...
@@ -123,7 +125,8 @@ import gnannsumkbn = require( './index' );
123125
const x = new Float64Array( 10 );
124126
const out = new Float64Array( 2 );
125127

126-
gnannsumkbn.ndarray( x.length, x, 1, 0, out, 1, 0 ); // $ExpectType NumericArray
128+
gnannsumkbn.ndarray( x.length, x, 1, 0, out, 1, 0 ); // $ExpectType Float64Array
129+
gnannsumkbn.ndarray( x.length, new AccessorArray( x ), 1, 0, new AccessorArray( out ), 1, 0 ); // $ExpectType AccessorArray<number>
127130
}
128131

129132
// The compiler throws an error if the `ndarray` method is provided a first argument which is not a number...
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
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+
var abs = require( '@stdlib/math/base/special/abs' );
25+
26+
27+
// MAIN //
28+
29+
/**
30+
* Computes the sum of strided array elements, ignoring `NaN` values and using an improved Kahan–Babuška algorithm.
31+
*
32+
* ## Method
33+
*
34+
* - This implementation uses an "improved Kahan–Babuška algorithm", as described by Neumaier (1974).
35+
*
36+
* ## References
37+
*
38+
* - Neumaier, Arnold. 1974. "Rounding Error Analysis of Some Methods for Summing Finite Sums." _Zeitschrift Für Angewandte Mathematik Und Mechanik_ 54 (1): 39–51. doi:[10.1002/zamm.19740540106](https://doi.org/10.1002/zamm.19740540106).
39+
*
40+
* @private
41+
* @param {PositiveInteger} N - number of indexed elements
42+
* @param {Object} x - input array object
43+
* @param {Collection} x.data - input array data
44+
* @param {Array<Function>} x.accessors - array element accessors
45+
* @param {integer} strideX - stride length for `x`
46+
* @param {NonNegativeInteger} offsetX - starting index for `x`
47+
* @param {Object} out - output array object
48+
* @param {Collection} out.data - output array data
49+
* @param {Array<Function>} out.accessors - array element accessors
50+
* @param {integer} strideOut - stride length for `out`
51+
* @param {NonNegativeInteger} offsetOut - starting index for `out`
52+
* @returns {Object} output array object
53+
*
54+
* @example
55+
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
56+
* var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
57+
*
58+
* var x = toAccessorArray( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0, NaN, NaN ] );
59+
* var out = toAccessorArray( [ 0.0, 0 ] );
60+
*
61+
* var v = gnannsumkbn( 5, arraylike2object( x ), 2, 1, arraylike2object( out ), 1, 0 );
62+
* // returns {...}
63+
*/
64+
function gnannsumkbn( N, x, strideX, offsetX, out, strideOut, offsetOut ) {
65+
var obuf;
66+
var xbuf;
67+
var xget;
68+
var oset;
69+
var sum;
70+
var ix;
71+
var v;
72+
var t;
73+
var c;
74+
var n;
75+
var i;
76+
77+
// Cache reference to array data:
78+
xbuf = x.data;
79+
obuf = out.data;
80+
81+
// Cache reference to the element accessors:
82+
xget = x.accessors[ 0 ];
83+
oset = out.accessors[ 1 ];
84+
85+
sum = 0.0;
86+
ix = offsetX;
87+
if ( strideX === 0 ) {
88+
v = xget( xbuf, ix );
89+
if ( isnan( v ) ) {
90+
oset( obuf, offsetOut, sum );
91+
oset( obuf, offsetOut+strideOut, 0 );
92+
return out;
93+
}
94+
oset( obuf, offsetOut, v * N );
95+
oset( obuf, offsetOut+strideOut, N );
96+
return out;
97+
}
98+
c = 0.0;
99+
n = 0;
100+
for ( i = 0; i < N; i++ ) {
101+
v = xget( xbuf, ix );
102+
if ( isnan( v ) === false ) {
103+
t = sum + v;
104+
if ( abs( sum ) >= abs( v ) ) {
105+
c += (sum-t) + v;
106+
} else {
107+
c += (v-t) + sum;
108+
}
109+
sum = t;
110+
n += 1;
111+
}
112+
ix += strideX;
113+
}
114+
oset( obuf, offsetOut, sum + c );
115+
oset( obuf, offsetOut+strideOut, n );
116+
return out;
117+
}
118+
119+
120+
// EXPORTS //
121+
122+
module.exports = gnannsumkbn;

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

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

2121
// MODULES //
2222

23+
var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
2324
var isnan = require( '@stdlib/math/base/assert/is-nan' );
2425
var abs = require( '@stdlib/math/base/special/abs' );
26+
var accessors = require( './accessors.js' );
2527

2628

2729
// MAIN //
@@ -56,6 +58,8 @@ var abs = require( '@stdlib/math/base/special/abs' );
5658
function gnannsumkbn( N, x, strideX, offsetX, out, strideOut, offsetOut ) {
5759
var sum;
5860
var ix;
61+
var ox;
62+
var oo;
5963
var v;
6064
var t;
6165
var c;
@@ -68,6 +72,12 @@ function gnannsumkbn( N, x, strideX, offsetX, out, strideOut, offsetOut ) {
6872
out[ offsetOut+strideOut ] = 0;
6973
return out;
7074
}
75+
ox = arraylike2object( x );
76+
oo = arraylike2object( out );
77+
if ( ox.accessorProtocol || oo.accessorProtocol ) {
78+
accessors( N, ox, strideX, offsetX, oo, strideOut, offsetOut );
79+
return out;
80+
}
7181
ix = offsetX;
7282
if ( strideX === 0 ) {
7383
if ( isnan( x[ ix ] ) ) {

0 commit comments

Comments
 (0)