diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/README.md b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/README.md index 02558dcc2f93..53c91b1fe7a9 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/README.md +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/README.md @@ -30,9 +30,9 @@ limitations under the License. var gsorthp = require( '@stdlib/blas/ext/base/gsorthp' ); ``` -#### gsorthp( N, order, x, stride ) +#### gsorthp( N, order, x, strideX ) -Sorts a strided array `x` using heapsort. +Sorts a strided array using heapsort. ```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. +- **strideX**: 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 ); -gsorthp( N, -1.0, x, 2 ); +gsorthp( 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... -gsorthp( N, -1.0, x1, 2 ); +gsorthp( 2, -1.0, x1, 2 ); // x0 => [ 1.0, 4.0, 3.0, 2.0 ] ``` -#### gsorthp.ndarray( N, order, x, stride, offset ) +#### gsorthp.ndarray( N, order, x, strideX, offsetX ) -Sorts a strided array `x` using heapsort and alternative indexing semantics. +Sorts a strided array using heapsort and alternative indexing semantics. ```javascript var x = [ 1.0, -2.0, 3.0, -4.0 ]; @@ -91,9 +86,9 @@ gsorthp.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 @@ gsorthp.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 time complexity `O(N log2 N)`. @@ -129,27 +125,12 @@ gsorthp.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 gsorthp = require( '@stdlib/blas/ext/base/gsorthp' ); -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 ); gsorthp( x.length, -1.0, x, -1 ); @@ -197,6 +178,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 + [@williams:1964a]: https://doi.org/10.1145/512274.512284 [@floyd:1964a]: https://doi.org/10.1145/355588.365103 diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/repl.txt b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/repl.txt index 6515ac853c1c..36ef31009326 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/repl.txt +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/repl.txt @@ -1,9 +1,9 @@ -{{alias}}( N, order, x, stride ) +{{alias}}( N, order, x, strideX ) Sorts a strided array using heapsort. - 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 array + are accessed at runtime. Indexing is relative to the first index. To introduce an offset, use typed array views. @@ -39,8 +39,8 @@ x: Array|TypedArray Input array. - stride: integer - Index increment for `x`. + strideX: integer + Stride length. Returns ------- @@ -54,27 +54,26 @@ > {{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 heapsort 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 ---------- @@ -88,11 +87,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 ------- @@ -108,8 +107,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/gsorthp/docs/types/index.d.ts b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/types/index.d.ts index f7e0fe7bb62d..7bcd99bb4a45 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/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 `gsorthp`. @@ -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 { * gsorthp( 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, stride: number ): T; /** * Sorts a strided array using heapsort 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 { * gsorthp.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, stride: number, offset: 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/gsorthp/docs/types/test.ts b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/types/test.ts index c4c53cc2132a..959641243f85 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/types/test.ts +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import gsorthp = require( './index' ); @@ -25,7 +26,8 @@ import gsorthp = require( './index' ); { const x = new Float64Array( 10 ); - gsorthp( x.length, 1, x, 1 ); // $ExpectType NumericArray + gsorthp( x.length, 1, x, 1 ); // $ExpectType Float64Array + gsorthp( 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 gsorthp = require( './index' ); { const x = new Float64Array( 10 ); - gsorthp.ndarray( x.length, 1, x, 1, 0 ); // $ExpectType NumericArray + gsorthp.ndarray( x.length, 1, x, 1, 0 ); // $ExpectType Float64Array + gsorthp.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/gsorthp/examples/index.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/examples/index.js index c2d7acb94208..9564d69e5f9e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/examples/index.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/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 gsorthp = 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 ); gsorthp( x.length, -1.0, x, -1 ); diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/accessors.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/accessors.js new file mode 100644 index 000000000000..3c32a85eaea9 --- /dev/null +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/accessors.js @@ -0,0 +1,160 @@ +/** +* @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 isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var floor = require( '@stdlib/math/base/special/floor' ); + + +// MAIN // + +/** +* Sorts a strided array using heapsort. +* +* ## Notes +* +* - This implementation uses an in-place algorithm derived from the work of Floyd (1964). +* +* ## References +* +* - Williams, John William Joseph. 1964. "Algorithm 232: Heapsort." _Communications of the ACM_ 7 (6). New York, NY, USA: Association for Computing Machinery: 347–49. doi:[10.1145/512274.512284](https://doi.org/10.1145/512274.512284). +* - Floyd, Robert W. 1964. "Algorithm 245: Treesort." _Communications of the ACM_ 7 (12). New York, NY, USA: Association for Computing Machinery: 701. doi:[10.1145/355588.365103](https://doi.org/10.1145/355588.365103). +* +* @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 ]; +* +* gsorthp( x.length, 1.0, arraylike2object( toAccessorArray( x ) ), 1, 0 ); +* +* console.log( x ); +* // => [ -4.0, -2.0, 1.0, 3.0 ] +*/ +function gsorthp( N, order, x, strideX, offsetX ) { + var parent; + var child; + var xbuf; + var xget; + var xset; + var v1; + var v2; + var n; + var t; + var i; + var j; + var k; + + // 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; + } + // Set the initial heap size: + n = N; + + // Specify an initial "parent" index for building the heap: + parent = floor( N / 2 ); + + // Continue looping until the array is sorted... + while ( true ) { + if ( parent > 0 ) { + // We need to build the heap... + parent -= 1; + t = xget( xbuf, offsetX+(parent*strideX) ); + } else { + // Reduce the heap size: + n -= 1; + + // Check if the heap is empty, and, if so, we are finished sorting... + if ( n === 0 ) { + return x; + } + // Store the last heap value in a temporary variable in order to make room for the heap root being placed into its sorted position: + i = offsetX + (n*strideX); + t = xget( xbuf, i ); + + // Move the heap root to its sorted position: + xset( xbuf, i, xget( xbuf, offsetX ) ); + } + // We need to "sift down", pushing `t` down the heap to in order to replace the parent and satisfy the heap property... + + // Start at the parent index: + j = parent; + + // Get the "left" child index: + child = (j*2) + 1; + + while ( child < n ) { + // Find the largest child... + k = child + 1; + if ( k < n ) { + v1 = xget( xbuf, offsetX+(k*strideX) ); + v2 = xget( xbuf, offsetX+(child*strideX) ); + + // Check if a "right" child exists and is "bigger"... + if ( v1 > v2 || isnan( v1 ) || (v1 === v2 && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len + child += 1; + } + } + // Check if the largest child is bigger than `t`... + v1 = xget( xbuf, offsetX+(child*strideX) ); + if ( v1 > t || isnan( v1 ) || ( v1 === t && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len + // Insert the larger child value: + xset( xbuf, offsetX+(j*strideX), v1 ); + + // Update `j` to point to the child index: + j = child; + + // Get the "left" child index and repeat... + child = (j*2) + 1; + } else { + // We've found `t`'s place in the heap... + break; + } + } + // Insert `t` into the heap: + xset( xbuf, offsetX+(j*strideX), t ); + } +} + + +// EXPORTS // + +module.exports = gsorthp; diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/main.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/main.js index 727318a7abf1..4597ce7034bd 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/main.js @@ -20,9 +20,8 @@ // MODULES // -var isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); -var isnan = require( '@stdlib/math/base/assert/is-nan' ); -var floor = require( '@stdlib/math/base/special/floor' ); +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); +var ndarray = require( './ndarray.js' ); // MAIN // @@ -42,7 +41,7 @@ var floor = require( '@stdlib/math/base/special/floor' ); * @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 @@ -51,96 +50,8 @@ var floor = require( '@stdlib/math/base/special/floor' ); * gsorthp( x.length, 1.0, x, 1 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ -function gsorthp( N, order, x, stride ) { - var offset; - var parent; - var child; - var v1; - var v2; - var n; - var t; - var i; - var j; - var k; - - 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 ) { - offset = (1-N) * stride; - } else { - offset = 0; - } - // Set the initial heap size: - n = N; - - // Specify an initial "parent" index for building the heap: - parent = floor( N / 2 ); - - // Continue looping until the array is sorted... - while ( true ) { - if ( parent > 0 ) { - // We need to build the heap... - parent -= 1; - t = x[ offset+(parent*stride) ]; - } else { - // Reduce the heap size: - n -= 1; - - // Check if the heap is empty, and, if so, we are finished sorting... - if ( n === 0 ) { - return x; - } - // Store the last heap value in a temporary variable in order to make room for the heap root being placed into its sorted position: - i = offset + (n*stride); - t = x[ i ]; - - // Move the heap root to its sorted position: - x[ i ] = x[ offset ]; - } - // We need to "sift down", pushing `t` down the heap to in order to replace the parent and satisfy the heap property... - - // Start at the parent index: - j = parent; - - // Get the "left" child index: - child = (j*2) + 1; - - while ( child < n ) { - // Find the largest child... - k = child + 1; - if ( k < n ) { - v1 = x[ offset+(k*stride) ]; - v2 = x[ offset+(child*stride) ]; - - // Check if a "right" child exists and is "bigger"... - if ( v1 > v2 || isnan( v1 ) || (v1 === v2 && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len - child += 1; - } - } - // Check if the largest child is bigger than `t`... - v1 = x[ offset+(child*stride) ]; - if ( v1 > t || isnan( v1 ) || ( v1 === t && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len - // Insert the larger child value: - x[ offset+(j*stride) ] = v1; - - // Update `j` to point to the child index: - j = child; - - // Get the "left" child index and repeat... - child = (j*2) + 1; - } else { - // We've found `t`'s place in the heap... - break; - } - } - // Insert `t` into the heap: - x[ offset+(j*stride) ] = t; - } +function gsorthp( N, order, x, strideX ) { + return ndarray( N, order, x, strideX, stride2offset( N, strideX ) ); } diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/ndarray.js index 072cef2bff44..01a6eef91235 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/lib/ndarray.js @@ -20,9 +20,11 @@ // MODULES // +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); var isPositiveZero = require( '@stdlib/math/base/assert/is-positive-zero' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); var floor = require( '@stdlib/math/base/special/floor' ); +var accessors = require( './accessors.js' ); // MAIN // @@ -42,8 +44,8 @@ var floor = require( '@stdlib/math/base/special/floor' ); * @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 @@ -52,11 +54,12 @@ var floor = require( '@stdlib/math/base/special/floor' ); * gsorthp( x.length, 1.0, x, 1, 0 ); * // x => [ -4.0, -2.0, 1.0, 3.0 ] */ -function gsorthp( N, order, x, stride, offset ) { +function gsorthp( N, order, x, strideX, offsetX ) { var parent; var child; var v1; var v2; + var ox; var n; var t; var i; @@ -66,10 +69,15 @@ function gsorthp( 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; } // Set the initial heap size: n = N; @@ -82,7 +90,7 @@ function gsorthp( N, order, x, stride, offset ) { if ( parent > 0 ) { // We need to build the heap... parent -= 1; - t = x[ offset+(parent*stride) ]; + t = x[ offsetX+(parent*strideX) ]; } else { // Reduce the heap size: n -= 1; @@ -92,11 +100,11 @@ function gsorthp( N, order, x, stride, offset ) { return x; } // Store the last heap value in a temporary variable in order to make room for the heap root being placed into its sorted position: - i = offset + (n*stride); + i = offsetX + (n*strideX); t = x[ i ]; // Move the heap root to its sorted position: - x[ i ] = x[ offset ]; + x[ i ] = x[ offsetX ]; } // We need to "sift down", pushing `t` down the heap to in order to replace the parent and satisfy the heap property... @@ -110,8 +118,8 @@ function gsorthp( N, order, x, stride, offset ) { // Find the largest child... k = child + 1; if ( k < n ) { - v1 = x[ offset+(k*stride) ]; - v2 = x[ offset+(child*stride) ]; + v1 = x[ offsetX+(k*strideX) ]; + v2 = x[ offsetX+(child*strideX) ]; // Check if a "right" child exists and is "bigger"... if ( v1 > v2 || isnan( v1 ) || (v1 === v2 && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len @@ -119,10 +127,10 @@ function gsorthp( N, order, x, stride, offset ) { } } // Check if the largest child is bigger than `t`... - v1 = x[ offset+(child*stride) ]; + v1 = x[ offsetX+(child*strideX) ]; if ( v1 > t || isnan( v1 ) || ( v1 === t && isPositiveZero( v1 ) ) ) { // eslint-disable-line max-len // Insert the larger child value: - x[ offset+(j*stride) ] = v1; + x[ offsetX+(j*strideX) ] = v1; // Update `j` to point to the child index: j = child; @@ -135,7 +143,7 @@ function gsorthp( N, order, x, stride, offset ) { } } // Insert `t` into the heap: - x[ offset+(j*stride) ] = t; + x[ offsetX+(j*strideX) ] = t; } } diff --git a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/test/test.main.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/test/test.main.js index f8fff00def6c..80123138dad4 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/test/test.main.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/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 ); + + gsorthp( 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 ); + + gsorthp( 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 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 = gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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/gsorthp/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/test/test.ndarray.js index b153bad12bc6..1ef0496e5f0e 100644 --- a/lib/node_modules/@stdlib/blas/ext/base/gsorthp/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/ext/base/gsorthp/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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 ); + + gsorthp( 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 = gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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 + ]; + + gsorthp( 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;