Skip to content

Commit ec233ec

Browse files
headlessNodekgrytestdlib-bot
authored
feat: add C ndarray API and refactor blas/ext/base/dnannsumpw
PR-URL: #2994 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]> Signed-off-by: Athan Reines <[email protected]> Co-authored-by: stdlib-bot <[email protected]>
1 parent d23d168 commit ec233ec

File tree

20 files changed

+408
-181
lines changed

20 files changed

+408
-181
lines changed

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

Lines changed: 133 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@ The function has the following parameters:
5454

5555
- **N**: number of indexed elements.
5656
- **x**: input [`Float64Array`][@stdlib/array/float64].
57-
- **strideX**: index increment for the strided array.
57+
- **strideX**: stride length for `x`.
5858
- **out**: output [`Float64Array`][@stdlib/array/float64] whose first element is the sum and whose second element is the number of non-NaN elements.
59-
- **strideOut**: index increment for `out`.
59+
- **strideOut**: stride length for `out`.
6060

61-
The `N` and `stride` parameters determine which elements are accessed at runtime. For example, to compute the sum of every other element in the strided array,
61+
The `N` and stride parameters determine which elements are accessed at runtime. For example, to compute the sum of every other element in the strided array,
6262

6363
```javascript
6464
var Float64Array = require( '@stdlib/array/float64' );
@@ -103,10 +103,10 @@ var v = dnannsumpw.ndarray( x.length, x, 1, 0, out, 1, 0 );
103103

104104
The function has the following additional parameters:
105105

106-
- **offsetX**: starting index for the strided array.
106+
- **offsetX**: starting index for `x`.
107107
- **offsetOut**: starting index for `out`.
108108

109-
While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying `buffer`, the `offset` parameter supports indexing semantics based on a starting index. For example, to calculate the sum of every other value in the strided array starting from the second value
109+
While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying buffer, offset parameters support indexing semantics based on starting indices. For example, to calculate the sum of every other element starting from the second element:
110110

111111
```javascript
112112
var Float64Array = require( '@stdlib/array/float64' );
@@ -165,8 +165,136 @@ console.log( out );
165165

166166
<!-- /.examples -->
167167

168+
<!-- C interface documentation. -->
169+
168170
* * *
169171

172+
<section class="c">
173+
174+
## C APIs
175+
176+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
177+
178+
<section class="intro">
179+
180+
</section>
181+
182+
<!-- /.intro -->
183+
184+
<!-- C usage documentation. -->
185+
186+
<section class="usage">
187+
188+
### Usage
189+
190+
```c
191+
#include "stdlib/blas/ext/base/dnannsumpw.h"
192+
```
193+
194+
#### stdlib_strided_dnannsumpw( N, \*X, strideX, \*n )
195+
196+
Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation.
197+
198+
```c
199+
#include "stdlib/blas/base/shared.h"
200+
201+
const double x[] = { 1.0, 2.0, 0.0/0.0, 4.0 };
202+
CBLAS_INT n = 0;
203+
204+
double v = stdlib_strided_dnannsumpw( 4, x, 1, &n );
205+
// returns 7.0
206+
```
207+
208+
The function accepts the following arguments:
209+
210+
- **N**: `[in] CBLAS_INT` number of indexed elements.
211+
- **X**: `[in] double*` input array.
212+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
213+
- **n**: `[out] CBLAS_INT*` pointer for storing the number of non-NaN elements.
214+
215+
```c
216+
double stdlib_strided_dnannsumpw( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, CBLAS_INT *n );
217+
```
218+
219+
#### stdlib_strided_dnannsumpw_ndarray( N, \*X, strideX, offsetX, \*n )
220+
221+
Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation and alternative indexing semantics.
222+
223+
```c
224+
#include "stdlib/blas/base/shared.h"
225+
226+
const double x[] = { 1.0, 2.0, 0.0/0.0, 4.0 };
227+
CBLAS_INT n = 0;
228+
229+
double v = stdlib_strided_dnannsumpw_ndarray( 4, x, 1, 0, &n );
230+
// returns 7.0
231+
```
232+
233+
The function accepts the following arguments:
234+
235+
- **N**: `[in] CBLAS_INT` number of indexed elements.
236+
- **X**: `[in] double*` input array.
237+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
238+
- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
239+
- **n**: `[out] CBLAS_INT*` pointer for storing the number of non-NaN elements.
240+
241+
```c
242+
double stdlib_strided_dnannsumpw_ndarray( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n );
243+
```
244+
245+
</section>
246+
247+
<!-- /.usage -->
248+
249+
<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
250+
251+
<section class="notes">
252+
253+
</section>
254+
255+
<!-- /.notes -->
256+
257+
<!-- C API usage examples. -->
258+
259+
<section class="examples">
260+
261+
### Examples
262+
263+
```c
264+
#include "stdlib/blas/ext/base/dnannsumpw.h"
265+
#include "stdlib/blase/base/shared.h"
266+
#include <stdio.h>
267+
268+
int main( void ) {
269+
// Create a strided array:
270+
const double x[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 0.0/0.0, 0.0/0.0 };
271+
272+
// Specify the number of elements:
273+
const int N = 5;
274+
275+
// Specify the stride length:
276+
const int strideX = 2;
277+
278+
// Initialize a variable for storing the number of non-NaN elements:
279+
CBLAS_INT n = 0;
280+
281+
// Compute the sum:
282+
double v = stdlib_strided_dnannsumpw( N, x, strideX, &n );
283+
284+
// Print the result:
285+
printf( "sum: %lf\n", v );
286+
printf( "n: %"CBLAS_IFMT"\n", n );
287+
}
288+
```
289+
290+
</section>
291+
292+
<!-- /.examples -->
293+
294+
</section>
295+
296+
<!-- /.c -->
297+
170298
<section class="references">
171299
172300
## References

lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/benchmark.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ var dnannsumpw = require( './../lib/dnannsumpw.js' );
3333

3434
// FUNCTIONS //
3535

36+
/**
37+
* Returns a random number.
38+
*
39+
* @private
40+
* @returns {number} random number
41+
*/
42+
function rand() {
43+
if ( bernoulli( 0.8 ) > 0 ) {
44+
return uniform( -10.0, 10.0 );
45+
}
46+
return NaN;
47+
}
48+
3649
/**
3750
* Creates a benchmark function.
3851
*
@@ -48,13 +61,6 @@ function createBenchmark( len ) {
4861
out = new Float64Array( 2 );
4962
return benchmark;
5063

51-
function rand() {
52-
if ( bernoulli( 0.8 ) > 0 ) {
53-
return uniform( -10.0, 10.0 );
54-
}
55-
return NaN;
56-
}
57-
5864
function benchmark( b ) {
5965
var i;
6066

lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/benchmark.native.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ var opts = {
4242

4343
// FUNCTIONS //
4444

45+
/**
46+
* Returns a random number.
47+
*
48+
* @private
49+
* @returns {number} random number
50+
*/
51+
function rand() {
52+
if ( bernoulli( 0.8 ) > 0 ) {
53+
return uniform( -10.0, 10.0 );
54+
}
55+
return NaN;
56+
}
57+
4558
/**
4659
* Creates a benchmark function.
4760
*
@@ -57,13 +70,6 @@ function createBenchmark( len ) {
5770
out = new Float64Array( 2 );
5871
return benchmark;
5972

60-
function rand() {
61-
if ( bernoulli( 0.8 ) > 0 ) {
62-
return uniform( -10.0, 10.0 );
63-
}
64-
return NaN;
65-
}
66-
6773
function benchmark( b ) {
6874
var i;
6975

lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/benchmark.ndarray.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ var dnannsumpw = require( './../lib/ndarray.js' );
3333

3434
// FUNCTIONS //
3535

36+
/**
37+
* Returns a random number.
38+
*
39+
* @private
40+
* @returns {number} random number
41+
*/
42+
function rand() {
43+
if ( bernoulli( 0.8 ) > 0 ) {
44+
return uniform( -10.0, 10.0 );
45+
}
46+
return NaN;
47+
}
48+
3649
/**
3750
* Creates a benchmark function.
3851
*
@@ -48,13 +61,6 @@ function createBenchmark( len ) {
4861
out = new Float64Array( 2 );
4962
return benchmark;
5063

51-
function rand() {
52-
if ( bernoulli( 0.8 ) > 0 ) {
53-
return uniform( -10.0, 10.0 );
54-
}
55-
return NaN;
56-
}
57-
5864
function benchmark( b ) {
5965
var i;
6066

lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/benchmark.ndarray.native.js

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,19 @@ var opts = {
4242

4343
// FUNCTIONS //
4444

45+
/**
46+
* Returns a random number.
47+
*
48+
* @private
49+
* @returns {number} random number
50+
*/
51+
function rand() {
52+
if ( bernoulli( 0.8 ) > 0 ) {
53+
return uniform( -10.0, 10.0 );
54+
}
55+
return NaN;
56+
}
57+
4558
/**
4659
* Creates a benchmark function.
4760
*
@@ -57,13 +70,6 @@ function createBenchmark( len ) {
5770
out = new Float64Array( 2 );
5871
return benchmark;
5972

60-
function rand() {
61-
if ( bernoulli( 0.8 ) > 0 ) {
62-
return uniform( -10.0, 10.0 );
63-
}
64-
return NaN;
65-
}
66-
6773
function benchmark( b ) {
6874
var i;
6975

lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/c/benchmark.length.c

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include "stdlib/blas/ext/base/dnannsumpw.h"
20+
#include "stdlib/blas/base/shared.h"
2021
#include <stdlib.h>
2122
#include <stdio.h>
2223
#include <math.h>
@@ -94,10 +95,10 @@ static double rand_double( void ) {
9495
* @param len array length
9596
* @return elapsed time in seconds
9697
*/
97-
static double benchmark( int iterations, int len ) {
98+
static double benchmark1( int iterations, int len ) {
9899
double elapsed;
99100
double x[ len ];
100-
int64_t n;
101+
CBLAS_INT n;
101102
double v;
102103
double t;
103104
int i;
@@ -113,6 +114,7 @@ static double benchmark( int iterations, int len ) {
113114
n = 0;
114115
t = tic();
115116
for ( i = 0; i < iterations; i++ ) {
117+
// cppcheck-suppress uninitvar
116118
v = stdlib_strided_dnannsumpw( len, x, 1, &n );
117119
if ( v != v || n < 0 ) {
118120
printf( "should not return NaN\n" );
@@ -126,6 +128,46 @@ static double benchmark( int iterations, int len ) {
126128
return elapsed;
127129
}
128130

131+
/**
132+
* Runs a benchmark.
133+
*
134+
* @param iterations number of iterations
135+
* @param len array length
136+
* @return elapsed time in seconds
137+
*/
138+
static double benchmark2( int iterations, int len ) {
139+
double elapsed;
140+
double x[ len ];
141+
CBLAS_INT n;
142+
double v;
143+
double t;
144+
int i;
145+
146+
for ( i = 0; i < len; i++ ) {
147+
if ( rand_double() < 0.2 ) {
148+
x[ i ] = 0.0 / 0.0; // NaN
149+
} else {
150+
x[ i ] = ( rand_double() * 20000.0 ) - 10000.0;
151+
}
152+
}
153+
v = 0.0;
154+
n = 0;
155+
t = tic();
156+
for ( i = 0; i < iterations; i++ ) {
157+
// cppcheck-suppress uninitvar
158+
v = stdlib_strided_dnannsumpw_ndarray( len, x, 1, 0, &n );
159+
if ( v != v || n < 0 ) {
160+
printf( "should not return NaN\n" );
161+
break;
162+
}
163+
}
164+
elapsed = tic() - t;
165+
if ( v != v || n < 0 ) {
166+
printf( "should not return NaN\n" );
167+
}
168+
return elapsed;
169+
}
170+
129171
/**
130172
* Main execution sequence.
131173
*/
@@ -148,7 +190,18 @@ int main( void ) {
148190
for ( j = 0; j < REPEATS; j++ ) {
149191
count += 1;
150192
printf( "# c::%s:len=%d\n", NAME, len );
151-
elapsed = benchmark( iter, len );
193+
elapsed = benchmark1( iter, len );
194+
print_results( iter, elapsed );
195+
printf( "ok %d benchmark finished\n", count );
196+
}
197+
}
198+
for ( i = MIN; i <= MAX; i++ ) {
199+
len = pow( 10, i );
200+
iter = ITERATIONS / pow( 10, i-1 );
201+
for ( j = 0; j < REPEATS; j++ ) {
202+
count += 1;
203+
printf( "# c::%s:ndarray:len=%d\n", NAME, len );
204+
elapsed = benchmark2( iter, len );
152205
print_results( iter, elapsed );
153206
printf( "ok %d benchmark finished\n", count );
154207
}

0 commit comments

Comments
 (0)