Repository navigation
Conversation
Coverage Report
The above coverage report was generated for the changes in this PR. |
There was a problem hiding this comment.
Please update the require statement in benchmark.js to point to the main package export './../lib/main.js' instead of './../lib/' so that the benchmark correctly tests the main entry point.
| /** | ||
| * Computes the standard deviation of a one-dimensional single-precision floating-point ndarray. | ||
| * | ||
| * @param arrays list containing an input ndarray and a zero-dimensional ndarray specifying the degrees of freedom adjustment |
There was a problem hiding this comment.
| * @param arrays list containing an input ndarray and a zero-dimensional ndarray specifying the degrees of freedom adjustment | |
| * ## Notes | |
| * | |
| * - The function expects the following ndarrays: | |
| * | |
| * - a one-dimensional input ndarray. | |
| * - a zero-dimensional ndarray specifying the degrees of freedom adjustment. | |
| * | |
| * @param arrays list containing ndarrays |
| */ | ||
| float stdlib_stats_sstdev( const struct ndarray *arrays[] ) { | ||
| const struct ndarray *x = arrays[ 0 ]; | ||
| const struct ndarray *correction = arrays[ 1 ]; |
There was a problem hiding this comment.
| const struct ndarray *correction = arrays[ 1 ]; |
| const struct ndarray *x = arrays[ 0 ]; | ||
| const struct ndarray *correction = arrays[ 1 ]; | ||
|
|
||
| float c; |
There was a problem hiding this comment.
| float c; | |
| float correction; | |
| stdlib_ndarray_get_float32( arrays[ 1 ], NULL, &correction ); |
| // For zero-dimensional arrays, `stdlib_ndarray_iget_float32` returns the first (and only) indexed element, regardless of the supplied index: | ||
| stdlib_ndarray_iget_float32( correction, 0, &c ); | ||
|
|
||
| return API_SUFFIX(stdlib_strided_sstdev_ndarray)( stdlib_ndarray_dimension( x, 0 ), c, (const float *)stdlib_ndarray_data( x ), stdlib_ndarray_stride_elements( x, 0 ), stdlib_ndarray_offset_elements( x ) ); |
There was a problem hiding this comment.
| return API_SUFFIX(stdlib_strided_sstdev_ndarray)( stdlib_ndarray_dimension( x, 0 ), c, (const float *)stdlib_ndarray_data( x ), stdlib_ndarray_stride_elements( x, 0 ), stdlib_ndarray_offset_elements( x ) ); | |
| return API_SUFFIX(stdlib_strided_sstdev_ndarray)( stdlib_ndarray_dimension( x, 0 ), correction, (const float *)stdlib_ndarray_data( x ), stdlib_ndarray_stride_elements( x, 0 ), stdlib_ndarray_offset_elements( x ) ); |
There was a problem hiding this comment.
The test/test.js file should only test the dynamic dispatcher (using proxyquire to mock tryRequire), rather than running the mathematical tests. The actual correctness tests should live exclusively in test.main.js (for JS) and test.native.js (for C).
Right now, test.js is just a copy of test.main.js. Please update test/test.js so it matches the dispatcher testing pattern;
refer this : lib/node_modules/%40stdlib/stats/base/ndarray/dstdev/test/test.js
| tape( 'the function calculates the standard deviation of a one-dimensional ndarray', opts, function test( t ) { | ||
| var correction; | ||
| var expected; | ||
| var optsD; |
There was a problem hiding this comment.
| var optsD; | |
| var opts; |
|
|
||
| optsD = { | ||
| 'dtype': 'float32' | ||
| }; |
There was a problem hiding this comment.
| }; | |
| opts = { | |
| 'dtype': 'float32' | |
| }; |
| }; | ||
|
|
||
| x = new Float32Array( [ 1.0, -2.0, -4.0, 5.0, 0.0, 3.0 ] ); | ||
| correction = scalar2ndarray( 1.0, optsD ); |
There was a problem hiding this comment.
| correction = scalar2ndarray( 1.0, optsD ); | |
| correction = scalar2ndarray( 1.0, opts ); |
There was a problem hiding this comment.
The local dtype options variable is named optsD throughout this file , please rename it to opts (consistent with the established convention) across all test callbacks.
|
@aryan7071 , It looks like |
|
Left few suggestions; |
|
Hi @ujjwalv01 , thanks for the detailed review! I've pushed a fix commit addressing all of these: src/main.c: Simplified as suggested removed the intermediate correction ndarray variable and switched to stdlib_ndarray_get_float32( arrays[ 1 ], NULL, &correction ), and added the ## Notes block documenting the expected ndarrays list. All three test files pass locally (test.js 4/4, test.main.js 12/12, test.native.js 12/12) and the addon rebuilds cleanly. |
|
Looks good to me. Thanks @aryan7071 , for the changes; cc : @kgryte |
0PrashantYadav0
left a comment
There was a problem hiding this comment.
Please add backticks around the package path in the PR title (feat: add C implementation for stats/base/ndarray/sstdev) and fill in the AI disclosure, which still says {{TODO: add disclosure if applicable}}.
| // Create an input ndarray: | ||
| const float xbuf[] = { 1.0f, 2.0f, 3.0f, 4.0f }; | ||
| int64_t xshape[] = { 4 }; | ||
| int64_t xstrides[] = { STDLIB_NDARRAY_FLOAT32_BYTES_PER_ELEMENT }; | ||
| int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; | ||
|
|
||
| struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)xbuf, 1, xshape, xstrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); | ||
|
|
||
| // Create a zero-dimensional ndarray specifying the degrees of freedom adjustment: | ||
| const float cbuf[] = { 1.0f }; | ||
| int64_t cshape[] = {}; | ||
| int64_t cstrides[] = { 0 }; | ||
|
|
||
| struct ndarray *correction = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cbuf, 0, cshape, cstrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 0, submodes ); | ||
|
|
||
| // Compute the standard deviation: | ||
| const struct ndarray *arrays[] = { x, correction }; | ||
| float v = stdlib_stats_sstdev( arrays ); | ||
| // returns ~2.0817 | ||
|
|
||
| // Free allocated memory: | ||
| stdlib_ndarray_free( x ); | ||
| stdlib_ndarray_free( correction ); |
There was a problem hiding this comment.
| // Create an input ndarray: | |
| const float xbuf[] = { 1.0f, 2.0f, 3.0f, 4.0f }; | |
| int64_t xshape[] = { 4 }; | |
| int64_t xstrides[] = { STDLIB_NDARRAY_FLOAT32_BYTES_PER_ELEMENT }; | |
| int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; | |
| struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)xbuf, 1, xshape, xstrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); | |
| // Create a zero-dimensional ndarray specifying the degrees of freedom adjustment: | |
| const float cbuf[] = { 1.0f }; | |
| int64_t cshape[] = {}; | |
| int64_t cstrides[] = { 0 }; | |
| struct ndarray *correction = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cbuf, 0, cshape, cstrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 0, submodes ); | |
| // Compute the standard deviation: | |
| const struct ndarray *arrays[] = { x, correction }; | |
| float v = stdlib_stats_sstdev( arrays ); | |
| // returns ~2.0817 | |
| // Free allocated memory: | |
| stdlib_ndarray_free( x ); | |
| stdlib_ndarray_free( correction ); | |
| // Create an ndarray: | |
| const float data[] = { 1.0f, -2.0f, 2.0f }; | |
| int64_t shape[] = { 3 }; | |
| int64_t strides[] = { STDLIB_NDARRAY_FLOAT32_BYTES_PER_ELEMENT }; | |
| int8_t submodes[] = { STDLIB_NDARRAY_INDEX_ERROR }; | |
| struct ndarray *x = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)data, 1, shape, strides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); | |
| // Create an ndarray for specifying the degrees of freedom adjustment: | |
| const float cdata[] = { 1.0f }; | |
| int64_t cstrides[] = { 0 }; | |
| struct ndarray *corr = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cdata, 0, NULL, cstrides, 0, STDLIB_NDARRAY_ROW_MAJOR, STDLIB_NDARRAY_INDEX_ERROR, 1, submodes ); | |
| // Compute the result: | |
| const struct ndarray *arrays[] = { x, corr }; | |
| float v = stdlib_stats_sstdev( arrays ); | |
| // returns ~2.0817 | |
| // Free allocated memory: | |
| stdlib_ndarray_free( x ); | |
| stdlib_ndarray_free( corr ); |
With { 1, 2, 3, 4 } this snippet returns 1.290994, not ~2.0817 (compiled and ran it). int64_t cshape[] = {} is also not valid C99 (-pedantic: "zero size arrays are an extension"). Match svariancech/README.md.
|
|
||
| The function accepts the following arguments: | ||
|
|
||
| - **arrays**: `[in] struct ndarray**` list containing the following ndarrays: a one-dimensional input ndarray and a zero-dimensional ndarray specifying the degrees of freedom adjustment. |
There was a problem hiding this comment.
| - **arrays**: `[in] struct ndarray**` list containing the following ndarrays: a one-dimensional input ndarray and a zero-dimensional ndarray specifying the degrees of freedom adjustment. | |
| - **arrays**: `[in] struct ndarray**` list containing the following ndarrays: | |
| - `[in] struct ndarray*` a one-dimensional input ndarray. | |
| - `[in] struct ndarray*` a zero-dimensional ndarray specifying the degrees of freedom adjustment. Providing a non-zero degrees of freedom adjustment has the effect of adjusting the divisor during the calculation of the [standard deviation][standard-deviation] according to `N-c` where `N` is the number of elements in the input ndarray and `c` corresponds to the provided degrees of freedom adjustment. When computing the [standard deviation][standard-deviation] of a population, setting this parameter to `0` is the standard choice (i.e., the provided array contains data constituting an entire population). When computing the corrected sample [standard deviation][standard-deviation], setting this parameter to `1` is the standard choice (i.e., the provided array contains data sampled from a larger population; this is commonly referred to as Bessel's correction). |
Match dstdev/README.md.
| // Create a zero-dimensional ndarray specifying the degrees of freedom adjustment: | ||
| const float cbuf[] = { 1.0f }; | ||
| int64_t *cshape = NULL; | ||
| int64_t cstrides[] = { 0 }; | ||
|
|
||
| // cppcheck-suppress invalidPointerCast | ||
| struct ndarray *correction = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cbuf, 0, cshape, cstrides, offset, order, imode, 0, submodes ); |
There was a problem hiding this comment.
| // Create a zero-dimensional ndarray specifying the degrees of freedom adjustment: | |
| const float cbuf[] = { 1.0f }; | |
| int64_t *cshape = NULL; | |
| int64_t cstrides[] = { 0 }; | |
| // cppcheck-suppress invalidPointerCast | |
| struct ndarray *correction = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cbuf, 0, cshape, cstrides, offset, order, imode, 0, submodes ); | |
| // Create a data buffer for an ndarray specifying the degrees of freedom adjustment: | |
| const float cbuf[] = { 1.0f }; | |
| // Specify the array strides: | |
| int64_t cstrides[] = { 0 }; | |
| // Create an ndarray for the degrees of freedom adjustment: | |
| // cppcheck-suppress invalidPointerCast | |
| struct ndarray *correction = stdlib_ndarray_allocate( STDLIB_NDARRAY_FLOAT32, (uint8_t *)cbuf, 0, NULL, cstrides, 0, order, imode, nsubmodes, submodes ); |
The correction ndarray shouldn't reuse x's offset; match svariancech/examples/c/example.c. Same in README.md:301-306 and benchmark/c/benchmark.length.c:141-144.
| * Generates a random number on the interval [0, 1). | ||
| * | ||
| * @return random number | ||
| */ | ||
| static double rand_double( void ) { | ||
| return (double)rand() / ( (double)RAND_MAX + 1.0 ); |
There was a problem hiding this comment.
| * Generates a random number on the interval [0, 1). | |
| * | |
| * @return random number | |
| */ | |
| static double rand_double( void ) { | |
| return (double)rand() / ( (double)RAND_MAX + 1.0 ); | |
| * Generates a random number on the interval [0,1). | |
| * | |
| * @return random number | |
| */ | |
| static float rand_float( void ) { | |
| int r = rand(); | |
| return (float)r / ( (float)RAND_MAX + 1.0f ); |
Line 135 then becomes data[ i ] = ( rand_float() * 20000.0f ) - 10000.0f;. See #15170 (comment) and svariancech/benchmark/c/benchmark.length.c.
| $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES) | ||
|
|
||
| #/ | ||
| # Runs compiled examples. |
There was a problem hiding this comment.
| # Runs compiled examples. | |
| # Runs compiled benchmarks. |
| // Create a const-qualified view of the argument pointer list: | ||
| const struct ndarray *arr[ 2 ] = { | ||
| arrays[ 0 ], | ||
| arrays[ 1 ] | ||
| }; | ||
| // Perform computation: | ||
| STDLIB_NAPI_CREATE_DOUBLE( env, (double)stdlib_stats_sstdev( arr ), v ); | ||
|
|
||
| // Free allocated memory: | ||
| stdlib_ndarray_free( arrays[ 0 ] ); | ||
| arrays[ 0 ] = NULL; | ||
|
|
||
| stdlib_ndarray_free( arrays[ 1 ] ); | ||
| arrays[ 1 ] = NULL; |
There was a problem hiding this comment.
| // Create a const-qualified view of the argument pointer list: | |
| const struct ndarray *arr[ 2 ] = { | |
| arrays[ 0 ], | |
| arrays[ 1 ] | |
| }; | |
| // Perform computation: | |
| STDLIB_NAPI_CREATE_DOUBLE( env, (double)stdlib_stats_sstdev( arr ), v ); | |
| // Free allocated memory: | |
| stdlib_ndarray_free( arrays[ 0 ] ); | |
| arrays[ 0 ] = NULL; | |
| stdlib_ndarray_free( arrays[ 1 ] ); | |
| arrays[ 1 ] = NULL; | |
| // Create a const-qualified view of the argument pointer list: | |
| const struct ndarray *arr[ 2 ] = { arrays[ 0 ], arrays[ 1 ] }; | |
| // Perform computation: | |
| STDLIB_NAPI_CREATE_DOUBLE( env, (double)stdlib_stats_sstdev( arr ), v ); | |
| // Free allocated memory: | |
| stdlib_ndarray_free( arrays[ 0 ] ); | |
| stdlib_ndarray_free( arrays[ 1 ] ); | |
| arrays[ 0 ] = NULL; | |
| arrays[ 1 ] = NULL; |
Match svariancech/src/addon.c.
| * var opts = { | ||
| * 'dtype': 'float32' | ||
| * }); | ||
| * }; | ||
| * | ||
| * var x = new Float32Vector( [ 1.0, -2.0, 2.0 ] ); | ||
| * | ||
| * var correction = scalar2ndarray( 1.0, opts ); |
There was a problem hiding this comment.
| * var opts = { | |
| * 'dtype': 'float32' | |
| * }); | |
| * }; | |
| * | |
| * var x = new Float32Vector( [ 1.0, -2.0, 2.0 ] ); | |
| * | |
| * var correction = scalar2ndarray( 1.0, opts ); | |
| * var x = new Float32Vector( [ 1.0, -2.0, 2.0 ] ); | |
| * var correction = scalar2ndarray( 1.0, { | |
| * 'dtype': 'float32' | |
| * }); |
This change isn't needed; keep the example as in lib/main.js. Same in lib/native.js:48-54, see #15170 (comment).
Resolves a part of #14034
Description
This pull request:
sstdev).Related Issues
This pull request has the following related issues:
@stdlib/stats/base/ndarraypackages (tracking issue) #14034Questions
No.
Other
No.
Checklist
AI Assistance
If you answered "yes" above, how did you use AI assistance?
Disclosure
{{TODO: add disclosure if applicable}}
@stdlib-js/reviewers