Skip to content

Commit 3e1f4b3

Browse files
gururaj1512kgryte
andauthored
feat: add C ndarray interface and refactor implementation for stats/base/snanmskrange
PR-URL: #7238 Co-authored-by: Athan Reines <[email protected]> Reviewed-by: Athan Reines <[email protected]>
1 parent 40c7647 commit 3e1f4b3

22 files changed

+449
-422
lines changed

lib/node_modules/@stdlib/stats/base/snanmskrange/README.md

Lines changed: 160 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ limitations under the License.
1818
1919
-->
2020

21+
<!-- lint disable maximum-heading-length -->
22+
2123
# snanmskrange
2224

2325
> Calculate the [range][range] of a single-precision floating-point strided array according to a mask, ignoring `NaN` values.
@@ -40,7 +42,7 @@ var snanmskrange = require( '@stdlib/stats/base/snanmskrange' );
4042

4143
#### snanmskrange( N, x, strideX, mask, strideMask )
4244

43-
Computes the [range][range] of a single-precision floating-point strided array `x` according to a `mask`, ignoring `NaN` values.
45+
Computes the [range][range] of a single-precision floating-point strided array according to a `mask`, ignoring `NaN` values.
4446

4547
```javascript
4648
var Float32Array = require( '@stdlib/array/float32' );
@@ -57,22 +59,20 @@ The function has the following parameters:
5759

5860
- **N**: number of indexed elements.
5961
- **x**: input [`Float32Array`][@stdlib/array/float32].
60-
- **strideX**: index increment for `x`.
62+
- **strideX**: stride length for `x`.
6163
- **mask**: mask [`Uint8Array`][@stdlib/array/uint8]. If a `mask` array element is `0`, the corresponding element in `x` is considered valid and **included** in computation. If a `mask` array element is `1`, the corresponding element in `x` is considered invalid/missing and **excluded** from computation.
62-
- **strideMask**: index increment for `mask`.
64+
- **strideMask**: stride length for `mask`.
6365

64-
The `N` and `stride` parameters determine which elements are accessed at runtime. For example, to compute the [range][range] of every other element in `x`,
66+
The `N` and stride parameters determine which elements in the strided arrays are accessed at runtime. For example, to compute the [range][range] of every other element in `x`,
6567

6668
```javascript
6769
var Float32Array = require( '@stdlib/array/float32' );
6870
var Uint8Array = require( '@stdlib/array/uint8' );
69-
var floor = require( '@stdlib/math/base/special/floor' );
7071

7172
var x = new Float32Array( [ 1.0, 2.0, -7.0, -2.0, 4.0, 3.0, 5.0, 6.0 ] );
7273
var mask = new Uint8Array( [ 0, 0, 0, 0, 0, 0, 1, 1 ] );
73-
var N = floor( x.length / 2 );
7474

75-
var v = snanmskrange( N, x, 2, mask, 2 );
75+
var v = snanmskrange( 4, x, 2, mask, 2 );
7676
// returns 11.0
7777
```
7878

@@ -83,17 +83,14 @@ Note that indexing is relative to the first index. To introduce offsets, use [`t
8383
```javascript
8484
var Float32Array = require( '@stdlib/array/float32' );
8585
var Uint8Array = require( '@stdlib/array/uint8' );
86-
var floor = require( '@stdlib/math/base/special/floor' );
8786

8887
var x0 = new Float32Array( [ 2.0, 1.0, -2.0, -2.0, 3.0, 4.0, 5.0, 6.0 ] );
8988
var x1 = new Float32Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
9089

9190
var mask0 = new Uint8Array( [ 0, 0, 0, 0, 0, 0, 1, 1 ] );
9291
var mask1 = new Uint8Array( mask0.buffer, mask0.BYTES_PER_ELEMENT*1 ); // start at 2nd element
9392

94-
var N = floor( x0.length / 2 );
95-
96-
var v = snanmskrange( N, x1, 2, mask1, 2 );
93+
var v = snanmskrange( 4, x1, 2, mask1, 2 );
9794
// returns 6.0
9895
```
9996

