diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/README.md b/lib/node_modules/@stdlib/blas/base/dnrm2/README.md index d286446a1fe8..c4a6f6e72934 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/README.md +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/README.md @@ -91,7 +91,7 @@ var z = dnrm2( 4, x1, 2 ); // returns 5.0 ``` -If either `N` or `stride` is less than or equal to `0`, the function returns `0`. +If `N` is less than or equal to `0`, the function returns `0`. #### dnrm2.ndarray( N, x, stride, offset ) @@ -207,6 +207,28 @@ The function accepts the following arguments: double c_dnrm2( const CBLAS_INT N, const double *X, const CBLAS_INT stride ); ``` +#### c_dnrm2_ndarray( N, \*X, stride, offset ) + +Computes the L2-norm of a double-precision floating-point vector using alternative indexing semantics. + +```c +const double x[] = { 1.0, -2.0, 2.0 }; + +double v = c_dnrm2( 3, x, -1, 2 ); +// returns 3.0 +``` + +The function accepts the following arguments: + +- **N**: `[in] CBLAS_INT` number of indexed elements. +- **X**: `[in] double*` input array. +- **stride**: `[in] CBLAS_INT` index increment for `X`. +- **offset**: `[in] CBLAS_INT` starting index for `X`. + +```c +double c_dnrm2_ndarray( const CBLAS_INT N, const double *X, const CBLAS_INT stride, const CBLAS_INT offset ); +``` + @@ -244,6 +266,12 @@ int main( void ) { // Print the result: printf( "L2-norm: %lf\n", l2 ); + + // Compute the L2-norm: + l2 = c_dnrm2_ndarray( N, x, -strideX, N-1 ); + + // Print the result: + printf( "L2-norm: %lf\n", l2 ); } ``` diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/benchmark/c/benchmark.length.c b/lib/node_modules/@stdlib/blas/base/dnrm2/benchmark/c/benchmark.length.c index 5d648dd88568..d6d4413fee1c 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/benchmark/c/benchmark.length.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/benchmark/c/benchmark.length.c @@ -94,7 +94,7 @@ 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 ]; double z; @@ -120,6 +120,39 @@ 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 ]; + double z; + double t; + int i; + + for ( i = 0; i < len; i++ ) { + x[ i ] = ( rand_double() * 20000.0 ) - 10000.0; + } + z = 0.0; + t = tic(); + for ( i = 0; i < iterations; i++ ) { + z = c_dnrm2_ndarray( len, x, 1, 0 ); + if ( z != z ) { + printf( "should not return NaN\n" ); + break; + } + } + elapsed = tic() - t; + if ( z != z ) { + printf( "should not return NaN\n" ); + } + return elapsed; +} + /** * Main execution sequence. */ @@ -142,7 +175,14 @@ 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 ( 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/base/dnrm2/docs/repl.txt b/lib/node_modules/@stdlib/blas/base/dnrm2/docs/repl.txt index 2bec3739d6b9..3e12a5e30fd1 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/docs/repl.txt +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/docs/repl.txt @@ -8,7 +8,7 @@ Indexing is relative to the first index. To introduce an offset, use a typed array view. - If `N <= 0` or `stride <= 0`, the function returns `0`. + If `N <= 0`, the function returns `0`. Parameters ---------- diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/examples/c/example.c b/lib/node_modules/@stdlib/blas/base/dnrm2/examples/c/example.c index 6df2de1d7d27..9b577f98c418 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/examples/c/example.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/examples/c/example.c @@ -34,4 +34,10 @@ int main( void ) { // Print the result: printf( "L2-norm: %lf\n", l2 ); + + // Compute the L2-norm: + l2 = c_dnrm2_ndarray( N, x, -strideX, N-1 ); + + // Print the result: + printf( "L2-norm: %lf\n", l2 ); } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/include/stdlib/blas/base/dnrm2.h b/lib/node_modules/@stdlib/blas/base/dnrm2/include/stdlib/blas/base/dnrm2.h index 88eae88f0ae3..1cf316fe2d80 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/include/stdlib/blas/base/dnrm2.h +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/include/stdlib/blas/base/dnrm2.h @@ -36,6 +36,11 @@ extern "C" { */ double API_SUFFIX(c_dnrm2)( const CBLAS_INT N, const double *X, const CBLAS_INT stride ); +/** +* Computes the L2-norm of a double-precision floating-point vector using alternative indexing semantics. +*/ +double API_SUFFIX(c_dnrm2_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT stride, const CBLAS_INT offset ); + #ifdef __cplusplus } #endif diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.js b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.js index e215ed0e6c05..b602fe09f7d3 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.js @@ -20,9 +20,8 @@ // MODULES // -var sqrt = require( '@stdlib/math/base/special/sqrt' ); -var abs = require( '@stdlib/math/base/special/abs' ); -var pow = require( '@stdlib/math/base/special/pow' ); +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -32,7 +31,7 @@ var pow = require( '@stdlib/math/base/special/pow' ); * * @param {PositiveInteger} N - number of indexed elements * @param {Float64Array} x - input array -* @param {PositiveInteger} stride - stride length +* @param {integer} stride - stride length * @returns {number} L2-norm * * @example @@ -44,32 +43,8 @@ var pow = require( '@stdlib/math/base/special/pow' ); * // returns 3.0 */ function dnrm2( N, x, stride ) { - var scale; - var ssq; - var ax; - var i; - - if ( N <= 0 || stride <= 0 ) { - return 0.0; - } - if ( N === 1 ) { - return abs( x[ 0 ] ); - } - scale = 0.0; - ssq = 1.0; - N *= stride; - for ( i = 0; i < N; i += stride ) { - if ( x[ i ] !== 0.0 ) { - ax = abs( x[ i ] ); - if ( scale < ax ) { - ssq = 1.0 + ( ssq * pow( scale/ax, 2 ) ); - scale = ax; - } else { - ssq += pow( ax/scale, 2 ); - } - } - } - return scale * sqrt( ssq ); + var ox = stride2offset( N, stride ); + return ndarray( N, x, stride, ox ); } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.native.js b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.native.js index 373d55e877ba..faf62bd4eab1 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.native.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/dnrm2.native.js @@ -30,7 +30,7 @@ var addon = require( './../src/addon.node' ); * * @param {PositiveInteger} N - number of indexed elements * @param {Float64Array} x - input array -* @param {PositiveInteger} stride - stride length +* @param {integer} stride - stride length * @returns {number} L2-norm * * @example diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.js b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.js index 4061194670cb..bbc2db376bfb 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2020 The Stdlib Authors. +* Copyright (c) 2023 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,19 @@ // MODULES // -var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var FLOAT64_MAX = require( '@stdlib/constants/float64/max' ); var abs = require( '@stdlib/math/base/special/abs' ); -var pow = require( '@stdlib/math/base/special/pow' ); +var abs2 = require( '@stdlib/math/base/special/abs2' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); + + +// VARIABLES // + +// Blue's scaling constants: +var tsml = 1.4916681462400413E-154; +var tbig = 1.9979190722022350E+146; +var ssml = 4.4989137945431964E+161; +var sbig = 1.1113793747425387E-162; // MAIN // @@ -41,12 +51,18 @@ var pow = require( '@stdlib/math/base/special/pow' ); * * var x = new Float64Array( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] ); * -* var out = dnrm2( 4, x, 2, 1 ); +* var z = dnrm2( 4, x, 2, 1 ); * // returns 5.0 */ function dnrm2( N, x, stride, offset ) { - var scale; - var ssq; + var notbig; + var sumsq; + var abig; + var amed; + var asml; + var ymax; + var ymin; + var scl; var ax; var ix; var i; @@ -54,25 +70,64 @@ function dnrm2( N, x, stride, offset ) { if ( N <= 0 ) { return 0.0; } - if ( N === 1 ) { - return abs( x[ offset ] ); - } ix = offset; - scale = 0.0; - ssq = 1.0; + + // Initialize loop values for accumulation: + notbig = true; + + sumsq = 0.0; + abig = 0.0; + amed = 0.0; + asml = 0.0; + scl = 1.0; + + // Compute the sum of squares using 3 accumulators--`abig` (sum of squares scaled down to avoid overflow), `asml` (sum of squares scaled up to avoid underflow), `amed` (sum of squares that do not require scaling)--and thresholds and multipliers--`tbig` (values bigger than this are scaled down by `sbig`) and `tsml` (values smaller than this are scaled up by `ssml`)... for ( i = 0; i < N; i++ ) { - if ( x[ ix ] !== 0.0 ) { - ax = abs( x[ ix ] ); - if ( scale < ax ) { - ssq = 1.0 + ( ssq * pow( scale/ax, 2 ) ); - scale = ax; - } else { - ssq += pow( ax/scale, 2 ); + ax = abs( x[ ix ] ); + if ( ax > tbig ) { + abig += abs2( ax * sbig ); + notbig = false; + } else if ( ax < tsml ) { + if ( notbig ) { + asml += abs2( ax * ssml ); } + } else { + amed += ( ax * ax ); } ix += stride; } - return scale * sqrt( ssq ); + // Combine `abig` and `amed` or `amed` and `asml` if more than one accumulator was used... + if ( abig > 0.0 ) { + // Combine `abig` and `amed` if `abig` > 0... + if ( amed > 0.0 || ( amed > FLOAT64_MAX ) || ( amed !== amed ) ) { + abig += ( ( amed * sbig ) * sbig ); + } + scl = 1.0 / sbig; + sumsq = abig; + } else if ( asml > 0.0 ) { + // Combine `amed` and `asml` if `asml` > 0... + if ( amed > 0.0 || amed > FLOAT64_MAX || ( amed !== amed ) ) { + amed = sqrt( amed ); + asml = sqrt( asml ) / ssml; + if ( asml > amed ) { + ymin = amed; + ymax = asml; + } else { + ymin = asml; + ymax = amed; + } + scl = 1.0; + sumsq = ( ymax * ymax ) * ( 1.0 + abs2( ymin / ymax ) ); + } else { + scl = 1.0 / ssml; + sumsq = asml; + } + } else { + // All values are mid-range... + scl = 1.0; + sumsq = amed; + } + return sqrt( sumsq ) * scl; } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.native.js b/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.native.js index 12b25953b397..d8a3ee8d89a8 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/lib/ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/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( './dnrm2.native.js' ); +var addon = require( './../src/addon.node' ); // MAIN // @@ -45,13 +43,7 @@ var addon = require( './dnrm2.native.js' ); * // returns 5.0 */ function dnrm2( N, x, stride, offset ) { - var view; - offset = minViewBufferIndex( N, stride, offset ); - if ( stride < 0 ) { - stride *= -1; - } - view = offsetView( x, offset ); - return addon( N, view, stride ); + return addon.ndarray( N, x, stride, offset ); } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/manifest.json b/lib/node_modules/@stdlib/blas/base/dnrm2/manifest.json index 33d4c1d48f44..cd98f1b28677 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/manifest.json +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/manifest.json @@ -44,8 +44,9 @@ "libraries": [], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", @@ -58,7 +59,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -70,8 +72,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, { @@ -80,7 +84,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -92,8 +97,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, @@ -114,8 +121,9 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", @@ -139,7 +147,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, { @@ -159,7 +168,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, @@ -179,8 +189,9 @@ "libraries": [], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", @@ -193,7 +204,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -205,8 +217,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, { @@ -215,7 +229,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -227,8 +242,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, @@ -248,8 +265,9 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", @@ -272,7 +290,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, { @@ -291,7 +310,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, @@ -312,8 +332,9 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", @@ -337,7 +358,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, { @@ -357,7 +379,8 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared" + "@stdlib/blas/base/shared", + "@stdlib/strided/base/min-view-buffer-index" ] }, @@ -367,7 +390,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -377,15 +401,17 @@ ], "libpath": [], "dependencies": [ - "@stdlib/blas/base/shared", "@stdlib/napi/export", + "@stdlib/blas/base/shared", + "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", + "@stdlib/math/base/special/sqrt", + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset", "@stdlib/napi/argv", "@stdlib/napi/argv-int64", "@stdlib/napi/argv-strided-float64array", - "@stdlib/napi/create-double", - "@stdlib/math/base/special/abs", - "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/napi/create-double" ] }, { @@ -394,7 +420,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -406,8 +433,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, { @@ -416,7 +445,8 @@ "blas": "", "wasm": false, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -428,8 +458,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] }, @@ -439,7 +471,8 @@ "blas": "", "wasm": true, "src": [ - "./src/dnrm2.c" + "./src/dnrm2.c", + "./src/dnrm2_ndarray.c" ], "include": [ "./include" @@ -451,8 +484,10 @@ "dependencies": [ "@stdlib/blas/base/shared", "@stdlib/math/base/special/abs", + "@stdlib/math/base/special/abs2", "@stdlib/math/base/special/sqrt", - "@stdlib/math/base/special/pow" + "@stdlib/constants/float64/max", + "@stdlib/strided/base/stride2offset" ] } ] diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/addon.c b/lib/node_modules/@stdlib/blas/base/dnrm2/src/addon.c index 5559035460e6..b09d97ab1c6d 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/src/addon.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/addon.c @@ -35,10 +35,27 @@ static napi_value addon( napi_env env, napi_callback_info info ) { STDLIB_NAPI_ARGV( env, info, argv, argc, 3 ); STDLIB_NAPI_ARGV_INT64( env, N, argv, 0 ); - STDLIB_NAPI_ARGV_INT64( env, strideX, argv, 2 ); - STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, X, N, strideX, argv, 1 ); - STDLIB_NAPI_CREATE_DOUBLE( env, API_SUFFIX(c_dnrm2)( N, X, strideX ), v ); + STDLIB_NAPI_ARGV_INT64( env, stride, argv, 2 ); + STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, X, N, stride, argv, 1 ); + STDLIB_NAPI_CREATE_DOUBLE( env, API_SUFFIX(c_dnrm2)( N, X, stride ), v ); return v; } -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, 4 ); + STDLIB_NAPI_ARGV_INT64( env, N, argv, 0 ); + STDLIB_NAPI_ARGV_INT64( env, stride, argv, 2 ); + STDLIB_NAPI_ARGV_INT64( env, offset, argv, 3 ); + STDLIB_NAPI_ARGV_STRIDED_FLOAT64ARRAY( env, X, N, stride, argv, 1 ); + STDLIB_NAPI_CREATE_DOUBLE( env, API_SUFFIX(c_dnrm2_ndarray)( N, X, stride, offset ), v ); + return v; +} + +STDLIB_NAPI_MODULE_EXPORT_FCN_WITH_METHOD( addon, "ndarray", addon_method ) diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.c b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.c index a15dddf7bac6..74569f415334 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.c @@ -18,9 +18,7 @@ #include "stdlib/blas/base/dnrm2.h" #include "stdlib/blas/base/shared.h" -#include "stdlib/math/base/special/abs.h" -#include "stdlib/math/base/special/sqrt.h" -#include "stdlib/math/base/special/pow.h" +#include "stdlib/strided/base/stride2offset.h" /** * Computes the L2-norm of a double-precision floating-point vector. @@ -31,29 +29,6 @@ * @return L2-norm */ double API_SUFFIX(c_dnrm2)( const CBLAS_INT N, const double *X, const CBLAS_INT stride ) { - double scale; - double ssq; - double ax; - CBLAS_INT i; - - if ( N <= 0 || stride <= 0 ) { - return 0.0; - } - if ( N == 1 ) { - return stdlib_base_abs( X[ 0 ] ); - } - scale = 0.0; - ssq = 1.0; - for ( i = 0; i < N*stride; i += stride ) { - if ( X[ i ] != 0.0 ) { - ax = stdlib_base_abs( X[ i ] ); - if ( scale < ax ) { - ssq = 1.0 + ( ssq * stdlib_base_pow( scale/ax, 2 ) ); - scale = ax; - } else { - ssq += stdlib_base_pow( ax/scale, 2 ); - } - } - } - return scale * stdlib_base_sqrt( ssq ); + CBLAS_INT ox = stdlib_strided_stride2offset( N, stride ); + return API_SUFFIX(c_dnrm2_ndarray)( N, X, stride, ox ); } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.f b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.f index d3b24c19fd1c..19f115a19b16 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.f +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2.f @@ -52,6 +52,20 @@ !< double precision function dnrm2( N, dx, stride ) implicit none + ! .. + ! Define a kind parameter for double-precision: + integer, parameter :: wp = kind( 1.0d0 ) + ! .. + ! Define constants: + real( wp ), parameter :: zero = 0.0_wp + real( wp ), parameter :: one = 1.0_wp + real( wp ), parameter :: maxN = huge( 0.0_wp ) + ! .. + ! Blue's scaling constants: + real( wp ), parameter :: tsml = 1.4916681462400413e-154_wp + real( wp ), parameter :: tbig = 1.9979190722022350e146_wp + real( wp ), parameter :: ssml = 4.4989137945431964e161_wp + real( wp ), parameter :: sbig = 1.1113793747425387e-162_wp !.. ! Scalar arguments: integer :: N, stride @@ -60,35 +74,85 @@ double precision function dnrm2( N, dx, stride ) double precision, intent(in) :: dx(*) ! .. ! Local scalars: - double precision :: ax, scale, ssq - integer :: i + integer :: i, ix + logical :: notbig + real( wp ) :: abig, amed, asml, ax, scl, sumsq, ymax, ymin ! .. ! Intrinsic functions: intrinsic dabs, dsqrt ! .. dnrm2 = 0.0d0 ! .. - if ( N <= 0 .OR. stride <= 0 ) then + if ( N <= 0 ) then return end if - !.. - if ( N == 1 ) then - dnrm2 = dabs( dx( 1 ) ) - return + ! .. + scl = one + sumsq = zero + ! .. + ! Compute the sum of squares in 3 accumulators: + ! abig -- sums of squares scaled down to avoid overflow + ! asml -- sums of squares scaled up to avoid underflow + ! amed -- sums of squares that do not require scaling + ! Thresholds and multipliers: + ! tbig -- values bigger than this are scaled down by sbig + ! tsml -- values smaller than this are scaled up by ssml + ! .. + notbig = .true. + asml = zero + amed = zero + abig = zero + ix = 1 + if ( stride < 0 ) then + ix = 1 - ( N - 1 ) * stride end if ! .. - scale = 0.0d0 - ssq = 1.0d0 - do i = 1, 1+((N-1)*stride), stride - if ( dx( i ) /= 0.0d0 ) then - ax = dabs( dx( i ) ) - if ( scale < ax ) then - ssq = 1.0d0 + ( ssq * (scale/ax)**2 ) - scale = ax - else - ssq = ssq + (ax/scale)**2 + do i = 1, N + ax = abs( dx( ix ) ) + if ( ax > tbig ) then + abig = abig + ( ax * sbig )**2 + notbig = .false. + else if ( ax < tsml ) then + if ( notbig ) then + asml = asml + ( ax * ssml )**2 end if + else + amed = amed + ax**2 end if + ix = ix + stride end do - dnrm2 = scale * dsqrt( ssq ) + ! .. + ! Combine abig and amed or amed and asml if more than one accumulator was used: + if ( abig > zero ) then + ! Combine abig and amed if abig > 0... + if ( ( amed > zero ) .or. ( amed > maxN ) .or. ( amed /= amed ) ) then + abig = abig + ( amed * sbig ) * sbig + end if + scl = one / sbig + sumsq = abig + else if ( asml > zero ) then + ! Combine amed and asml if asml > 0... + if ( ( amed > zero ) .or. ( amed > maxN ) .or. ( amed /= amed ) ) then + amed = sqrt( amed ) + asml = sqrt( asml ) / ssml + if ( asml > amed ) then + ymin = amed + ymax = asml + else + ymin = asml + ymax = amed + end if + scl = one + sumsq = ymax**2 * ( one + ( ymin / ymax )**2 ) + else + scl = one / ssml + sumsq = asml + end if + else + ! All values are mid-range... + scl = one + sumsq = amed + end if + dnrm2 = scl * sqrt( sumsq ) + return end function dnrm2 diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_cblas.c b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_cblas.c index 9c4cbc66e0aa..65d94b77a2c5 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_cblas.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_cblas.c @@ -19,6 +19,7 @@ #include "stdlib/blas/base/dnrm2.h" #include "stdlib/blas/base/dnrm2_cblas.h" #include "stdlib/blas/base/shared.h" +#include "stdlib/strided/base/min_view_buffer_index.h" /** * Computes the L2-norm of a double-precision floating-point vector. @@ -29,5 +30,27 @@ * @return L2-norm */ double API_SUFFIX(c_dnrm2)( const CBLAS_INT N, const double *X, const CBLAS_INT stride ) { - return API_SUFFIX(cblas_dnrm2)( N, X, stride ); + CBLAS_INT sx = stride; + if ( sx < 0 ) { + sx = -sx; + } + return API_SUFFIX(cblas_dnrm2)( N, X, sx ); +} + +/** +* Computes the L2-norm of a double-precision floating-point vector using alternative indexing semantics. +* +* @param N number of indexed elements +* @param X input array +* @param stride stride length +* @param offset starting index +* @return L2-norm +*/ +double API_SUFFIX(c_dnrm2_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT stride, const CBLAS_INT offset ) { + CBLAS_INT sx = stride; + if ( sx < 0 ) { + sx = -sx; + } + X += stdlib_strided_min_view_buffer_index( N, stride, offset ); // adjust array pointer + return API_SUFFIX(cblas_dnrm2)( N, X, sx ); } diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_f.c b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_f.c index 87c289eca6bb..41d93d21a989 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_f.c +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_f.c @@ -19,6 +19,7 @@ #include "stdlib/blas/base/dnrm2.h" #include "stdlib/blas/base/dnrm2_fortran.h" #include "stdlib/blas/base/shared.h" +#include "stdlib/strided/base/min_view_buffer_index.h" /** * Computes the L2-norm of a double-precision floating-point vector. @@ -33,3 +34,19 @@ double API_SUFFIX(c_dnrm2)( const CBLAS_INT N, const double *X, const CBLAS_INT dnrm2sub( &N, X, &stride, &nrm2 ); return nrm2; } + +/** +* Computes the L2-norm of a double-precision floating-point vector using alternative indexing semantics. +* +* @param N number of indexed elements +* @param X input array +* @param stride stride length +* @param offset starting index +* @return L2-norm +*/ +double API_SUFFIX(c_dnrm2_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT stride, const CBLAS_INT offset ) { + double nrm2; + X += stdlib_strided_min_view_buffer_index( N, stride, offset ); // adjust array pointer + dnrm2sub( &N, X, &stride, &nrm2 ); + return nrm2; +} diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_ndarray.c b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_ndarray.c new file mode 100644 index 000000000000..1063f8bd7689 --- /dev/null +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/src/dnrm2_ndarray.c @@ -0,0 +1,112 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "stdlib/blas/base/dnrm2.h" +#include "stdlib/blas/base/shared.h" +#include "stdlib/math/base/special/abs.h" +#include "stdlib/math/base/special/abs2.h" +#include "stdlib/math/base/special/sqrt.h" +#include "stdlib/constants/float64/max.h" +#include + +// Blue's scaling constants... +static const double tsml = 1.4916681462400413E-154; +static const double tbig = 1.9979190722022350E+146; +static const double ssml = 4.4989137945431964E+161; +static const double sbig = 1.1113793747425387E-162; + +/** +* Computes the L2-norm of a double-precision floating-point vector using alternative indexing semantics. +* +* @param N number of indexed elements +* @param X input array +* @param stride stride length +* @param offset starting index +* @return output value +*/ +double API_SUFFIX(c_dnrm2_ndarray)( const CBLAS_INT N, const double *X, const CBLAS_INT stride, const CBLAS_INT offset ) { + CBLAS_INT ix; + double sumsq; + bool notbig; + CBLAS_INT i; + double abig; + double amed; + double asml; + double ymax; + double ymin; + double scl; + double ax; + + if ( N <= 0 ) { + return 0.0; + } + ix = offset; + + // Compute the sum of squares using 3 accumulators--`abig` (sum of squares scaled down to avoid overflow), `asml` (sum of squares scaled up to avoid underflow), `amed` (sum of squares that do not require scaling)--and thresholds and multipliers--`tbig` (values bigger than this are scaled down by `sbig`) and `tsml` (values smaller than this are scaled up by `ssml`)... + notbig = true; + sumsq = 0.0; + abig = 0.0; + amed = 0.0; + asml = 0.0; + for ( i = 0; i < N; i++ ) { + ax = stdlib_base_abs( X[ ix ] ); + if ( ax > tbig ) { + abig += stdlib_base_abs2( ax * sbig ); + notbig = false; + } else if ( ax < tsml ) { + if ( notbig ) { + asml += stdlib_base_abs2( ax * ssml ); + } + } else { + amed += stdlib_base_abs2( ax ); + } + ix += stride; + } + // Combine `abig` and `amed` or `amed` and `asml` if more than one accumulator was used... + if ( abig > 0.0 ) { + // Combine `abig` and `amed` if `abig` > 0... + if ( amed > 0.0 || ( amed > STDLIB_CONSTANT_FLOAT64_MAX ) || ( amed != amed ) ) { + abig += ( amed * sbig ) * sbig; + } + scl = 1.0 / sbig; + sumsq = abig; + } else if ( asml > 0.0 ) { + // Combine `amed` and `asml` if `asml` > 0... + if ( amed > 0.0 || amed > STDLIB_CONSTANT_FLOAT64_MAX || ( amed != amed ) ) { + amed = stdlib_base_sqrt( amed ); + asml = stdlib_base_sqrt( asml ) / ssml; + if ( asml > amed ) { + ymin = amed; + ymax = asml; + } else { + ymin = asml; + ymax = amed; + } + scl = 1.0; + sumsq = stdlib_base_abs2( ymax ) * ( 1.0 + stdlib_base_abs2( ymin / ymax ) ); + } else { + scl = 1.0 / ssml; + sumsq = asml; + } + } else { + // All values are mid-range... + scl = 1.0; + sumsq = amed; + } + return stdlib_base_sqrt( sumsq ) * scl; +} diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.js b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.js index aa303af61d1e..22a6a4b1316c 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.js @@ -92,18 +92,24 @@ tape( 'the function supports a `stride` parameter', function test( t ) { t.end(); }); -tape( 'if provided a `stride` parameter less than or equal to `0`, the function returns `0`', function test( t ) { +tape( 'the function supports a negative `stride` parameter', function test( t ) { var x; var z; - x = new Float64Array( [ 1.0, -2.0, -4.0, 5.0, 3.0 ] ); - - z = dnrm2( x.length, x, 0 ); - t.strictEqual( z, 0.0, 'returns expected value' ); + x = new Float64Array([ + 1.0, // 3 + 2.0, + 2.0, // 2 + -7.0, + -2.0, // 1 + 3.0, + 4.0, // 0 + 2.0 + ]); - z = dnrm2( x.length, x, -1 ); - t.strictEqual( z, 0.0, 'returns expected value' ); + z = dnrm2( 4, x, -2 ); + t.strictEqual( z, 5.0, 'returns expected value' ); t.end(); }); diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.native.js b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.native.js index 822c56743fb3..9441031a1b28 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.native.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.dnrm2.native.js @@ -101,18 +101,24 @@ tape( 'the function supports a `stride` parameter', opts, function test( t ) { t.end(); }); -tape( 'if provided a `stride` parameter less than or equal to `0`, the function returns `0`', opts, function test( t ) { +tape( 'the function supports a negative `stride` parameter', opts, function test( t ) { var x; var z; - x = new Float64Array( [ 1.0, -2.0, -4.0, 5.0, 3.0 ] ); - - z = dnrm2( x.length, x, 0 ); - t.strictEqual( z, 0.0, 'returns expected value' ); + x = new Float64Array([ + 1.0, // 3 + 2.0, + 2.0, // 2 + -7.0, + -2.0, // 1 + 3.0, + 4.0, // 0 + 2.0 + ]); - z = dnrm2( x.length, x, -1 ); - t.strictEqual( z, 0.0, 'returns expected value' ); + z = dnrm2( 4, x, -2 ); + t.strictEqual( z, 5.0, 'returns expected value' ); t.end(); }); diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.js index 5f2bc2d22514..1962dcf9419e 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.js @@ -97,13 +97,13 @@ tape( 'the function supports a negative `stride` parameter', function test( t ) var z; x = new Float64Array([ - 1.0, // 0 + 1.0, // 3 2.0, - 2.0, // 1 + 2.0, // 2 -7.0, - -2.0, // 2 + -2.0, // 1 3.0, - 4.0, // 3 + 4.0, // 0 2.0 ]); diff --git a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.native.js b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.native.js index 9932d8c2e832..541af646c82e 100644 --- a/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/base/dnrm2/test/test.ndarray.native.js @@ -106,13 +106,13 @@ tape( 'the function supports a negative `stride` parameter', opts, function test var z; x = new Float64Array([ - 1.0, // 0 + 1.0, // 3 2.0, - 2.0, // 1 + 2.0, // 2 -7.0, - -2.0, // 2 + -2.0, // 1 3.0, - 4.0, // 3 + 4.0, // 0 2.0 ]);