Skip to content

Commit af8d471

Browse files
authored
feat: add C ndarray API and refactor blas/ext/base/dnannsumors
PR-URL: #2991 Reviewed-by: Philipp Burckhardt <[email protected]>
1 parent 796d76a commit af8d471

File tree

20 files changed

+401
-202
lines changed

20 files changed

+401
-202
lines changed

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

Lines changed: 130 additions & 4 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 `x`.
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 `x`,
61+
The `N` and stride parameters determine which elements are accessed at runtime. For example, to compute the sum of every other element in `x`,
6262

6363
```javascript
6464
var Float64Array = require( '@stdlib/array/float64' );
@@ -106,7 +106,7 @@ The function has the following additional parameters:
106106
- **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 `x` 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' );
@@ -166,6 +166,132 @@ console.log( out );
166166

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

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

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ var dnannsumors = require( './../lib/dnannsumors.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
*
@@ -46,13 +59,6 @@ function createBenchmark( len ) {
4659
out = new Float64Array( 2 );
4760
return benchmark;
4861

49-
function rand() {
50-
if ( bernoulli( 0.8 ) > 0 ) {
51-
return uniform( -10.0, 10.0 );
52-
}
53-
return NaN;
54-
}
55-
5662
function benchmark( b ) {
5763
var i;
5864

lib/node_modules/@stdlib/blas/ext/base/dnannsumors/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
*
@@ -55,13 +68,6 @@ function createBenchmark( len ) {
5568
out = new Float64Array( 2 );
5669
return benchmark;
5770

58-
function rand() {
59-
if ( bernoulli( 0.8 ) > 0 ) {
60-
return uniform( -10.0, 10.0 );
61-
}
62-
return NaN;
63-
}
64-
6571
function benchmark( b ) {
6672
var i;
6773

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ var dnannsumors = 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
*
@@ -46,13 +59,6 @@ function createBenchmark( len ) {
4659
out = new Float64Array( 2 );
4760
return benchmark;
4861

49-
function rand() {
50-
if ( bernoulli( 0.8 ) > 0 ) {
51-
return uniform( -10.0, 10.0 );
52-
}
53-
return NaN;
54-
}
55-
5662
function benchmark( b ) {
5763
var i;
5864

lib/node_modules/@stdlib/blas/ext/base/dnannsumors/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
*
@@ -55,13 +68,6 @@ function createBenchmark( len ) {
5568
out = new Float64Array( 2 );
5669
return benchmark;
5770

58-
function rand() {
59-
if ( bernoulli( 0.8 ) > 0 ) {
60-
return uniform( -10.0, 10.0 );
61-
}
62-
return NaN;
63-
}
64-
6571
function benchmark( b ) {
6672
var i;
6773

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

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

1919
#include "stdlib/blas/ext/base/dnannsumors.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;
@@ -126,6 +127,45 @@ static double benchmark( int iterations, int len ) {
126127
return elapsed;
127128
}
128129

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

0 commit comments

Comments
 (0)