@@ -117,18 +114,16 @@ The function has the following additional parameters:
117114
- **offsetX**: starting index for `x`.
118115
- **offsetMask**: starting index for `mask`.
119116

120-
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 [range][range] for every other value in `x` starting from the second value
117+
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 [range][range] for every other element in `x` starting from the second element
121118

122119
```javascript
123120
var Float32Array = require( '@stdlib/array/float32' );
124121
var Uint8Array = require( '@stdlib/array/uint8' );
125-
var floor = require( '@stdlib/math/base/special/floor' );
126122

127123
var x = new Float32Array( [ 2.0, 1.0, -2.0, -2.0, 3.0, 4.0, 5.0, 6.0 ] );
128124
var mask = new Uint8Array( [ 0, 0, 0, 0, 0, 0, 1, 1 ] );
129-
var N = floor( x.length / 2 );
130125

131-
var v = snanmskrange.ndarray( N, x, 2, 1, mask, 2, 1 );
126+
var v = snanmskrange.ndarray( 4, x, 2, 1, mask, 2, 1 );
132127
// returns 6.0
133128
```
134129

@@ -153,31 +148,22 @@ var v = snanmskrange.ndarray( N, x, 2, 1, mask, 2, 1 );
153148
<!-- eslint no-undef: "error" -->
154149

