Skip to content

Commit 0a3d97a

Browse files
committed
feat: add C ndarray API and refactor
1 parent ea7b344 commit 0a3d97a

File tree

16 files changed

+366
-196
lines changed

16 files changed

+366
-196
lines changed

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

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ The function has the following parameters:
5858
- **out**: output [`Float64Array`][@stdlib/array/float64] whose first element is the sum and whose second element is the number of non-NaN elements.
5959
- **strideOut**: index increment 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 index. For example, to calculate the sum of every other value in `x` starting from the second value:
110110

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

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

167+
<!-- C interface documentation. -->
168+
167169
* * *
168170

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

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

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ static double rand_double( void ) {
9494
* @param len array length
9595
* @return elapsed time in seconds
9696
*/
97-
static double benchmark( int iterations, int len ) {
97+
static double benchmark1( int iterations, int len ) {
9898
double elapsed;
9999
double x[ len ];
100-
int64_t n;
100+
int n;
101101
double v;
102102
double t;
103103
int i;
@@ -126,6 +126,45 @@ static double benchmark( int iterations, int len ) {
126126
return elapsed;
127127
}
128128

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

lib/node_modules/@stdlib/blas/ext/base/dnannsumkbn/docs/repl.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Computes the sum of double-precision floating-point strided array elements,
44
ignoring `NaN` values and using an improved Kahan–Babuška algorithm.
55

6-
The `N` and `stride` parameters determine which elements in the strided
6+
The `N` and stride parameters determine which elements in the strided
77
array are accessed at runtime.
88

99
Indexing is relative to the first index. To introduce an offset, use a typed
@@ -62,8 +62,8 @@
6262
alternative indexing semantics.
6363

6464
While typed array views mandate a view offset based on the underlying
65-
buffer, the offsetX and offsetY parameter supports indexing semantics
66-
based on a starting index.
65+
buffer, offset parameters support indexing semantics based on starting
66+
index.
6767

6868
Parameters
6969
----------

lib/node_modules/@stdlib/blas/ext/base/dnannsumkbn/examples/c/example.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,25 @@
1717
*/
1818

1919
#include "stdlib/blas/ext/base/dnannsumkbn.h"
20-
#include <stdint.h>
2120
#include <stdio.h>
22-
#include <inttypes.h>
2321

2422
int main( void ) {
2523
// Create a strided array:
2624
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 };
2725

2826
// Specify the number of elements:
29-
const int64_t N = 5;
27+
const int N = 5;
3028

3129
// Specify the stride length:
32-
const int64_t stride = 2;
30+
const int strideX = 2;
3331

3432
// Initialize a variable for storing the number of non-NaN elements:
35-
int64_t n = 0;
33+
int n = 0;
3634

3735
// Compute the sum:
38-
double v = stdlib_strided_dnannsumkbn( N, x, stride, &n );
36+
double v = stdlib_strided_dnannsumkbn( N, x, strideX, &n );
3937

4038
// Print the result:
4139
printf( "sum: %lf\n", v );
42-
printf( "n: %"PRId64"\n", n );
40+
printf( "n: %d\n", n );
4341
}

lib/node_modules/@stdlib/blas/ext/base/dnannsumkbn/include/stdlib/blas/ext/base/dnannsumkbn.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#ifndef STDLIB_BLAS_EXT_BASE_DNANNSUMKBN_H
2020
#define STDLIB_BLAS_EXT_BASE_DNANNSUMKBN_H
2121

22-
#include <stdint.h>
22+
#include "stdlib/blas/base/shared.h"
2323

2424
/*
2525
* If C++, prevent name mangling so that the compiler emits a binary file having undecorated names, thus mirroring the behavior of a C compiler.
@@ -31,7 +31,12 @@ extern "C" {
3131
/**
3232
* Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using an improved Kahan–Babuška algorithm.
3333
*/
34-
double stdlib_strided_dnannsumkbn( const int64_t N, const double *X, const int64_t stride, int64_t *n );
34+
double API_SUFFIX(stdlib_strided_dnannsumkbn)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, CBLAS_INT *n );
35+
36+
/**
37+
* Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using an improved Kahan–Babuška algorithm and using alternative indexing semantics.
38+
*/
39+
double API_SUFFIX(stdlib_strided_dnannsumkbn_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n );
3540

3641
#ifdef __cplusplus
3742
}

lib/node_modules/@stdlib/blas/ext/base/dnannsumkbn/lib/dnannsumkbn.js

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

2121
// MODULES //
2222

23-
var isnan = require( '@stdlib/math/base/assert/is-nan' );
24-
var abs = require( '@stdlib/math/base/special/abs' );
23+
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
24+
var ndarray = require( './ndarray.js' );
2525

2626

2727
// MAIN //
@@ -54,60 +54,16 @@ var abs = require( '@stdlib/math/base/special/abs' );
5454
* // returns <Float64Array>[ 1.0, 3 ]
5555
*/
5656
function dnannsumkbn( N, x, strideX, out, strideOut ) {
57-
var sum;
5857
var ix;
5958
var io;
60-
var v;
61-
var t;
62-
var c;
63-
var n;
64-
var i;
6559

66-
if ( strideX < 0 ) {
67-
ix = (1-N) * strideX;
68-
} else {
69-
ix = 0;
70-
}
60+
ix = stride2offset( N, strideX );
7161
if ( strideOut < 0 ) {
7262
io = -strideOut;
7363
} else {
7464
io = 0;
7565
}
76-
sum = 0.0;
77-
if ( N <= 0 ) {
78-
out[ io ] = sum;
79-
out[ io+strideOut ] = 0;
80-
return out;
81-
}
82-
if ( N === 1 || strideX === 0 ) {
83-
if ( isnan( x[ ix ] ) ) {
84-
out[ io ] = sum;
85-
out[ io+strideOut ] = 0;
86-
return out;
87-
}
88-
out[ io ] = x[ ix ];
89-
out[ io+strideOut ] = 1;
90-
return out;
91-
}
92-
c = 0.0;
93-
n = 0;
94-
for ( i = 0; i < N; i++ ) {
95-
v = x[ ix ];
96-
if ( isnan( v ) === false ) {
97-
t = sum + v;
98-
if ( abs( sum ) >= abs( v ) ) {
99-
c += (sum-t) + v;
100-
} else {
101-
c += (v-t) + sum;
102-
}
103-
sum = t;
104-
n += 1;
105-
}
106-
ix += strideX;
107-
}
108-
out[ io ] = sum + c;
109-
out[ io+strideOut ] = n;
110-
return out;
66+
return ndarray( N, x, strideX, ix, out, strideOut, io );
11167
}
11268

11369

0 commit comments

Comments
 (0)