diff --git a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/accessors.js b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/accessors.js index 2189c70e9c8a..c3eeb919f2ca 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/accessors.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/accessors.js @@ -20,7 +20,9 @@ // MODULES // +var isnan = require( '@stdlib/math/base/assert/is-nan' ); var floor = require( '@stdlib/math/base/special/floor' ); +var gindexOfGreaterThan = require( '@stdlib/blas/ext/base/gindex-of-greater-than' ).ndarray; // MAIN // @@ -50,11 +52,13 @@ var floor = require( '@stdlib/math/base/special/floor' ); function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { var xbuf; var get; + var idx; var mid; var lo; var hi; var v1; var v2; + var v; // Cache reference to array data: xbuf = x.data; @@ -65,6 +69,10 @@ function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { v1 = get( xbuf, offsetX ); v2 = get( xbuf, offsetX + ( ( N - 1 ) * strideX ) ); + // If either the first or last indexed element is NaN, we cannot determine the sort order, so fall back to a linear search... + if ( isnan( v1 ) || isnan( v2 ) ) { + return gindexOfGreaterThan( N, searchElement, xbuf, strideX, offsetX ); + } // Descending order: elements which are greater than the search element form a prefix, so only the first indexed element needs to be checked... if ( v1 >= v2 ) { if ( v1 > searchElement ) { @@ -77,7 +85,14 @@ function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { hi = N; while ( lo < hi ) { mid = lo + floor( ( hi - lo ) / 2 ); - if ( searchElement < get( xbuf, offsetX + ( mid * strideX ) ) ) { + v = get( xbuf, offsetX + ( mid * strideX ) ); + + // If we encounter a NaN, fall back to a linear search... + if ( isnan( v ) ) { + idx = gindexOfGreaterThan( N-lo, searchElement, xbuf, strideX, offsetX + ( lo * strideX ) ); + return ( idx < 0 ) ? idx : idx + lo; + } + if ( searchElement < v ) { hi = mid; } else { lo = mid + 1; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/ndarray.js index 38f777a247bd..75952d4b5791 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/lib/ndarray.js @@ -20,8 +20,10 @@ // MODULES // +var isnan = require( '@stdlib/math/base/assert/is-nan' ); var floor = require( '@stdlib/math/base/special/floor' ); var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +var gindexOfGreaterThan = require( '@stdlib/blas/ext/base/gindex-of-greater-than' ).ndarray; var accessors = require( './accessors.js' ); @@ -48,12 +50,14 @@ var accessors = require( './accessors.js' ); * // returns 3 */ function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { + var idx; var mid; var lo; var hi; var v1; var v2; var o; + var v; if ( N <= 0 ) { return -1; @@ -65,6 +69,10 @@ function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { v1 = x[ offsetX ]; v2 = x[ offsetX + ( ( N - 1 ) * strideX ) ]; + // If either the first or last indexed element is NaN, we cannot determine the sort order, so fall back to a linear search... + if ( isnan( v1 ) || isnan( v2 ) ) { + return gindexOfGreaterThan( N, searchElement, x, strideX, offsetX ); + } // Descending order: elements which are greater than the search element form a prefix, so only the first indexed element needs to be checked... if ( v1 >= v2 ) { if ( v1 > searchElement ) { @@ -77,7 +85,14 @@ function gindexOfGreaterThanSorted( N, searchElement, x, strideX, offsetX ) { hi = N; while ( lo < hi ) { mid = lo + floor( ( hi - lo ) / 2 ); - if ( searchElement < x[ offsetX + ( mid * strideX ) ] ) { + v = x[ offsetX + ( mid * strideX ) ]; + + // If we encounter a NaN, fall back to a linear search... + if ( isnan( v ) ) { + idx = gindexOfGreaterThan( N-lo, searchElement, x, strideX, offsetX + ( lo * strideX ) ); + return ( idx < 0 ) ? idx : idx + lo; + } + if ( searchElement < v ) { hi = mid; } else { lo = mid + 1; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.main.js b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.main.js index 95a9c0f21bf7..af0b769fe461 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.main.js @@ -468,3 +468,57 @@ tape( 'the function supports view offsets (descending order)', function test( t t.end(); }); + +tape( 'the function supports input arrays containing `NaN` values', function test( t ) { + var actual; + var x; + + x = [ 1.0, NaN, 3.0, 4.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = [ NaN, 1.0, 2.0, 3.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = [ 1.0, 2.0, 3.0, NaN ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 1, 'returns expected value' ); + + x = [ 3.0, NaN, 2.0, 1.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 0, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function supports input arrays containing `NaN` values (accessors)', function test( t ) { + var actual; + var x; + + x = toAccessorArray( [ 1.0, NaN, 3.0, 4.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = toAccessorArray( [ NaN, 1.0, 2.0, 3.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = toAccessorArray( [ 1.0, 2.0, 3.0, NaN ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 1, 'returns expected value' ); + + x = toAccessorArray( [ 3.0, NaN, 2.0, 1.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1 ); + t.strictEqual( actual, 0, 'returns expected value' ); + + t.end(); +}); diff --git a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.ndarray.js index 217b405fb9a0..f8f3208ef5c3 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gindex-of-greater-than-sorted/test/test.ndarray.js @@ -517,3 +517,57 @@ tape( 'the function supports an `x` offset (descending order) (accessors)', func t.end(); }); + +tape( 'the function supports input arrays containing `NaN` values', function test( t ) { + var actual; + var x; + + x = [ 1.0, NaN, 3.0, 4.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = [ NaN, 1.0, 2.0, 3.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = [ 1.0, 2.0, 3.0, NaN ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 1, 'returns expected value' ); + + x = [ 3.0, NaN, 2.0, 1.0 ]; + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 0, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function supports input arrays containing `NaN` values (accessors)', function test( t ) { + var actual; + var x; + + x = toAccessorArray( [ 1.0, NaN, 3.0, 4.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = toAccessorArray( [ NaN, 1.0, 2.0, 3.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 2, 'returns expected value' ); + + x = toAccessorArray( [ 1.0, 2.0, 3.0, NaN ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 1, 'returns expected value' ); + + x = toAccessorArray( [ 3.0, NaN, 2.0, 1.0 ] ); + + actual = gindexOfGreaterThanSorted( x.length, 1.5, x, 1, 0 ); + t.strictEqual( actual, 0, 'returns expected value' ); + + t.end(); +});