155150
```javascript
156-
var randu = require( '@stdlib/random/base/randu' );
157-
var round = require( '@stdlib/math/base/special/round' );
158-
var Float32Array = require( '@stdlib/array/float32' );
159-
var Uint8Array = require( '@stdlib/array/uint8' );
151+
var uniform = require( '@stdlib/random/base/uniform' );
152+
var bernoulli = require( '@stdlib/random/base/bernoulli' );
153+
var filledarrayBy = require( '@stdlib/array/filled-by' );
160154
var snanmskrange = require( '@stdlib/stats/base/snanmskrange' );
161155

162-
var mask;
163-
var x;
164-
var i;
165-
166-
x = new Float32Array( 10 );
167-
mask = new Uint8Array( x.length );
168-
for ( i = 0; i < x.length; i++ ) {
169-
if ( randu() < 0.2 ) {
170-
mask[ i ] = 1;
171-
} else {
172-
mask[ i ] = 0;
173-
}
174-
if ( randu() < 0.1 ) {
175-
x[ i ] = NaN;
176-
} else {
177-
x[ i ] = round( (randu()*100.0) - 50.0 );
156+
function rand() {
157+
if ( bernoulli( 0.8 ) < 1 ) {
158+
return NaN;
178159
}
160+
return uniform( -50.0, 50.0 );
179161
}
162+
163+
var x = filledarrayBy( 10, 'float32', rand );
180164
console.log( x );
165+
166+
var mask = filledarrayBy( x.length, 'uint8', bernoulli.factory( 0.2 ) );
181167
console.log( mask );
182168

183169
var v = snanmskrange( x.length, x, 1, mask, 1 );
@@ -188,6 +174,145 @@ console.log( v );
188174

189175
<!-- /.examples -->
190176

177+
<!-- C interface documentation. -->
178+
179+
* * *
180+
181+
<section class="c">
182+
183+
## C APIs
184+
185+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
186+
187+
<section class="intro">
188+
189+
</section>
190+
191+
<!-- /.intro -->
192+
193+
<!-- C usage documentation. -->
194+
195+
<section class="usage">
196+
197+
### Usage
198+
199+
```c
200+
#include "stdlib/stats/base/snanmskrange.h"
201+
```
202+
203+
#### stdlib_strided_snanmskrange( N, \*X, strideX, \*Mask, strideMask )
204+
205+
Computes the [range][range] of a single-precision floating-point strided array according to a `mask`, ignoring `NaN` values.
206+
207+
```c
208+
#include <stdint.h>
209+
210+
const float x[] = { 1.0f, -2.0f, 4.0f, 2.0f, 0.0f/0.0f };
211+
const uint8_t mask[] = { 0, 0, 1, 0, 0 };
212+
213+
float v = stdlib_strided_snanmskrange( 5, x, 1, mask, 1 );
214+
// returns 4.0f
215+
```
216+
217+
The function accepts the following arguments:
218+
219+
- **N**: `[in] CBLAS_INT` number of indexed elements.
220+
- **X**: `[in] float*` input array.
221+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
222+
- **Mask**: `[in] uint8_t*` mask array. If a `Mask` array element is `0`, the corresponding element in `X` is considered valid and included in computation. If a `Mask` array element is `1`, the corresponding element in `X` is considered invalid/missing and excluded from computation.
223+
- **strideMask**: `[in] CBLAS_INT` stride length for `Mask`.
224+
225+
```c
226+
float stdlib_strided_snanmskrange( const CBLAS_INT N, const float *X, const CBLAS_INT strideX, const uint8_t *Mask, const CBLAS_INT strideMask );
227+
```
228+
229+
#### stdlib_strided_snanmskrange_ndarray( N, \*X, strideX, offsetX, \*Mask, strideMask, offsetMask )
230+
231+
Computes the [range][range] of a single-precision floating-point strided array according to a `mask`, ignoring `NaN` values and using alternative indexing semantics.
232+
233+
```c
234+
#include <stdint.h>
235+
236+
const float x[] = { 1.0f, -2.0f, 4.0f, 2.0f, 0.0f/0.0f };
237+
const uint8_t mask[] = { 0, 0, 1, 0, 0 };
238+
239+
float v = stdlib_strided_snanmskrange_ndarray( 5, x, 1, 0, mask, 1, 0 );
240+
// returns 4.0f
241+
```
242+
243+
The function accepts the following arguments:
244+
245+
- **N**: `[in] CBLAS_INT` number of indexed elements.
246+
- **X**: `[in] float*` input array.
247+
- **strideX**: `[in] CBLAS_INT` stride length for `X`.
248+
- **offsetX**: `[in] CBLAS_INT` starting index for `X`.
249+
- **Mask**: `[in] uint8_t*` mask array. If a `Mask` array element is `0`, the corresponding element in `X` is considered valid and included in computation. If a `Mask` array element is `1`, the corresponding element in `X` is considered invalid/missing and excluded from computation.
250+
- **strideMask**: `[in] CBLAS_INT` stride length for `Mask`.
251+
- **offsetMask**: `[in] CBLAS_INT` starting index for `Mask`.
252+
253+
```c
254+
float stdlib_strided_snanmskrange_ndarray( const CBLAS_INT N, const float *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, const uint8_t *Mask, const CBLAS_INT strideMask, const CBLAS_INT offsetMask );
255+
```
256+
257+
</section>
258+
259+
<!-- /.usage -->
260+
261+
<!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
262+
263+
<section class="notes">
264+
265+
</section>
266+
267+
<!-- /.notes -->
268+
269+
<!-- C API usage examples. -->
270+
271+
<section class="examples">
272+
273+
### Examples
274+
275+
```c
276+
#include "stdlib/stats/base/snanmskrange.h"
277+
#include <stdint.h>
278+
#include <stdio.h>
279+
280+
int main( void ) {
281+
// Create a strided array:
282+
const float x[] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 0.0f/0.0f, 0.0f/0.0f };
283+
284+
// Create a mask array:
285+
const uint8_t mask[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
286+
287+
// Specify the number of elements:
288+
const int N = 5;
289+
290+
// Specify the stride lengths:
291+
const int strideX = 2;
292+
const int strideMask = 2;
293+
294+
// Compute the range:
295+
float v = stdlib_strided_snanmskrange( N, x, strideX, mask, strideMask );
296+
297+
// Print the result:
298+
printf( "range: %f\n", v );
299+
}
300+
```
301+
302+
</section>
303+
304+
<!-- /.examples -->
305+
306+
</section>
307+
308+
<!-- /.c -->
309+
310+
<section class="references">
311+
312+
</section>
313+
314+
<!-- /.references -->
315+
191316
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
192317
193318
<section class="related">

lib/node_modules/@stdlib/stats/base/snanmskrange/benchmark/benchmark.js

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,30 @@
2121
// MODULES //
2222

2323
var bench = require( '@stdlib/bench' );
24-
var randu = require( '@stdlib/random/base/randu' );
24+
var uniform = require( '@stdlib/random/base/uniform' );
25+
var bernoulli = require( '@stdlib/random/base/bernoulli' );
26+
var filledarrayBy = require( '@stdlib/array/filled-by' );
2527
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
2628
var pow = require( '@stdlib/math/base/special/pow' );
27-
var Float32Array = require( '@stdlib/array/float32' );
28-
var Uint8Array = require( '@stdlib/array/uint8' );
2929
var pkg = require( './../package.json' ).name;
3030
var snanmskrange = require( './../lib/snanmskrange.js' );
3131

3232

3333
// FUNCTIONS //
3434

35+
/**
36+
* Returns a random value or `NaN`.
37+
*
38+
* @private
39+
* @returns {number} random number or `NaN`
40+
*/
41+
function rand() {
42+
if ( bernoulli( 0.8 ) < 1 ) {
43+
return NaN;
44+
}
45+
return uniform( -10.0, 10.0 );
46+
}
47+
3548
/**
3649
* Creates a benchmark function.
3750
*
@@ -42,18 +55,9 @@ var snanmskrange = require( './../lib/snanmskrange.js' );
4255
function createBenchmark( len ) {
4356
var mask;
4457
var x;
45-
var i;
4658

47-
x = new Float32Array( len );
48-
mask = new Uint8Array( len );
49-
for ( i = 0; i < x.length; i++ ) {
50-
if ( randu() < 0.2 ) {
51-
mask[ i ] = 1;
52-
} else {
53-
mask[ i ] = 0;
54-
}
55-
x[ i ] = ( randu()*20.0 ) - 10.0;
56-
}
59+
x = filledarrayBy( len, 'float32', rand );
60+
mask = filledarrayBy( len, 'uint8', bernoulli.factory( 0.2 ) );
5761
return benchmark;
5862

5963
function benchmark( b ) {

lib/node_modules/@stdlib/stats/base/snanmskrange/benchmark/benchmark.native.js

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222

2323
var resolve = require( 'path' ).resolve;
2424
var bench = require( '@stdlib/bench' );
25-
var randu = require( '@stdlib/random/base/randu' );
25+
var uniform = require( '@stdlib/random/base/uniform' );
26+
var bernoulli = require( '@stdlib/random/base/bernoulli' );
27+
var filledarrayBy = require( '@stdlib/array/filled-by' );
2628
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
2729
var pow = require( '@stdlib/math/base/special/pow' );
28-
var Float32Array = require( '@stdlib/array/float32' );
29-
var Uint8Array = require( '@stdlib/array/uint8' );
3030
var tryRequire = require( '@stdlib/utils/try-require' );
3131
var pkg = require( './../package.json' ).name;
3232

@@ -41,6 +41,19 @@ var opts = {
4141

4242
// FUNCTIONS //
4343

44+
/**
45+
* Returns a random value or `NaN`.
46+
*
47+
* @private
48+
* @returns {number} random number or `NaN`
49+
*/
50+
function rand() {
51+
if ( bernoulli( 0.8 ) < 1 ) {
52+
return NaN;
53+
}
54+
return uniform( -10.0, 10.0 );
55+
}
56+
4457
/**
4558
* Creates a benchmark function.
4659
*
@@ -51,18 +64,9 @@ var opts = {
5164
function createBenchmark( len ) {
5265
var mask;
5366
var x;
54-
var i;
5567

56-
x = new Float32Array( len );
57-
mask = new Uint8Array( len );
58-
for ( i = 0; i < x.length; i++ ) {
59-
if ( randu() < 0.2 ) {
60-
mask[ i ] = 1;
61-
} else {
62-
mask[ i ] = 0;
63-
}
64-
x[ i ] = ( randu()*20.0 ) - 10.0;
65-
}
68+
x = filledarrayBy( len, 'float32', rand );
69+
mask = filledarrayBy( len, 'uint8', bernoulli.factory( 0.2 ) );
6670
return benchmark;
6771

6872
function benchmark( b ) {

0 commit comments

Comments
 (0)