From 8494b39596b3291103ee8474e057864c04e0ef1e Mon Sep 17 00:00:00 2001 From: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> Date: Sat, 8 Feb 2025 17:07:14 +0000 Subject: [PATCH 1/2] feat: add accessor arrays support and refactor --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: na - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- type: pre_push_report description: Results of running various checks prior to pushing changes. report: - task: run_javascript_examples status: na - task: run_c_examples status: na - task: run_cpp_examples status: na - task: run_javascript_readme_examples status: na - task: run_c_benchmarks status: na - task: run_cpp_benchmarks status: na - task: run_fortran_benchmarks status: na - task: run_javascript_benchmarks status: na - task: run_julia_benchmarks status: na - task: run_python_benchmarks status: na - task: run_r_benchmarks status: na - task: run_javascript_tests status: na --- --- .../@stdlib/blas/ext/base/gsortins/README.md | 51 +- .../blas/ext/base/gsortins/docs/repl.txt | 36 +- .../ext/base/gsortins/docs/types/index.d.ts | 19 +- .../blas/ext/base/gsortins/docs/types/test.ts | 7 +- .../blas/ext/base/gsortins/examples/index.js | 27 +- .../blas/ext/base/gsortins/lib/accessors.js | 159 ++++++ .../blas/ext/base/gsortins/lib/main.js | 103 +--- .../blas/ext/base/gsortins/lib/ndarray.js | 54 +- .../blas/ext/base/gsortins/test/test.main.js | 436 +++++++++++++++- .../ext/base/gsortins/test/test.ndarray.js | 488 +++++++++++++++++- 10 files changed, 1170 insertions(+), 210 deletions(-) create mode 100644 lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/accessors.js diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/README.md b/lib/node_modules/@stdlib/blas/ext/base/gsortins/README.md index cfccda3d0947..0d0ef22eb2c5 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/README.md @@ -30,9 +30,9 @@ limitations under the License. var gsortins = require( '@stdlib/blas/ext/base/gsortins' ); ``` -#### gsortins( N, order, x, stride ) +#### gsortins( N, order, x, strideX ) -Sorts a strided array `x` using insertion sort. +Sorts a strided array using insertion sort. ```javascript var x = [ 1.0, -2.0, 3.0, -4.0 ]; @@ -46,17 +46,14 @@ The function has the following parameters: - **N**: number of indexed elements. - **order**: sort order. If `order < 0.0`, the input strided array is sorted in **decreasing** order. If `order > 0.0`, the input strided array is sorted in **increasing** order. If `order == 0.0`, the input strided array is left unchanged. - **x**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array]. -- **stride**: index increment. +- **stride**: stride length. -The `N` and `stride` parameters determine which elements in `x` are accessed at runtime. For example, to sort every other element +The `N` and stride parameters determine which elements in the strided array are accessed at runtime. For example, to sort every other element: ```javascript -var floor = require( '@stdlib/math/base/special/floor' ); - var x = [ 1.0, -2.0, 3.0, -4.0 ]; -var N = floor( x.length / 2 ); -gsortins( N, -1.0, x, 2 ); +gsortins( 2, -1.0, x, 2 ); // x => [ 3.0, -2.0, 1.0, -4.0 ] ``` @@ -64,23 +61,21 @@ Note that indexing is relative to the first index. To introduce an offset, use [ ```javascript var Float64Array = require( '@stdlib/array/float64' ); -var floor = require( '@stdlib/math/base/special/floor' ); // Initial array... var x0 = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); // Create an offset view... var x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element -var N = floor( x0.length/2 ); // Sort every other element... -gsortins( N, -1.0, x1, 2 ); +gsortins( 2, -1.0, x1, 2 ); // x0 => [ 1.0, 4.0, 3.0, 2.0 ] ``` -#### gsortins.ndarray( N, order, x, stride, offset ) +#### gsortins.ndarray( N, order, x, strideX, offsetX ) -Sorts a strided array `x` using insertion sort and alternative indexing semantics. +Sorts a strided array using insertion sort and alternative indexing semantics. ```javascript var x = [ 1.0, -2.0, 3.0, -4.0 ]; @@ -91,9 +86,9 @@ gsortins.ndarray( x.length, 1.0, x, 1, 0 ); The function has the following additional parameters: -- **offset**: starting index. +- **offsetX**: starting index. -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 access only the last three elements of `x` +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 access only the last three elements: ```javascript var x = [ 1.0, -2.0, 3.0, -4.0, 5.0, -6.0 ]; @@ -111,6 +106,7 @@ gsortins.ndarray( 3, 1.0, x, 1, x.length-3 ); ## Notes - If `N <= 0` or `order == 0.0`, both functions return `x` unchanged. +- Both functions support array-like objects having getter and setter accessors for array element access (e.g., [`@stdlib/array/base/accessor`][@stdlib/array/base/accessor]) - The algorithm distinguishes between `-0` and `+0`. When sorted in increasing order, `-0` is sorted before `+0`. When sorted in decreasing order, `-0` is sorted after `+0`. - The algorithm sorts `NaN` values to the end. When sorted in increasing order, `NaN` values are sorted last. When sorted in decreasing order, `NaN` values are sorted first. - The algorithm has space complexity `O(1)` and worst case time complexity `O(N^2)`. @@ -130,27 +126,12 @@ gsortins.ndarray( 3, 1.0, x, 1, x.length-3 ); ```javascript -var round = require( '@stdlib/math/base/special/round' ); -var randu = require( '@stdlib/random/base/randu' ); -var Float64Array = require( '@stdlib/array/float64' ); +var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); var gsortins = require( '@stdlib/blas/ext/base/gsortins' ); -var rand; -var sign; -var x; -var i; - -x = new Float64Array( 10 ); -for ( i = 0; i < x.length; i++ ) { - rand = round( randu()*100.0 ); - sign = randu(); - if ( sign < 0.5 ) { - sign = -1.0; - } else { - sign = 1.0; - } - x[ i ] = sign * rand; -} +var x = discreteUniform( 10, -100, 100, { + 'dtype': 'float64' +}); console.log( x ); gsortins( x.length, -1.0, x, -1 ); @@ -185,6 +166,8 @@ console.log( x ); [mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray +[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor + [@stdlib/blas/ext/base/dsortins]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/blas/ext/base/dsortins diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/repl.txt b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/repl.txt index 73f03c359ddf..db8e0ff1f56c 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/repl.txt +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/repl.txt @@ -1,9 +1,9 @@ -{{alias}}( N, order, x, stride ) +{{alias}}( N, order, x, strideX ) Sorts a strided array using insertion sort. - The `N` and `stride` parameters determine which elements in `x` are accessed - at runtime. + The `N` and stride parameters determine which elements in the strided arrays + are accessed at runtime. Indexing is relative to the first index. To introduce an offset, use typed array views. @@ -44,8 +44,8 @@ x: Array|TypedArray Input array. - stride: integer - Index increment for `x`. + strideX: integer + Stride length. Returns ------- @@ -59,28 +59,27 @@ > {{alias}}( x.length, 1, x, 1 ) [ -4.0, -2.0, 1.0, 3.0 ] - // Using `N` and `stride` parameters: + // Using `N` and stride parameters: > x = [ 1.0, -2.0, 3.0, -4.0 ]; - > var N = {{alias:@stdlib/math/base/special/floor}}( x.length / 2 ); - > {{alias}}( N, -1, x, 2 ) + > {{alias}}( 2, -1, x, 2 ) [ 3.0, -2.0, 1.0, -4.0 ] // Using view offsets: > var x0 = new {{alias:@stdlib/array/float64}}( [ 1.0, -2.0, 3.0, -4.0 ] ); > var x1 = new {{alias:@stdlib/array/float64}}( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); - > N = {{alias:@stdlib/math/base/special/floor}}( x0.length / 2 ); - > {{alias}}( N, 1, x1, 2 ) + > {{alias}}( 2, 1, x1, 2 ) [ -4.0, 3.0, -2.0 ] > x0 [ 1.0, -4.0, 3.0, -2.0 ] -{{alias}}.ndarray( N, order, x, stride, offset ) + +{{alias}}.ndarray( N, order, x, strideX, offsetX ) Sorts a strided array using insertion sort and alternative indexing 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, the offset parameter supports indexing semantics based on a starting + index. Parameters ---------- @@ -94,11 +93,11 @@ x: Array|TypedArray Input array. - stride: integer - Index increment for `x`. + strideX: integer + Stride length. - offset: integer - Starting index of `x`. + offsetX: integer + Starting index. Returns ------- @@ -114,8 +113,7 @@ // Using an index offset: > x = [ 1.0, -2.0, 3.0, -4.0 ]; - > var N = {{alias:@stdlib/math/base/special/floor}}( x.length / 2 ); - > {{alias}}.ndarray( N, 1, x, 2, 1 ) + > {{alias}}.ndarray( 2, 1, x, 2, 1 ) [ 1.0, -4.0, 3.0, -2.0 ] See Also diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/index.d.ts b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/index.d.ts index d3a96bbcbadf..6866bbe02c2f 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/index.d.ts @@ -20,7 +20,12 @@ /// -import { NumericArray } from '@stdlib/types/array'; +import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array'; + +/** +* Input array. +*/ +type InputArray = NumericArray | Collection | AccessorArrayLike; /** * Interface describing `gsortins`. @@ -32,7 +37,7 @@ interface Routine { * @param N - number of indexed elements * @param order - sort order * @param x - input array - * @param stride - stride length + * @param strideX - stride length * @returns `x` * * @example @@ -41,7 +46,7 @@ interface Routine { * gsortins( x.length, 1, x, 1 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ - ( N: number, order: number, x: NumericArray, stride: number ): NumericArray; + ( N: number, order: number, x: T, strideX: number ): T; /** * Sorts a strided array using insertion sort and alternative indexing semantics. @@ -49,8 +54,8 @@ interface Routine { * @param N - number of indexed elements * @param order - sort order * @param x - input array - * @param stride - stride length - * @param offset - starting index + * @param strideX - stride length + * @param offsetX - starting index * @returns `x` * * @example @@ -59,7 +64,7 @@ interface Routine { * gsortins.ndarray( x.length, 1, x, 1, 0 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ - ndarray( N: number, order: number, x: NumericArray, stride: number, offset: number ): NumericArray; + ndarray( N: number, order: number, x: T, strideX: number, offsetX: number ): T; } /** @@ -68,7 +73,7 @@ interface Routine { * @param N - number of indexed elements * @param order - sort order * @param x - input array -* @param stride - stride length +* @param strideX - stride length * @returns `x` * * @example diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/test.ts b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/test.ts index c8fd639035cc..87421a8dfdcd 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/test.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import gsortins = require( './index' ); @@ -25,7 +26,8 @@ import gsortins = require( './index' ); { const x = new Float64Array( 10 ); - gsortins( x.length, 1, x, 1 ); // $ExpectType NumericArray + gsortins( x.length, 1, x, 1 ); // $ExpectType Float64Array + gsortins( x.length, 1, new AccessorArray( x ), 1 ); // $ExpectType AccessorArray } // The compiler throws an error if the function is provided a first argument which is not a number... @@ -100,7 +102,8 @@ import gsortins = require( './index' ); { const x = new Float64Array( 10 ); - gsortins.ndarray( x.length, 1, x, 1, 0 ); // $ExpectType NumericArray + gsortins.ndarray( x.length, 1, x, 1, 0 ); // $ExpectType Float64Array + gsortins.ndarray( x.length, 1, new AccessorArray( x ), 1, 0 ); // $ExpectType AccessorArray } // The compiler throws an error if the `ndarray` method is provided a first argument which is not a number... diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/examples/index.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/examples/index.js index 49994f3a80a5..de670ea4bd7e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/examples/index.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/examples/index.js @@ -18,31 +18,12 @@ 'use strict'; -var round = require( '@stdlib/math/base/special/round' ); -var randu = require( '@stdlib/random/base/randu' ); -var Float64Array = require( '@stdlib/array/float64' ); +var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); var gsortins = require( './../lib' ); -var rand; -var sign; -var x; -var i; - -x = new Float64Array( 10 ); -for ( i = 0; i < x.length; i++ ) { - if ( randu() < 0.2 ) { - x[ i ] = NaN; - } else { - rand = round( randu()*100.0 ); - sign = randu(); - if ( sign < 0.5 ) { - sign = -1.0; - } else { - sign = 1.0; - } - x[ i ] = sign * rand; - } -} +var x = discreteUniform( 10, -100, 100, { + 'dtype': 'float64' +}); console.log( x ); gsortins( x.length, -1.0, x, -1 ); diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/accessors.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/accessors.js new file mode 100644 index 000000000000..17073049db61 --- /dev/null +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/accessors.js @@ -0,0 +1,159 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 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. +*/ + +'use strict'; + +// MODULES // + +var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); + + +// MAIN // + +/** +* Sorts a strided array using insertion sort. +* +* @private +* @param {PositiveInteger} N - number of indexed elements +* @param {number} order - sort order +* @param {Object} x - input array object +* @param {Collection} x.data - first input array data +* @param {Array} x.accessors - first input array element accessors +* @param {integer} strideX - stride length +* @param {NonNegativeInteger} offsetX - starting index +* @returns {Object} `x` +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +* +* var x = [ 1.0, -2.0, 3.0, -4.0 ]; +* +* gsortins( x.length, 1.0, arraylike2object( toAccessorArray( x ) ), 1, 0 ); +* +* console.log( x ); +* // => [ -4.0, -2.0, 1.0, 3.0 ] +*/ +function gsortins( N, order, x, strideX, offsetX ) { + var xbuf; + var xget; + var xset; + var flg; + var ix; + var jx; + var fx; + var lx; + var v; + var u; + var i; + + // Cache reference to array data: + xbuf = x.data; + + // Cache reference to the element accessors: + xget = x.accessors[ 0 ]; + xset = x.accessors[ 1 ]; + + // For a positive stride, sorting in decreasing order is equivalent to providing a negative stride and sorting in increasing order, and, for a negative stride, sorting in decreasing order is equivalent to providing a positive stride and sorting in increasing order... + if ( order < 0.0 ) { + strideX *= -1; + offsetX -= (N-1) * strideX; + } + fx = offsetX; // first index + lx = fx + ( (N-1)*strideX ); // last index + ix = fx + strideX; + + if ( strideX < 0 ) { + // Traverse the strided array from right-to-left... + + // Sort in increasing order... + for ( i = 1; i < N; i++ ) { + v = xget( xbuf, ix ); + + // Sort `NaN` values to the end (i.e., the left)... + if ( isnan( v ) ) { + jx = ix; + + // Shift all values (including NaNs) to the left of the current element to the right... + while ( jx > lx ) { + xset( xbuf, jx, xget( xbuf, jx+strideX ) ); + jx += strideX; + } + xset( xbuf, lx, v ); + } else { + flg = isNegativeZero( v ); + jx = ix - strideX; + + // Shift all larger values to the right of the current element to the left... + while ( jx <= fx ) { + u = xget( xbuf, jx ); + if ( u <= v && !(flg && u === v && isNegativeZero( u ) === false) ) { // eslint-disable-line max-len + // Note: positive zeros (and NaNs (e.g., when last element is NaN)) are sorted to the left + break; + } + xset( xbuf, jx+strideX, u ); + jx -= strideX; + } + xset( xbuf, jx+strideX, v ); + ix += strideX; + } + } + return x; + } + // Traverse the strided array from left-to-right... + + // Sort in increasing order... + for ( i = 1; i < N; i++ ) { + v = xget( xbuf, ix ); + + // Sort `NaN` values to the end... + if ( isnan( v ) ) { + jx = ix; + + // Shift all values (including NaNs) to the right of the current element to the left... + while ( jx < lx ) { + xset( xbuf, jx, xget( xbuf, jx+strideX ) ); + jx += strideX; + } + xset( xbuf, lx, v ); + } else { + flg = isNegativeZero( v ); + jx = ix - strideX; + + // Shift all larger values to the left of the current element to the right... + while ( jx >= fx ) { + u = xget( xbuf, jx ); + if ( u <= v && !(flg && u === v && isNegativeZero( u ) === false) ) { // eslint-disable-line max-len + // Note: positive zeros (and NaNs (e.g., when first element is NaN)) are sorted to the right + break; + } + xset( xbuf, jx+strideX, u ); + jx -= strideX; + } + xset( xbuf, jx+strideX, v ); + ix += strideX; + } + } + return x; +} + + +// EXPORTS // + +module.exports = gsortins; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/main.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/main.js index d1cbe535d8ff..dff7e46502a1 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/main.js @@ -20,8 +20,8 @@ // MODULES // -var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); -var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -32,7 +32,7 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' ); * @param {PositiveInteger} N - number of indexed elements * @param {number} order - sort order * @param {NumericArray} x - input array -* @param {integer} stride - index increment +* @param {integer} strideX - stride length * @returns {NumericArray} input array * * @example @@ -41,101 +41,8 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' ); * gsortins( x.length, 1.0, x, 1 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ -function gsortins( N, order, x, stride ) { - var flg; - var ix; - var jx; - var fx; - var lx; - var v; - var u; - var i; - - if ( N <= 0 || order === 0.0 ) { - return x; - } - // For a positive stride, sorting in decreasing order is equivalent to providing a negative stride and sorting in increasing order, and, for a negative stride, sorting in decreasing order is equivalent to providing a positive stride and sorting in increasing order... - if ( order < 0.0 ) { - stride *= -1; - } - if ( stride < 0 ) { - // Traverse the strided array from right-to-left... - fx = (1-N) * stride; // first index - lx = 0; // last index - ix = fx + stride; - - // Sort in increasing order... - for ( i = 1; i < N; i++ ) { - v = x[ ix ]; - - // Sort `NaN` values to the end (i.e., the left)... - if ( isnan( v ) ) { - jx = ix; - - // Shift all values (including NaNs) to the left of the current element to the right... - while ( jx > lx ) { - x[ jx ] = x[ jx+stride ]; - jx += stride; - } - x[ lx ] = v; - } else { - flg = isNegativeZero( v ); - jx = ix - stride; - - // Shift all larger values to the right of the current element to the left... - while ( jx <= fx ) { - u = x[ jx ]; - if ( u <= v && !(flg && u === v && isNegativeZero( u ) === false) ) { // eslint-disable-line max-len - // Note: positive zeros (and NaNs (e.g., when last element is NaN)) are sorted to the left - break; - } - x[ jx+stride ] = u; - jx -= stride; - } - x[ jx+stride ] = v; - ix += stride; - } - } - return x; - } - // Traverse the strided array from left-to-right... - fx = 0; // first index - lx = (N-1) * stride; // last index - ix = fx + stride; - - // Sort in increasing order... - for ( i = 1; i < N; i++ ) { - v = x[ ix ]; - - // Sort `NaN` values to the end... - if ( isnan( v ) ) { - jx = ix; - - // Shift all values (including NaNs) to the right of the current element to the left... - while ( jx < lx ) { - x[ jx ] = x[ jx+stride ]; - jx += stride; - } - x[ lx ] = v; - } else { - flg = isNegativeZero( v ); - jx = ix - stride; - - // Shift all larger values to the left of the current element to the right... - while ( jx >= fx ) { - u = x[ jx ]; - if ( u <= v && !(flg && u === v && isNegativeZero( u ) === false) ) { // eslint-disable-line max-len - // Note: positive zeros (and NaNs (e.g., when first element is NaN)) are sorted to the right - break; - } - x[ jx+stride ] = u; - jx -= stride; - } - x[ jx+stride ] = v; - ix += stride; - } - } - return x; +function gsortins( N, order, x, strideX ) { + return ndarray( N, order, x, strideX, stride2offset( N, strideX ) ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/ndarray.js index 42d1e0096175..24de6f711ef8 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/lib/ndarray.js @@ -20,8 +20,10 @@ // MODULES // +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var accessors = require( './accessors.js' ); // MAIN // @@ -32,8 +34,8 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' ); * @param {PositiveInteger} N - number of indexed elements * @param {number} order - sort order * @param {NumericArray} x - input array -* @param {integer} stride - index increment -* @param {NonNegativeInteger} offset - starting index +* @param {integer} strideX - stride length +* @param {NonNegativeInteger} offsetX - starting index * @returns {NumericArray} input array * * @example @@ -42,12 +44,13 @@ var isnan = require( '@stdlib/math/base/assert/is-nan' ); * gsortins( x.length, 1.0, x, 1, 0 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ -function gsortins( N, order, x, stride, offset ) { +function gsortins( N, order, x, strideX, offsetX ) { var flg; var ix; var jx; var fx; var lx; + var ox; var v; var u; var i; @@ -55,16 +58,21 @@ function gsortins( N, order, x, stride, offset ) { if ( N <= 0 || order === 0.0 ) { return x; } + ox = arraylike2object( x ); + if ( ox.accessorProtocol ) { + accessors( N, order, ox, strideX, offsetX ); + return x; + } // For a positive stride, sorting in decreasing order is equivalent to providing a negative stride and sorting in increasing order, and, for a negative stride, sorting in decreasing order is equivalent to providing a positive stride and sorting in increasing order... if ( order < 0.0 ) { - stride *= -1; - offset -= (N-1) * stride; + strideX *= -1; + offsetX -= (N-1) * strideX; } - fx = offset; // first index - lx = fx + ((N-1)*stride); // last index - ix = fx + stride; + fx = offsetX; // first index + lx = fx + ( (N-1)*strideX ); // last index + ix = fx + strideX; - if ( stride < 0 ) { + if ( strideX < 0 ) { // Traverse the strided array from right-to-left... // Sort in increasing order... @@ -77,13 +85,13 @@ function gsortins( N, order, x, stride, offset ) { // Shift all values (including NaNs) to the left of the current element to the right... while ( jx > lx ) { - x[ jx ] = x[ jx+stride ]; - jx += stride; + x[ jx ] = x[ jx+strideX ]; + jx += strideX; } x[ lx ] = v; } else { flg = isNegativeZero( v ); - jx = ix - stride; + jx = ix - strideX; // Shift all larger values to the right of the current element to the left... while ( jx <= fx ) { @@ -92,11 +100,11 @@ function gsortins( N, order, x, stride, offset ) { // Note: positive zeros (and NaNs (e.g., when last element is NaN)) are sorted to the left break; } - x[ jx+stride ] = u; - jx -= stride; + x[ jx+strideX ] = u; + jx -= strideX; } - x[ jx+stride ] = v; - ix += stride; + x[ jx+strideX ] = v; + ix += strideX; } } return x; @@ -113,13 +121,13 @@ function gsortins( N, order, x, stride, offset ) { // Shift all values (including NaNs) to the right of the current element to the left... while ( jx < lx ) { - x[ jx ] = x[ jx+stride ]; - jx += stride; + x[ jx ] = x[ jx+strideX ]; + jx += strideX; } x[ lx ] = v; } else { flg = isNegativeZero( v ); - jx = ix - stride; + jx = ix - strideX; // Shift all larger values to the left of the current element to the right... while ( jx >= fx ) { @@ -128,11 +136,11 @@ function gsortins( N, order, x, stride, offset ) { // Note: positive zeros (and NaNs (e.g., when first element is NaN)) are sorted to the right break; } - x[ jx+stride ] = u; - jx -= stride; + x[ jx+strideX ] = u; + jx -= strideX; } - x[ jx+stride ] = v; - ix += stride; + x[ jx+strideX ] = v; + ix += strideX; } } return x; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js index 9869a2ec0b52..54156c95ffcf 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js @@ -24,6 +24,7 @@ var tape = require( 'tape' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); var isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var randu = require( '@stdlib/random/base/randu' ); var Float64Array = require( '@stdlib/array/float64' ); var ascending = require( './fixtures/ascending.js' ); @@ -72,6 +73,34 @@ tape( 'the function sorts a strided array (increasing order)', function test( t t.end(); }); +tape( 'the function sorts a strided array (increasing order, accessors)', function test( t ) { + var expected; + var x; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + x.push( (randu()*20.0) - 10.0 ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array (decreasing order)', function test( t ) { var expected; var x; @@ -102,6 +131,36 @@ tape( 'the function sorts a strided array (decreasing order)', function test( t t.end(); }); +tape( 'the function sorts a strided array (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + x.push( (randu()*20.0) - 10.0 ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, x, 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes NaNs (increasing order)', function test( t ) { var expected; var x; @@ -136,6 +195,40 @@ tape( 'the function sorts a strided array which includes NaNs (increasing order) t.end(); }); +tape( 'the function sorts a strided array which includes NaNs (increasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = (randu()*20.0) - 10.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes NaNs (decreasing order)', function test( t ) { var expected; var x; @@ -172,6 +265,42 @@ tape( 'the function sorts a strided array which includes NaNs (decreasing order) t.end(); }); +tape( 'the function sorts a strided array which includes NaNs (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = (randu()*20.0) - 10.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes positive and negative zeros (increasing order)', function test( t ) { var expected; var x; @@ -206,6 +335,40 @@ tape( 'the function sorts a strided array which includes positive and negative z t.end(); }); +tape( 'the function sorts a strided array which includes positive and negative zeros (increasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.5 ) { + v = -0.0; + } else { + v = 0.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes positive and negative zeros (decreasing order)', function test( t ) { var expected; var x; @@ -242,7 +405,43 @@ tape( 'the function sorts a strided array which includes positive and negative z t.end(); }); -tape( 'the function sorts a strided array (increasing order; special cases)', function test( t ) { +tape( 'the function sorts a strided array which includes positive and negative zeros (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.5 ) { + v = -0.0; + } else { + v = 0.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + +tape( 'the function sorts a strided array (increasing order, special cases)', function test( t ) { var expected; var x; var i; @@ -303,7 +502,68 @@ tape( 'the function sorts a strided array (increasing order; special cases)', fu t.end(); }); -tape( 'the function sorts a strided array (decreasing order; special cases)', function test( t ) { +tape( 'the function sorts a strided array (increasing order, special cases, accessors)', function test( t ) { + var expected; + var x; + var i; + + x = [ NaN, 1.0, -1.0, 2.0, 2.0 ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + + x = [ 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + + x = [ NaN, 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + +tape( 'the function sorts a strided array (decreasing order, special cases)', function test( t ) { var expected; var x; var i; @@ -368,6 +628,71 @@ tape( 'the function sorts a strided array (decreasing order; special cases)', fu t.end(); }); +tape( 'the function sorts a strided array (decreasing order, special cases, accessors)', function test( t ) { + var expected; + var x; + var i; + var j; + + x = [ NaN, 1.0, -1.0, 2.0, 2.0 ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + + x = [ 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + + x = [ NaN, 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function returns a reference to the input array', function test( t ) { var out; var x; @@ -379,6 +704,17 @@ tape( 'the function returns a reference to the input array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the input array (accessors)', function test( t ) { + var out; + var x; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + out = gsortins( x.length, 1.0, x, 1 ); + + t.strictEqual( out, x, 'same reference' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `x` unchanged', function test( t ) { var expected; var x; @@ -432,6 +768,30 @@ tape( 'the function supports specifying a stride (increasing order)', function t t.end(); }); +tape( 'the function supports specifying a stride (increasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + -5.0, // 0 + -3.0, + 2.0, // 1 + 7.0, + 6.0 // 2 + ]; + + gsortins( 3, 1.0, toAccessorArray( x ), 2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a stride (decreasing order)', function test( t ) { var expected; var x; @@ -456,6 +816,30 @@ tape( 'the function supports specifying a stride (decreasing order)', function t t.end(); }); +tape( 'the function supports specifying a stride (decreasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + 6.0, // 0 + -3.0, + 2.0, // 1 + 7.0, + -5.0 // 2 + ]; + + gsortins( 3, -1.0, toAccessorArray( x ), 2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a negative stride (increasing order)', function test( t ) { var expected; var x; @@ -480,6 +864,30 @@ tape( 'the function supports specifying a negative stride (increasing order)', f t.end(); }); +tape( 'the function supports specifying a negative stride (increasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + 6.0, // 2 + -3.0, + 2.0, // 1 + 7.0, + -5.0 // 0 + ]; + + gsortins( 3, 1.0, toAccessorArray( x ), -2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a negative stride (decreasing order)', function test( t ) { var expected; var x; @@ -504,6 +912,30 @@ tape( 'the function supports specifying a negative stride (decreasing order)', f t.end(); }); +tape( 'the function supports specifying a negative stride (decreasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + -5.0, // 2 + -3.0, + 2.0, // 1 + 7.0, + 6.0 // 0 + ]; + + gsortins( 3, -1.0, toAccessorArray( x ), -2 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports view offsets (increasing order)', function test( t ) { var expected; var x0; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.ndarray.js index c790c8ec6a5d..9a7ae7609afe 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.ndarray.js @@ -24,6 +24,7 @@ var tape = require( 'tape' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); var isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); var isNegativeZero = require( '@stdlib/math/base/assert/is-negative-zero' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var randu = require( '@stdlib/random/base/randu' ); var ascending = require( './fixtures/ascending.js' ); var num2str = require( './fixtures/num2str.js' ); @@ -71,6 +72,34 @@ tape( 'the function sorts a strided array (increasing order)', function test( t t.end(); }); +tape( 'the function sorts a strided array (increasing order, accessors)', function test( t ) { + var expected; + var x; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + x.push( (randu()*20.0) - 10.0 ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array (decreasing order)', function test( t ) { var expected; var x; @@ -101,6 +130,36 @@ tape( 'the function sorts a strided array (decreasing order)', function test( t t.end(); }); +tape( 'the function sorts a strided array (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + x.push( (randu()*20.0) - 10.0 ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes NaNs (increasing order)', function test( t ) { var expected; var x; @@ -135,6 +194,40 @@ tape( 'the function sorts a strided array which includes NaNs (increasing order) t.end(); }); +tape( 'the function sorts a strided array which includes NaNs (increasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = (randu()*20.0) - 10.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes NaNs (decreasing order)', function test( t ) { var expected; var x; @@ -171,6 +264,42 @@ tape( 'the function sorts a strided array which includes NaNs (decreasing order) t.end(); }); +tape( 'the function sorts a strided array which includes NaNs (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = (randu()*20.0) - 10.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes positive and negative zeros (increasing order)', function test( t ) { var expected; var x; @@ -205,6 +334,40 @@ tape( 'the function sorts a strided array which includes positive and negative z t.end(); }); +tape( 'the function sorts a strided array which includes positive and negative zeros (increasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.5 ) { + v = -0.0; + } else { + v = 0.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + tape( 'the function sorts a strided array which includes positive and negative zeros (decreasing order)', function test( t ) { var expected; var x; @@ -241,7 +404,43 @@ tape( 'the function sorts a strided array which includes positive and negative z t.end(); }); -tape( 'the function sorts a strided array (increasing order; special cases)', function test( t ) { +tape( 'the function sorts a strided array which includes positive and negative zeros (decreasing order, accessors)', function test( t ) { + var expected; + var x; + var v; + var i; + var j; + + x = []; + for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.5 ) { + v = -0.0; + } else { + v = 0.0; + } + x.push( v ); + } + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + +tape( 'the function sorts a strided array (increasing order, special cases)', function test( t ) { var expected; var x; var i; @@ -302,7 +501,68 @@ tape( 'the function sorts a strided array (increasing order; special cases)', fu t.end(); }); -tape( 'the function sorts a strided array (decreasing order; special cases)', function test( t ) { +tape( 'the function sorts a strided array (increasing order, special cases, accessors)', function test( t ) { + var expected; + var x; + var i; + + x = [ NaN, 1.0, -1.0, 2.0, 2.0 ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + + x = [ 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + + x = [ NaN, 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, 1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + if ( isnan( expected[ i ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } else if ( isNegativeZero( expected[ i ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[i] )+'.' ); + } else if ( isPositiveZero( expected[ i ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[i]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ i ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[i]+'.' ); + } + } + t.end(); +}); + +tape( 'the function sorts a strided array (decreasing order, special cases)', function test( t ) { var expected; var x; var i; @@ -367,6 +627,71 @@ tape( 'the function sorts a strided array (decreasing order; special cases)', fu t.end(); }); +tape( 'the function sorts a strided array (decreasing order, special cases, accessors)', function test( t ) { + var expected; + var x; + var i; + var j; + + x = [ NaN, 1.0, -1.0, 2.0, 2.0 ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + + x = [ 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + + x = [ NaN, 1.0, -1.0, 2.0, 2.0, NaN ]; + + // Note: we assume that the built-in sort returns a correctly sorted result + expected = x.slice().sort( ascending ); + + gsortins( x.length, -1.0, toAccessorArray( x ), 1, 0 ); + for ( i = 0; i < expected.length; i++ ) { + j = expected.length - i - 1; + if ( isnan( expected[ j ] ) ) { + t.strictEqual( isnan( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } else if ( isNegativeZero( expected[ j ] ) ) { + t.strictEqual( isNegativeZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+num2str( expected[j] )+'.' ); + } else if ( isPositiveZero( expected[ j ] ) ) { + t.strictEqual( isPositiveZero( x[ i ] ), true, 'returns expected value. index: '+i+'. actual: '+num2str( x[i] )+'. expected: '+expected[j]+'.' ); + } else { + t.strictEqual( x[ i ], expected[ j ], 'returns expected value. index: '+i+' actual: '+x[i]+'. expected: '+expected[j]+'.' ); + } + } + t.end(); +}); + tape( 'the function returns a reference to the input array', function test( t ) { var out; var x; @@ -378,6 +703,17 @@ tape( 'the function returns a reference to the input array', function test( t ) t.end(); }); +tape( 'the function returns a reference to the input array (accessors)', function test( t ) { + var out; + var x; + + x = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0 ] ); + out = gsortins( x.length, 1.0, x, 1, 0 ); + + t.strictEqual( out, x, 'same reference' ); + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `x` unchanged', function test( t ) { var expected; var x; @@ -431,6 +767,30 @@ tape( 'the function supports specifying a stride (increasing order)', function t t.end(); }); +tape( 'the function supports specifying a stride (increasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + -5.0, // 0 + -3.0, + 2.0, // 1 + 7.0, + 6.0 // 2 + ]; + + gsortins( 3, 1.0, toAccessorArray( x ), 2, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a stride (decreasing order)', function test( t ) { var expected; var x; @@ -455,6 +815,30 @@ tape( 'the function supports specifying a stride (decreasing order)', function t t.end(); }); +tape( 'the function supports specifying a stride (decreasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 0 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 2 + ]; + expected = [ + 6.0, // 0 + -3.0, + 2.0, // 1 + 7.0, + -5.0 // 2 + ]; + + gsortins( 3, -1.0, toAccessorArray( x ), 2, 0 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a negative stride (increasing order)', function test( t ) { var expected; var x; @@ -479,6 +863,30 @@ tape( 'the function supports specifying a negative stride (increasing order)', f t.end(); }); +tape( 'the function supports specifying a negative stride (increasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + 6.0, // 2 + -3.0, + 2.0, // 1 + 7.0, + -5.0 // 0 + ]; + + gsortins( 3, 1.0, toAccessorArray( x ), -2, x.length-1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying a negative stride (decreasing order)', function test( t ) { var expected; var x; @@ -503,6 +911,30 @@ tape( 'the function supports specifying a negative stride (decreasing order)', f t.end(); }); +tape( 'the function supports specifying a negative stride (decreasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 2.0, // 2 + -3.0, + -5.0, // 1 + 7.0, + 6.0 // 0 + ]; + expected = [ + -5.0, // 2 + -3.0, + 2.0, // 1 + 7.0, + 6.0 // 0 + ]; + + gsortins( 3, -1.0, toAccessorArray( x ), -2, x.length-1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying an offset (increasing order)', function test( t ) { var expected; var x; @@ -529,6 +961,32 @@ tape( 'the function supports specifying an offset (increasing order)', function t.end(); }); +tape( 'the function supports specifying an offset (increasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 1.0, + -2.0, // 0 + 3.0, + -4.0, // 1 + 5.0, + -6.0 // 2 + ]; + expected = [ + 1.0, + -6.0, // 0 + 3.0, + -4.0, // 1 + 5.0, + -2.0 // 2 + ]; + + gsortins( 3, 1.0, toAccessorArray( x ), 2, 1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports specifying an offset (decreasing order)', function test( t ) { var expected; var x; @@ -555,6 +1013,32 @@ tape( 'the function supports specifying an offset (decreasing order)', function t.end(); }); +tape( 'the function supports specifying an offset (decreasing order, accessors)', function test( t ) { + var expected; + var x; + + x = [ + 1.0, + -6.0, // 0 + 3.0, + -4.0, // 1 + 5.0, + -2.0 // 2 + ]; + expected = [ + 1.0, + -2.0, // 0 + 3.0, + -4.0, // 1 + 5.0, + -6.0 // 2 + ]; + + gsortins( 3, -1.0, toAccessorArray( x ), 2, 1 ); + t.deepEqual( x, expected, 'returns expected value' ); + t.end(); +}); + tape( 'the function supports complex access patterns (increasing order)', function test( t ) { var expected; var x; From 11a766d1f4f1d7c60aefd7352d0b7c6040771829 Mon Sep 17 00:00:00 2001 From: Athan Date: Sun, 9 Feb 2025 01:03:24 -0800 Subject: [PATCH 2/2] test: fix test case Signed-off-by: Athan --- .../@stdlib/blas/ext/base/gsortins/test/test.main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js index 54156c95ffcf..f37c951f4881 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsortins/test/test.main.js @@ -145,7 +145,7 @@ tape( 'the function sorts a strided array (decreasing order, accessors)', functi // Note: we assume that the built-in sort returns a correctly sorted result expected = x.slice().sort( ascending ); - gsortins( x.length, -1.0, x, 1 ); + gsortins( x.length, -1.0, toAccessorArray( x ), 1 ); for ( i = 0; i < expected.length; i++ ) { j = expected.length - i - 1; if ( isnan( expected[ j ] ) ) {