diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/README.md b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/README.md index ac28485e833..52a5c05194c 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/README.md @@ -58,7 +58,7 @@ The function has the following parameters: - **out**: output [`Float64Array`][@stdlib/array/float64] whose first element is the sum and whose second element is the number of non-NaN elements. - **strideOut**: index increment for `out`. -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, +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, ```javascript var Float64Array = require( '@stdlib/array/float64' ); @@ -106,7 +106,7 @@ The function has the following additional parameters: - **offsetX**: starting index for the strided array. - **offsetOut**: starting index for `out`. -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 +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 value in the strided array starting from the second value: ```javascript var Float64Array = require( '@stdlib/array/float64' ); @@ -165,8 +165,132 @@ console.log( out ); + + * * * +
+ +## C APIs + + + +
+ +
+ + + + + +
+ +### Usage + +```c +#include "stdlib/blas/ext/base/dnannsumpw.h" +``` + +#### stdlib_strided_dnannsumpw( N, \*X, strideX, \*n ) + +Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation. + +```c +const double x[] = { 1.0, 2.0, 0.0/0.0, 4.0 }; +CBLAS_INT n = 0; + +double v = stdlib_strided_dnannsumpw( 4, x, 1, &n ); +// returns 7.0 +``` + +The function accepts the following arguments: + +- **N**: `[in] CBLAS_INT` number of indexed elements. +- **X**: `[in] double*` input array. +- **strideX**: `[in] CBLAS_INT` index increment for `X`. +- **n**: `[out] CBLAS_INT*` number of non-NaN elements. + +```c +double stdlib_strided_dnannsumpw( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, CBLAS_INT *n ); +``` + +#### stdlib_strided_dnannsumpw_ndarray( N, \*X, strideX, offsetX, \*n ) + +Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation and alternative indexing semantics. + +```c +const double x[] = { 1.0, 2.0, 0.0/0.0, 4.0 }; +CBLAS_INT n = 0; + +double v = stdlib_strided_dnannsumpw_ndarray( 4, x, 1, 0, &n ); +// returns 7.0 +``` + +The function accepts the following arguments: + +- **N**: `[in] CBLAS_INT` number of indexed elements. +- **X**: `[in] double*` input array. +- **strideX**: `[in] CBLAS_INT` index increment for `X`. +- **offsetX**: `[in] CBLAS_INT` starting index for `X`. +- **n**: `[out] CBLAS_INT*` number of non-NaN elements. + +```c +double stdlib_strided_dnannsumpw_ndarray( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n ); +``` + +
+ + + + + +
+ +
+ + + + + +
+ +### Examples + +```c +#include "stdlib/blas/ext/base/dnannsumpw.h" +#include "stdlib/blase/base/shared.h" +#include + +int main( void ) { + // Create a strided array: + 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 }; + + // Specify the number of elements: + const int N = 5; + + // Specify the stride length: + const int strideX = 2; + + // Initialize a variable for storing the number of non-NaN elements: + CBLAS_INT n = 0; + + // Compute the sum: + double v = stdlib_strided_dnannsumpw( N, x, strideX, &n ); + + // Print the result: + printf( "sum: %lf\n", v ); + printf( "n: %"CBLAS_IFMT"\n", n ); +} +``` + +
+ + + +
+ + +
## References diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/c/benchmark.length.c b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/c/benchmark.length.c index ed0058b4c27..3a0b8247339 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/c/benchmark.length.c +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/benchmark/c/benchmark.length.c @@ -17,6 +17,7 @@ */ #include "stdlib/blas/ext/base/dnannsumpw.h" +#include "stdlib/blas/base/shared.h" #include #include #include @@ -94,10 +95,10 @@ static double rand_double( void ) { * @param len array length * @return elapsed time in seconds */ -static double benchmark( int iterations, int len ) { +static double benchmark1( int iterations, int len ) { double elapsed; double x[ len ]; - int64_t n; + CBLAS_INT n; double v; double t; int i; @@ -126,6 +127,45 @@ static double benchmark( int iterations, int len ) { return elapsed; } +/** +* Runs a benchmark. +* +* @param iterations number of iterations +* @param len array length +* @return elapsed time in seconds +*/ +static double benchmark2( int iterations, int len ) { + double elapsed; + double x[ len ]; + CBLAS_INT n; + double v; + double t; + int i; + + for ( i = 0; i < len; i++ ) { + if ( rand_double() < 0.2 ) { + x[ i ] = 0.0 / 0.0; // NaN + } else { + x[ i ] = ( rand_double() * 20000.0 ) - 10000.0; + } + } + v = 0.0; + n = 0; + t = tic(); + for ( i = 0; i < iterations; i++ ) { + v = stdlib_strided_dnannsumpw_ndarray( len, x, 1, 0, &n ); + if ( v != v || n < 0 ) { + printf( "should not return NaN\n" ); + break; + } + } + elapsed = tic() - t; + if ( v != v || n < 0 ) { + printf( "should not return NaN\n" ); + } + return elapsed; +} + /** * Main execution sequence. */ @@ -148,7 +188,18 @@ int main( void ) { for ( j = 0; j < REPEATS; j++ ) { count += 1; printf( "# c::%s:len=%d\n", NAME, len ); - elapsed = benchmark( iter, len ); + elapsed = benchmark1( iter, len ); + print_results( iter, elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + } + for ( i = MIN; i <= MAX; i++ ) { + len = pow( 10, i ); + iter = ITERATIONS / pow( 10, i-1 ); + for ( j = 0; j < REPEATS; j++ ) { + count += 1; + printf( "# c::%s:ndarray:len=%d\n", NAME, len ); + elapsed = benchmark2( iter, len ); print_results( iter, elapsed ); printf( "ok %d benchmark finished\n", count ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/docs/repl.txt b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/docs/repl.txt index 7a9cab8d5a1..7af984a7e69 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/docs/repl.txt +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/docs/repl.txt @@ -3,7 +3,7 @@ Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation. - The `N` and `stride` parameters determine which elements are accessed at + The `N` and stride parameters determine which elements are accessed at runtime. Indexing is relative to the first index. To introduce an offset, use a typed @@ -62,8 +62,8 @@ semantics. While typed array views mandate a view offset based on the underlying - buffer, the `offset` parameter supports indexing semantics based on a - starting index. + buffer, offset parameters support indexing semantics based on starting + indices. Parameters ---------- diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/examples/c/example.c b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/examples/c/example.c index 5a3a8cd1411..c46893ab378 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/examples/c/example.c +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/examples/c/example.c @@ -17,27 +17,26 @@ */ #include "stdlib/blas/ext/base/dnannsumpw.h" -#include +#include "stdlib/blas/base/shared.h" #include -#include int main( void ) { // Create a strided array: 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 }; // Specify the number of elements: - const int64_t N = 5; + const int N = 5; // Specify the stride length: - const int64_t stride = 2; + const int strideX = 2; // Initialize a variable for storing the number of non-NaN elements: - int64_t n = 0; + CBLAS_INT n = 0; // Compute the sum: - double v = stdlib_strided_dnannsumpw( N, x, stride, &n ); + double v = stdlib_strided_dnannsumpw( N, x, strideX, &n ); // Print the result: printf( "sum: %lf\n", v ); - printf( "n: %"PRId64"\n", n ); + printf( "n: %"CBLAS_IFMT"\n", n ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/include/stdlib/blas/ext/base/dnannsumpw.h b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/include/stdlib/blas/ext/base/dnannsumpw.h index 6380bc83270..436aaab6c9b 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/include/stdlib/blas/ext/base/dnannsumpw.h +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/include/stdlib/blas/ext/base/dnannsumpw.h @@ -19,7 +19,7 @@ #ifndef STDLIB_BLAS_EXT_BASE_DNANNSUMPW_H #define STDLIB_BLAS_EXT_BASE_DNANNSUMPW_H -#include +#include "stdlib/blas/base/shared.h" /* * 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" { /** * Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation. */ -double stdlib_strided_dnannsumpw( const int64_t N, const double *X, const int64_t stride, int64_t *n ); +double API_SUFFIX(stdlib_strided_dnannsumpw)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, CBLAS_INT *n ); + +/** +* Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation and alternative indexing semantics. +*/ +double API_SUFFIX(stdlib_strided_dnannsumpw_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n ); #ifdef __cplusplus } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/dnannsumpw.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/dnannsumpw.js index 1ce83c440c6..23b2becdd27 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/dnannsumpw.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/dnannsumpw.js @@ -20,7 +20,8 @@ // MODULES // -var sumpw = require( './sumpw.js' ); +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -55,20 +56,14 @@ var sumpw = require( './sumpw.js' ); function dnannsumpw( N, x, strideX, out, strideOut ) { var ix; var io; - if ( strideX < 0 ) { - ix = (1-N) * strideX; - } else { - ix = 0; - } + + ix = stride2offset( N, strideX ); if ( strideOut < 0 ) { io = -strideOut; } else { io = 0; } - out[ io ] = 0.0; - out[ io+strideOut ] = 0; - sumpw( N, x, strideX, ix, out, strideOut, io ); - return out; + return ndarray( N, x, strideX, ix, out, strideOut, io ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.js index 33b88afce3c..4e5df22ae67 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.js @@ -38,10 +38,10 @@ var sumpw = require( './sumpw.js' ); * * @param {PositiveInteger} N - number of indexed elements * @param {Float64Array} x - input array -* @param {integer} strideX - `x` stride length +* @param {integer} strideX - `x` index increment * @param {NonNegativeInteger} offsetX - `x` starting index * @param {Float64Array} out - output array -* @param {integer} strideOut - `out` stride length +* @param {integer} strideOut - `out` index increment * @param {NonNegativeInteger} offsetOut - `out` starting index * @returns {Float64Array} output array * @@ -55,10 +55,7 @@ var sumpw = require( './sumpw.js' ); * // returns [ 5.0, 4 ] */ function dnannsumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ) { - out[ offsetOut ] = 0.0; - out[ offsetOut+strideOut ] = 0; - sumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ); - return out; + return sumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.native.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.native.js index 3cf957affba..aaa1795c189 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/ndarray.native.js @@ -20,9 +20,7 @@ // MODULES // -var minViewBufferIndex = require( '@stdlib/strided/base/min-view-buffer-index' ); -var offsetView = require( '@stdlib/strided/base/offset-view' ); -var addon = require( './dnannsumpw.native.js' ); +var addon = require( './../src/addon.node' ); // MAIN // @@ -32,10 +30,10 @@ var addon = require( './dnannsumpw.native.js' ); * * @param {PositiveInteger} N - number of indexed elements * @param {Float64Array} x - input array -* @param {integer} strideX - `x` stride length +* @param {integer} strideX - `x` index increment * @param {NonNegativeInteger} offsetX - `x` starting index * @param {Float64Array} out - output array -* @param {integer} strideOut - `out` stride length +* @param {integer} strideOut - `out` index increment * @param {NonNegativeInteger} offsetOut - `out` starting index * @returns {Float64Array} output array * @@ -49,17 +47,7 @@ var addon = require( './dnannsumpw.native.js' ); * // returns [ 5.0, 4 ] */ function dnannsumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ) { - var viewOut; - var viewX; - - offsetX = minViewBufferIndex( N, strideX, offsetX ); - if ( strideOut < 0 ) { - offsetOut += strideOut; - } - - viewX = offsetView( x, offsetX ); - viewOut = offsetView( out, offsetOut ); - addon( N, viewX, strideX, viewOut, strideOut ); + addon.ndarray( N, x, strideX, offsetX, out, strideOut, offsetOut ); return out; } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/sumpw.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/sumpw.js index be329386ceb..a6af41e561e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/sumpw.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/lib/sumpw.js @@ -86,12 +86,12 @@ function sumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ) { } ix = offsetX; io = offsetOut; - if ( N === 1 || strideX === 0 ) { + if ( strideX === 0 ) { if ( isnan( x[ ix ] ) ) { return out; } - out[ io ] += x[ ix ]; - out[ io+strideOut ] += 1; + out[ io ] += x[ ix ] * N; + out[ io+strideOut ] += N; return out; } if ( N < 8 ) { @@ -174,7 +174,7 @@ function sumpw( N, x, strideX, offsetX, out, strideOut, offsetOut ) { ix += strideX; } // Pairwise sum the accumulators: - s = ((s0+s1) + (s2+s3)) + ((s4+s5) + (s6+s7)); + s = ( (s0+s1) + (s2+s3) ) + ( (s4+s5) + (s6+s7) ); // Clean-up loop... for ( i; i < N; i++ ) { diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/manifest.json b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/manifest.json index c6e264b64d2..afff6bbbe3e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/manifest.json +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/manifest.json @@ -28,49 +28,54 @@ { "task": "build", "src": [ - "./src/dnannsumpw.c" + "./src/main.c" ], "include": [ "./include" ], - "libraries": [ - "-lm" - ], + "libraries": [], "libpath": [], "dependencies": [ "@stdlib/napi/export", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", - "@stdlib/napi/argv-strided-float64array" + "@stdlib/napi/argv-strided-float64array", + "@stdlib/math/base/assert/is-nan", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/stride2offset" ] }, { "task": "benchmark", "src": [ - "./src/dnannsumpw.c" + "./src/main.c" ], "include": [ "./include" ], - "libraries": [ - "-lm" - ], + "libraries": [], "libpath": [], - "dependencies": [] + "dependencies": [ + "@stdlib/math/base/assert/is-nan", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/stride2offset" + ] }, { "task": "examples", "src": [ - "./src/dnannsumpw.c" + "./src/main.c" ], "include": [ "./include" ], - "libraries": [ - "-lm" - ], + "libraries": [], "libpath": [], - "dependencies": [] + "dependencies": [ + "@stdlib/math/base/assert/is-nan", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/stride2offset" + ] } ] } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/addon.c b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/addon.c index 54705f129b1..aeeecbd027a 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/addon.c +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/addon.c @@ -17,6 +17,7 @@ */ #include "stdlib/blas/ext/base/dnannsumpw.h" +#include "stdlib/blas/base/shared.h" #include "stdlib/napi/export.h" #include "stdlib/napi/argv.h" #include "stdlib/napi/argv_int64.h" @@ -38,7 +39,7 @@ static napi_value addon( napi_env env, napi_callback_info info ) { STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, X, N, strideX, argv, 1 ); STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, Out, 2, strideOut, argv, 3 ); - int64_t io; + int io; if ( strideOut < 0 ) { io = -strideOut; } @@ -47,11 +48,37 @@ static napi_value addon( napi_env env, napi_callback_info info ) { } double *out = Out; - int64_t n; - out[ io ] = stdlib_strided_dnannsumpw( N, X, strideX, &n ); + CBLAS_INT n; + out[ io ] = API_SUFFIX(stdlib_strided_dnannsumpw)( N, X, strideX, &n ); out[ io + strideOut ] = (double)n; return NULL; } -STDLIB_NAPI_MODULE_EXPORT_FCN( addon ) +/** +* Receives JavaScript callback invocation data. +* +* @param env environment under which the function is invoked +* @param info callback data +* @return Node-API value +*/ +static napi_value addon_method( napi_env env, napi_callback_info info ) { + STDLIB_NAPI_ARGV( env, info, argv, argc, 7 ); + STDLIB_NAPI_ARGV_INT64( env, N, argv, 0 ); + STDLIB_NAPI_ARGV_INT64( env, strideX, argv, 2 ); + STDLIB_NAPI_ARGV_INT64( env, offsetX, argv, 3 ); + STDLIB_NAPI_ARGV_INT64( env, strideOut, argv, 5 ); + STDLIB_NAPI_ARGV_INT64( env, offsetOut, argv, 6 ); + STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, X, N, strideX, argv, 1 ); + STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, Out, 2, strideOut, argv, 4 ); + + int io = offsetOut; + double *out = Out; + CBLAS_INT n; + out[ io ] = API_SUFFIX(stdlib_strided_dnannsumpw_ndarray)( N, X, strideX, offsetX, &n ); + out[ io+strideOut ] = (double)n; + + return NULL; +} + +STDLIB_NAPI_MODULE_EXPORT_FCN_WITH_METHOD( addon, "ndarray", addon_method ) diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/dnannsumpw.c b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/main.c similarity index 52% rename from lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/dnannsumpw.c rename to lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/main.c index 575e1df464a..e64381bdf4e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/dnannsumpw.c +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/src/main.c @@ -17,25 +17,28 @@ */ #include "stdlib/blas/ext/base/dnannsumpw.h" -#include +#include "stdlib/strided/base/stride2offset.h" +#include "stdlib/math/base/assert/is_nan.h" +#include "stdlib/blas/base/shared.h" /** * Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation. * -* @param N number of indexed elements -* @param X input array -* @param stride stride length -* @param n pointer for storing the number of non-NaN elements -* @return output value +* @param N number of indexed elements +* @param X input array +* @param strideX index increment +* @param offsetX starting index +* @param n number of non-NaN elements +* @return output value */ -static double sumpw( const int64_t N, const double *X, const int64_t stride, int64_t *n ) { - double *xp1; - double *xp2; +static double API_SUFFIX(stdlib_strided_sumpw)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n ) { + double sum1; + double sum2; double sum; - int64_t ix; - int64_t M; - int64_t m; - int64_t i; + CBLAS_INT ix; + CBLAS_INT M; + CBLAS_INT m; + CBLAS_INT i; double s0; double s1; double s2; @@ -44,23 +47,23 @@ static double sumpw( const int64_t N, const double *X, const int64_t stride, int double s5; double s6; double s7; + CBLAS_INT n1; + CBLAS_INT n2; double v; + sum = 0.0; + *n = 0; if ( N <= 0 ) { - return 0.0; + return sum; } - if ( N == 1 || stride == 0 ) { - v = X[ 0 ]; - if ( v == v ) { - *n += 1; - return v; + ix = offsetX; + if ( strideX == 0 ) { + if ( stdlib_base_is_nan( X[ ix ]) ) { + return sum; } - return 0.0; - } - if ( stride < 0 ) { - ix = (1-N) * stride; - } else { - ix = 0; + sum = X[ ix ] * N; + *n += N; + return sum; } if ( N < 8 ) { // Use simple summation... @@ -71,7 +74,7 @@ static double sumpw( const int64_t N, const double *X, const int64_t stride, int sum += v; *n += 1; } - ix += stride; + ix += strideX; } return sum; } @@ -94,52 +97,52 @@ static double sumpw( const int64_t N, const double *X, const int64_t stride, int s0 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s1 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s2 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s3 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s4 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s5 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s6 += v; *n += 1; } - ix += stride; + ix += strideX; v = X[ ix ]; if ( v == v ) { s7 += v; *n += 1; } - ix += stride; + ix += strideX; } // Pairwise sum the accumulators: - sum = ((s0+s1) + (s2+s3)) + ((s4+s5) + (s6+s7)); + sum = ( (s0+s1) + (s2+s3) ) + ( (s4+s5) + (s6+s7) ); // Clean-up loop... for (; i < N; i++ ) { @@ -148,21 +151,19 @@ static double sumpw( const int64_t N, const double *X, const int64_t stride, int sum += v; *n += 1; } - ix += stride; + ix += strideX; } return sum; } // Recurse by dividing by two, but avoiding non-multiples of unroll factor... m = N / 2; m -= m % 8; - if ( stride < 0 ) { - xp1 = (double *)X + ( (m-N)*stride ); - xp2 = (double *)X; - } else { - xp1 = (double *)X; - xp2 = (double *)X + ( m*stride ); - } - return sumpw( m, xp1, stride, n ) + sumpw( N-m, xp2, stride, n ); + n1 = 0; + n2 = 0; + sum1 = API_SUFFIX(stdlib_strided_sumpw)( m, X, strideX, ix, &n1 ); + sum2 = API_SUFFIX(stdlib_strided_sumpw)( N-m, X, strideX, ix+(m*strideX), &n2 ); + *n += n1 + n2; + return sum1 + sum2; } /** @@ -176,13 +177,35 @@ static double sumpw( const int64_t N, const double *X, const int64_t stride, int * * - Higham, Nicholas J. 1993. "The Accuracy of Floating Point Summation." _SIAM Journal on Scientific Computing_ 14 (4): 783–99. doi:[10.1137/0914050](https://doi.org/10.1137/0914050). * -* @param N number of indexed elements -* @param X input array -* @param stride stride length -* @param n pointer for storing the number of non-NaN elements -* @return output value +* @param N number of indexed elements +* @param X input array +* @param strideX stride length +* @param n number of non-NaN elements +* @return output value */ -double stdlib_strided_dnannsumpw( const int64_t N, const double *X, const int64_t stride, int64_t *n ) { - *n = 0; - return sumpw( N, X, stride, n ); +double API_SUFFIX(stdlib_strided_dnannsumpw)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, CBLAS_INT *n ) { + CBLAS_INT ox = stdlib_strided_stride2offset( N, strideX ); + return API_SUFFIX(stdlib_strided_dnannsumpw_ndarray)( N, X, strideX, ox, n ); +} + +/** +* Computes the sum of double-precision floating-point strided array elements, ignoring `NaN` values and using pairwise summation and alternative indexing semantics. +* +* ## Method +* +* - This implementation uses pairwise summation, which accrues rounding error `O(log2 N)` instead of `O(N)`. The recursion depth is also `O(log2 N)`. +* +* ## References +* +* - Higham, Nicholas J. 1993. "The Accuracy of Floating Point Summation." _SIAM Journal on Scientific Computing_ 14 (4): 783–99. doi:[10.1137/0914050](https://doi.org/10.1137/0914050). +* +* @param N number of indexed elements +* @param X input array +* @param strideX index increment +* @param offsetX starting index +* @param n number of non-NaN elements +* @return output value +*/ +double API_SUFFIX(stdlib_strided_dnannsumpw_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, CBLAS_INT *n ) { + return API_SUFFIX(stdlib_strided_sumpw)( N, X, strideX, offsetX, n ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.js index 67bab782e80..8f81d9232b0 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.js @@ -228,7 +228,7 @@ tape( 'the function supports negative `stride` parameters', function test( t ) { t.end(); }); -tape( 'if provided a `stride` parameter equal to `0`, the function returns a sum equal to the first element', function test( t ) { +tape( 'if provided a `stride` parameter equal to `0`, the function returns the sum of the first element repeated N times', function test( t ) { var expected; var out; var x; @@ -239,7 +239,7 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns a sum out = new Float64Array( 2 ); v = dnannsumpw( x.length, x, 0, out, 1 ); - expected = new Float64Array( [ 1.0, 1.0 ] ); + expected = new Float64Array( [ 5.0, 5.0 ] ); t.deepEqual( v, expected, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.native.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.native.js index 4861b86c57d..003d044b084 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.native.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.dnannsumpw.native.js @@ -237,7 +237,7 @@ tape( 'the function supports negative `stride` parameters', opts, function test( t.end(); }); -tape( 'if provided a `stride` parameter equal to `0`, the function returns a sum equal to the first element', opts, function test( t ) { +tape( 'if provided a `stride` parameter equal to `0`, the function returns the sum of the first element repeated N times', opts, function test( t ) { var expected; var out; var x; @@ -248,7 +248,7 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns a sum out = new Float64Array( 2 ); v = dnannsumpw( x.length, x, 0, out, 1 ); - expected = new Float64Array( [ 1.0, 1.0 ] ); + expected = new Float64Array( [ 5.0, 5.0 ] ); t.deepEqual( v, expected, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.js index b6cf906bfc3..940a884bacb 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.js @@ -228,7 +228,7 @@ tape( 'the function supports a negative `stride` parameter', function test( t ) t.end(); }); -tape( 'if provided a `stride` parameter equal to `0`, the function returns the first indexed element', function test( t ) { +tape( 'if provided a `stride` parameter equal to `0`, the function returns the sum of the first element repeated N times', function test( t ) { var expected; var out; var x; @@ -239,7 +239,7 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns the f out = new Float64Array( 2 ); v = dnannsumpw( x.length, x, 0, 0, out, 1, 0 ); - expected = new Float64Array( [ 1.0, 1.0 ] ); + expected = new Float64Array( [ 5.0, 5.0 ] ); t.deepEqual( v, expected, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.native.js b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.native.js index dc96f01a09b..ed07ad90292 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/ext/base/dnannsumpw/test/test.ndarray.native.js @@ -237,7 +237,7 @@ tape( 'the function supports a negative `stride` parameter', opts, function test t.end(); }); -tape( 'if provided a `stride` parameter equal to `0`, the function returns the first indexed element', opts, function test( t ) { +tape( 'if provided a `stride` parameter equal to `0`, the function returns the sum of the first element repeated N times', opts, function test( t ) { var expected; var out; var x; @@ -248,7 +248,7 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns the f out = new Float64Array( 2 ); v = dnannsumpw( x.length, x, 0, 0, out, 1, 0 ); - expected = new Float64Array( [ 1.0, 1.0 ] ); + expected = new Float64Array( [ 5.0, 5.0 ] ); t.deepEqual( v, expected, 'returns expected value' ); t.end();