diff --git a/base/arraylike2object/README.md b/base/arraylike2object/README.md index e6117709..b2ad2f8b 100644 --- a/base/arraylike2object/README.md +++ b/base/arraylike2object/README.md @@ -62,6 +62,7 @@ var obj = arraylike2object( [ 1, 2, 3, 4 ] ); - The returned object has the following properties: - **data**: reference to the input array. + - **dtype**: input array data type. If unable to resolve the [data type][@stdlib/array/dtype] of the input array, the property value is `null`. - **accessorProtocol**: `boolean` indicating whether the input uses accessors for getting and setting elements. - **accessors**: a two-element array whose first element is an accessor for retrieving an array element (i.e., a getter) and whose second element is an accessor for setting an array element (i.e., a setter). @@ -128,6 +129,8 @@ console.log( obj ); diff --git a/base/arraylike2object/docs/repl.txt b/base/arraylike2object/docs/repl.txt index e5135be4..eae1d4f8 100644 --- a/base/arraylike2object/docs/repl.txt +++ b/base/arraylike2object/docs/repl.txt @@ -5,6 +5,7 @@ The returned object has the following properties: - data: reference to input array. + - dtype: input array data type. - accessorProtocol: boolean indicating whether the input array uses accessors for getting and setting elements. - accessors: a two-element array whose first element is an accessor for @@ -35,6 +36,9 @@ out.data: ArrayLikeObject Reference to input array. + out.dtype: string|null + Input array data type. + out.accessorProtocol: boolean Boolean indicating whether the input array use accessors for getting and setting elements. diff --git a/base/arraylike2object/docs/types/index.d.ts b/base/arraylike2object/docs/types/index.d.ts index 2d285be7..48141560 100644 --- a/base/arraylike2object/docs/types/index.d.ts +++ b/base/arraylike2object/docs/types/index.d.ts @@ -1,3 +1,5 @@ +/* eslint-disable max-lines */ + /* * @license Apache-2.0 * @@ -285,6 +287,11 @@ interface Float64AccessorObject { */ data: Float64Array; + /** + * Data type. + */ + dtype: 'float64'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -305,6 +312,11 @@ interface Float32AccessorObject { */ data: Float32Array; + /** + * Data type. + */ + dtype: 'float32'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -325,6 +337,11 @@ interface Int32AccessorObject { */ data: Int32Array; + /** + * Data type. + */ + dtype: 'int32'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -345,6 +362,11 @@ interface Int16AccessorObject { */ data: Int16Array; + /** + * Data type. + */ + dtype: 'int16'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -365,6 +387,11 @@ interface Int8AccessorObject { */ data: Int8Array; + /** + * Data type. + */ + dtype: 'int8'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -385,6 +412,11 @@ interface Uint32AccessorObject { */ data: Uint32Array; + /** + * Data type. + */ + dtype: 'uint32'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -405,6 +437,11 @@ interface Uint16AccessorObject { */ data: Uint16Array; + /** + * Data type. + */ + dtype: 'uint16'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -425,6 +462,11 @@ interface Uint8AccessorObject { */ data: Uint8Array; + /** + * Data type. + */ + dtype: 'uint8'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -445,6 +487,11 @@ interface Uint8cAccessorObject { */ data: Uint8ClampedArray; + /** + * Data type. + */ + dtype: 'uint8c'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -465,6 +512,11 @@ interface Complex128AccessorObject { */ data: Complex128Array; + /** + * Data type. + */ + dtype: 'complex128'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -485,6 +537,11 @@ interface Complex64AccessorObject { */ data: Complex64Array; + /** + * Data type. + */ + dtype: 'complex64'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -505,6 +562,11 @@ interface GenericAccessorObject { */ data: Array; + /** + * Data type. + */ + dtype: 'generic'; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -525,6 +587,11 @@ interface IndexedAccessorObject { */ data: Collection; + /** + * Data type. + */ + dtype: string | null; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ @@ -545,6 +612,11 @@ interface GetSetAccessorObject { */ data: AccessorArrayLike; + /** + * Data type. + */ + dtype: string | null; + /** * Boolean indicating whether the provided array-like object supports the get/set protocol (i.e., uses accessors for getting and setting elements). */ diff --git a/base/arraylike2object/lib/main.js b/base/arraylike2object/lib/main.js index 99c8876c..a975488e 100644 --- a/base/arraylike2object/lib/main.js +++ b/base/arraylike2object/lib/main.js @@ -20,7 +20,12 @@ // MODULES // -var accessors = require( './../../../base/accessors' ); +var isAccessorArray = require( './../../../base/assert/is-accessor-array' ); +var getter = require( './../../../base/getter' ); +var setter = require( './../../../base/setter' ); +var accessorGetter = require( './../../../base/accessor-getter' ); +var accessorSetter = require( './../../../base/accessor-setter' ); +var dtype = require( './../../../dtype' ); // MAIN // @@ -35,6 +40,7 @@ var accessors = require( './../../../base/accessors' ); * - The returned object has the following properties: * * - **data**: reference to the input array. +* - **dtype**: array data type. * - **accessorProtocol**: `boolean` indicating whether the input array uses accessors for getting and setting elements. * - **accessors**: a two-element array whose first element is an accessor for retrieving an array element and whose second element is an accessor for setting an array element. * @@ -46,11 +52,26 @@ var accessors = require( './../../../base/accessors' ); * // returns {...} */ function arraylike2object( x ) { - var o = accessors( x ); + var dt = dtype( x ); + if ( isAccessorArray( x ) ) { + return { + 'data': x, + 'dtype': dt, + 'accessorProtocol': true, + 'accessors': [ + accessorGetter( dt ), + accessorSetter( dt ) + ] + }; + } return { 'data': x, - 'accessorProtocol': o.accessorProtocol, - 'accessors': o.accessors + 'dtype': dt, + 'accessorProtocol': false, + 'accessors': [ + getter( dt ), + setter( dt ) + ] }; } diff --git a/base/arraylike2object/test/test.js b/base/arraylike2object/test/test.js index b351295e..40c98ae6 100644 --- a/base/arraylike2object/test/test.js +++ b/base/arraylike2object/test/test.js @@ -47,11 +47,13 @@ tape( 'the function converts an array to a standardized object', function test( expected = { 'data': x, + 'dtype': 'float64', 'accessorProtocol': false }; actual = arraylike2object( x ); t.strictEqual( actual.data, expected.data, 'returns expected value' ); + t.strictEqual( actual.dtype, expected.dtype, 'returns expected value' ); t.strictEqual( actual.accessorProtocol, expected.accessorProtocol, 'returns expected value' ); t.strictEqual( typeof actual.accessors[ 0 ], 'function', 'returns expected value' ); t.strictEqual( actual.accessors[ 0 ].length, 2, 'returns expected value' ); @@ -77,11 +79,13 @@ tape( 'the function converts an array-like object to a standardized object', fun expected = { 'data': x, + 'dtype': null, 'accessorProtocol': false }; actual = arraylike2object( x ); t.strictEqual( actual.data, expected.data, 'returns expected value' ); + t.strictEqual( actual.dtype, expected.dtype, 'returns expected value' ); t.strictEqual( actual.accessorProtocol, expected.accessorProtocol, 'returns expected value' ); t.strictEqual( typeof actual.accessors[ 0 ], 'function', 'returns expected value' ); t.strictEqual( actual.accessors[ 0 ].length, 2, 'returns expected value' ); @@ -105,11 +109,13 @@ tape( 'the function converts an array to a standardized object (data buffer acce expected = { 'data': x, + 'dtype': 'complex64', 'accessorProtocol': true }; actual = arraylike2object( x ); t.strictEqual( actual.data, expected.data, 'returns expected value' ); + t.strictEqual( actual.dtype, expected.dtype, 'returns expected value' ); t.strictEqual( actual.accessorProtocol, expected.accessorProtocol, 'returns expected value' ); t.strictEqual( typeof actual.accessors[ 0 ], 'function', 'returns expected value' ); t.strictEqual( actual.accessors[ 0 ].length, 2, 'returns expected value' ); diff --git a/base/assert/is-mostly-safe-data-type-cast/README.md b/base/assert/is-mostly-safe-data-type-cast/README.md new file mode 100644 index 00000000..6da51578 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/README.md @@ -0,0 +1,118 @@ + + +# isMostlySafeCast + +> Determine whether an array [data type][@stdlib/array/dtypes] can be safely cast or, for floating-point data types, downcast to another array [data type][@stdlib/array/dtypes]. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var isMostlySafeCast = require( '@stdlib/array/base/assert/is-mostly-safe-data-type-cast' ); +``` + +#### isMostlySafeCast( from, to ) + +Returns a `boolean` indicating whether an array [data type][@stdlib/array/dtypes] can be safely cast or, for floating-point data types, downcast to another array [data type][@stdlib/array/dtypes]. + +```javascript +var bool = isMostlySafeCast( 'float32', 'float64' ); +// returns true + +bool = isMostlySafeCast( 'float64', 'int32' ); +// returns false +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var cartesianSquare = require( '@stdlib/array/base/cartesian-square' ); +var dtypes = require( '@stdlib/array/dtypes' ); +var isMostlySafeCast = require( '@stdlib/array/base/assert/is-mostly-safe-data-type-cast' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can cast to another data type... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Can cast? %s.', dt[i].join( ' => ' ), isMostlySafeCast.apply( null, dt[i] ) ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/assert/is-mostly-safe-data-type-cast/benchmark/benchmark.js b/base/assert/is-mostly-safe-data-type-cast/benchmark/benchmark.js new file mode 100644 index 00000000..8e0703b5 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/benchmark/benchmark.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var dtypes = require( './../../../../dtypes' ); +var pkg = require( './../package.json' ).name; +var isMostlySafeCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var out; + var N; + var i; + var j; + var k; + + N = DTYPES.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + j = i % N; + k = (i+1) % N; + out = isMostlySafeCast( DTYPES[ j ], DTYPES[ k ] ); + if ( typeof out !== 'boolean' ) { + b.fail( 'should return a boolean' ); + } + } + b.toc(); + if ( !isBoolean( out ) ) { + b.fail( 'should return a boolean' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/base/assert/is-mostly-safe-data-type-cast/docs/repl.txt b/base/assert/is-mostly-safe-data-type-cast/docs/repl.txt new file mode 100644 index 00000000..df66d219 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/docs/repl.txt @@ -0,0 +1,30 @@ + +{{alias}}( from, to ) + Returns a boolean indicating whether a provided array data type can be + safely cast or, for floating-point data types, downcast to another array + data type. + + Parameters + ---------- + from: string + Array data type. + + to: string + Array data type. + + Returns + ------- + bool: boolean + Boolean indicating whether a provided data type can be cast to another + data type. + + Examples + -------- + > var bool = {{alias}}( 'float32', 'float64' ) + true + > bool = {{alias}}( 'float64', 'int32' ) + false + + See Also + -------- + diff --git a/base/assert/is-mostly-safe-data-type-cast/docs/types/index.d.ts b/base/assert/is-mostly-safe-data-type-cast/docs/types/index.d.ts new file mode 100644 index 00000000..79f41969 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/docs/types/index.d.ts @@ -0,0 +1,40 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Returns a boolean indicating if a provided array data type can be safely cast or, for floating-point data types, downcast to another array data type. +* +* @param from - array data type +* @param to - array data type +* @returns boolean indicating if a data type can be cast to another data type +* +* @example +* var bool = isMostlySafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isMostlySafeCast( 'float64', 'int32' ); +* // returns false +*/ +declare function isMostlySafeCast( from: string, to: string ): boolean; + + +// EXPORTS // + +export = isMostlySafeCast; diff --git a/base/assert/is-mostly-safe-data-type-cast/docs/types/test.ts b/base/assert/is-mostly-safe-data-type-cast/docs/types/test.ts new file mode 100644 index 00000000..9e58f768 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/docs/types/test.ts @@ -0,0 +1,58 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import isMostlySafeCast = require( './index' ); + + +// TESTS // + +// The function returns a boolean... +{ + isMostlySafeCast( 'float32', 'float64' ); // $ExpectType boolean + isMostlySafeCast( 'float64', 'int32' ); // $ExpectType boolean +} + +// The compiler throws an error if the function is provided a first argument which is not a string... +{ + isMostlySafeCast( true, 'int32' ); // $ExpectError + isMostlySafeCast( false, 'int32' ); // $ExpectError + isMostlySafeCast( null, 'int32' ); // $ExpectError + isMostlySafeCast( undefined, 'int32' ); // $ExpectError + isMostlySafeCast( 123, 'int32' ); // $ExpectError + isMostlySafeCast( [], 'int32' ); // $ExpectError + isMostlySafeCast( {}, 'int32' ); // $ExpectError + isMostlySafeCast( ( x: number ): number => x, 'int32' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a string... +{ + isMostlySafeCast( 'float64', true ); // $ExpectError + isMostlySafeCast( 'float64', false ); // $ExpectError + isMostlySafeCast( 'float64', null ); // $ExpectError + isMostlySafeCast( 'float64', undefined ); // $ExpectError + isMostlySafeCast( 'float64', 123 ); // $ExpectError + isMostlySafeCast( 'float64', [] ); // $ExpectError + isMostlySafeCast( 'float64', {} ); // $ExpectError + isMostlySafeCast( 'float64', ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + isMostlySafeCast(); // $ExpectError + isMostlySafeCast( 'float64' ); // $ExpectError +} diff --git a/base/assert/is-mostly-safe-data-type-cast/examples/index.js b/base/assert/is-mostly-safe-data-type-cast/examples/index.js new file mode 100644 index 00000000..268ee91e --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/examples/index.js @@ -0,0 +1,32 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var cartesianSquare = require( './../../../../cartesian-square' ); +var dtypes = require( './../../../../dtypes' ); +var isMostlySafeCast = require( './../lib' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can cast to another data type... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Can cast? %s.', dt[i].join( ' => ' ), isMostlySafeCast.apply( null, dt[i] ) ); +} diff --git a/base/assert/is-mostly-safe-data-type-cast/lib/index.js b/base/assert/is-mostly-safe-data-type-cast/lib/index.js new file mode 100644 index 00000000..2d7fcee9 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/lib/index.js @@ -0,0 +1,43 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Determine if an array data type can be safely cast or, for floating-point data types, downcast to another array data type. +* +* @module @stdlib/array/base/assert/is-mostly-safe-data-type-cast +* +* @example +* var isMostlySafeCast = require( '@stdlib/array/base/assert/is-mostly-safe-data-type-cast' ); +* +* var bool = isMostlySafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isMostlySafeCast( 'float64', 'int32' ); +* // returns false +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/assert/is-mostly-safe-data-type-cast/lib/main.js b/base/assert/is-mostly-safe-data-type-cast/lib/main.js new file mode 100644 index 00000000..468e2507 --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/lib/main.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var casts = require( './../../../../mostly-safe-casts' ); + + +// VARIABLES // + +var TABLE = casts(); + + +// MAIN // + +/** +* Returns a boolean indicating if a provided array data type can be safely cast or, for floating-point data types, downcast to another array data type. +* +* @param {string} from - array data type +* @param {string} to - array data type +* @returns {boolean} boolean indicating if a data type can be cast to another data type +* +* @example +* var bool = isMostlySafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isMostlySafeCast( 'float64', 'int32' ); +* // returns false +*/ +function isMostlySafeCast( from, to ) { + if ( from === to ) { + return true; + } + return ( TABLE[ from ][ to ] > 0 ); +} + + +// EXPORTS // + +module.exports = isMostlySafeCast; diff --git a/base/assert/is-mostly-safe-data-type-cast/package.json b/base/assert/is-mostly-safe-data-type-cast/package.json new file mode 100644 index 00000000..a56c6cbd --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/package.json @@ -0,0 +1,73 @@ +{ + "name": "@stdlib/array/base/assert/is-mostly-safe-data-type-cast", + "version": "0.0.0", + "description": "Determine if an array data type can be safely cast or, for floating-point data types, downcast to another array data type.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "base", + "array", + "casting", + "safe", + "cast", + "promotion", + "test", + "assert", + "check", + "validate", + "validation", + "valid", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/base/assert/is-mostly-safe-data-type-cast/test/test.js b/base/assert/is-mostly-safe-data-type-cast/test/test.js new file mode 100644 index 00000000..2337330c --- /dev/null +++ b/base/assert/is-mostly-safe-data-type-cast/test/test.js @@ -0,0 +1,59 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var dtypes = require( './../../../../dtypes' ); +var casts = require( './../../../../mostly-safe-casts' ); +var isMostlySafeCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); +var CASTS = casts(); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof isMostlySafeCast, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns a boolean indicating if an array data type can be cast to another array data type', function test( t ) { + var expected; + var actual; + var dt; + var i; + var j; + + for ( i = 0; i < DTYPES.length; i++ ) { + dt = DTYPES[ i ]; + for ( j = 0; j < DTYPES.length; j++ ) { + expected = ( CASTS[ dt ][ DTYPES[j] ] > 0 ); + actual = isMostlySafeCast( dt, DTYPES[ j ] ); + t.strictEqual( actual, expected, 'returns expected value. from: '+dt+'. to: '+DTYPES[j]+'.' ); + } + } + t.end(); +}); diff --git a/base/assert/is-safe-data-type-cast/README.md b/base/assert/is-safe-data-type-cast/README.md new file mode 100644 index 00000000..ebd68da7 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/README.md @@ -0,0 +1,118 @@ + + +# isSafeCast + +> Determine whether an array [data type][@stdlib/array/dtypes] can be safely cast to another array [data type][@stdlib/array/dtypes]. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var isSafeCast = require( '@stdlib/array/base/assert/is-safe-data-type-cast' ); +``` + +#### isSafeCast( from, to ) + +Returns a `boolean` indicating whether an array [data type][@stdlib/array/dtypes] can be safely cast to another array [data type][@stdlib/array/dtypes]. + +```javascript +var bool = isSafeCast( 'float32', 'float64' ); +// returns true + +bool = isSafeCast( 'float64', 'int32' ); +// returns false +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var cartesianSquare = require( '@stdlib/array/cartesian-square' ); +var dtypes = require( '@stdlib/array/dtypes' ); +var isSafeCast = require( '@stdlib/array/base/assert/is-safe-data-type-cast' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can safely cast from one data type to another... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Safe? %s.', dt[i].join( ' => ' ), isSafeCast.apply( null, dt[i] ) ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/assert/is-safe-data-type-cast/benchmark/benchmark.js b/base/assert/is-safe-data-type-cast/benchmark/benchmark.js new file mode 100644 index 00000000..b886dcf7 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/benchmark/benchmark.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var dtypes = require( './../../../../dtypes' ); +var pkg = require( './../package.json' ).name; +var isSafeCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var out; + var N; + var i; + var j; + var k; + + N = DTYPES.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + j = i % N; + k = (i+1) % N; + out = isSafeCast( DTYPES[ j ], DTYPES[ k ] ); + if ( typeof out !== 'boolean' ) { + b.fail( 'should return a boolean' ); + } + } + b.toc(); + if ( !isBoolean( out ) ) { + b.fail( 'should return a boolean' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/base/assert/is-safe-data-type-cast/docs/repl.txt b/base/assert/is-safe-data-type-cast/docs/repl.txt new file mode 100644 index 00000000..276ae51b --- /dev/null +++ b/base/assert/is-safe-data-type-cast/docs/repl.txt @@ -0,0 +1,29 @@ + +{{alias}}( from, to ) + Returns a boolean indicating whether a provided array data type can be + safely cast to another array data type. + + Parameters + ---------- + from: string + Array data type. + + to: string + Array data type. + + Returns + ------- + bool: boolean + Boolean indicating whether a provided data type can be safely cast to + another data type. + + Examples + -------- + > var bool = {{alias}}( 'float32', 'float64' ) + true + > bool = {{alias}}( 'float64', 'int32' ) + false + + See Also + -------- + diff --git a/base/assert/is-safe-data-type-cast/docs/types/index.d.ts b/base/assert/is-safe-data-type-cast/docs/types/index.d.ts new file mode 100644 index 00000000..dc861c75 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/docs/types/index.d.ts @@ -0,0 +1,40 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Returns a boolean indicating if a provided array data type can be safely cast to another array data type. +* +* @param from - array data type +* @param to - array data type +* @returns boolean indicating if a data type can be safely cast to another data type +* +* @example +* var bool = isSafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSafeCast( 'float64', 'int32' ); +* // returns false +*/ +declare function isSafeCast( from: string, to: string ): boolean; + + +// EXPORTS // + +export = isSafeCast; diff --git a/base/assert/is-safe-data-type-cast/docs/types/test.ts b/base/assert/is-safe-data-type-cast/docs/types/test.ts new file mode 100644 index 00000000..4791c1a5 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/docs/types/test.ts @@ -0,0 +1,58 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import isSafeCast = require( './index' ); + + +// TESTS // + +// The function returns a boolean... +{ + isSafeCast( 'float32', 'float64' ); // $ExpectType boolean + isSafeCast( 'float64', 'int32' ); // $ExpectType boolean +} + +// The compiler throws an error if the function is provided a first argument which is not a string... +{ + isSafeCast( true, 'int32' ); // $ExpectError + isSafeCast( false, 'int32' ); // $ExpectError + isSafeCast( null, 'int32' ); // $ExpectError + isSafeCast( undefined, 'int32' ); // $ExpectError + isSafeCast( 123, 'int32' ); // $ExpectError + isSafeCast( [], 'int32' ); // $ExpectError + isSafeCast( {}, 'int32' ); // $ExpectError + isSafeCast( ( x: number ): number => x, 'int32' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a string... +{ + isSafeCast( 'float64', true ); // $ExpectError + isSafeCast( 'float64', false ); // $ExpectError + isSafeCast( 'float64', null ); // $ExpectError + isSafeCast( 'float64', undefined ); // $ExpectError + isSafeCast( 'float64', 123 ); // $ExpectError + isSafeCast( 'float64', [] ); // $ExpectError + isSafeCast( 'float64', {} ); // $ExpectError + isSafeCast( 'float64', ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + isSafeCast(); // $ExpectError + isSafeCast( 'float64' ); // $ExpectError +} diff --git a/base/assert/is-safe-data-type-cast/examples/index.js b/base/assert/is-safe-data-type-cast/examples/index.js new file mode 100644 index 00000000..0a4f8f1c --- /dev/null +++ b/base/assert/is-safe-data-type-cast/examples/index.js @@ -0,0 +1,32 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var cartesianSquare = require( './../../../../cartesian-square' ); +var dtypes = require( './../../../../dtypes' ); +var isSafeCast = require( './../lib' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can safely cast from one data type to another... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Safe? %s.', dt[i].join( ' => ' ), isSafeCast.apply( null, dt[i] ) ); +} diff --git a/base/assert/is-safe-data-type-cast/lib/index.js b/base/assert/is-safe-data-type-cast/lib/index.js new file mode 100644 index 00000000..bd4b9890 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/lib/index.js @@ -0,0 +1,43 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Determine if an array data type can be safely cast to another array data type. +* +* @module @stdlib/array/base/assert/is-safe-data-type-cast +* +* @example +* var isSafeCast = require( '@stdlib/array/base/assert/is-safe-data-type-cast' ); +* +* var bool = isSafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSafeCast( 'float64', 'int32' ); +* // returns false +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/assert/is-safe-data-type-cast/lib/main.js b/base/assert/is-safe-data-type-cast/lib/main.js new file mode 100644 index 00000000..6dc63356 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/lib/main.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var safeCasts = require( './../../../../safe-casts' ); + + +// VARIABLES // + +var TABLE = safeCasts(); + + +// MAIN // + +/** +* Returns a boolean indicating if a provided array data type can be safely cast to another array data type. +* +* @param {string} from - array data type +* @param {string} to - array data type +* @returns {boolean} boolean indicating if a data type can be safely cast to another data type +* +* @example +* var bool = isSafeCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSafeCast( 'float64', 'int32' ); +* // returns false +*/ +function isSafeCast( from, to ) { + if ( from === to ) { + return true; + } + return ( TABLE[ from ][ to ] > 0 ); +} + + +// EXPORTS // + +module.exports = isSafeCast; diff --git a/base/assert/is-safe-data-type-cast/package.json b/base/assert/is-safe-data-type-cast/package.json new file mode 100644 index 00000000..f1072b33 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/package.json @@ -0,0 +1,75 @@ +{ + "name": "@stdlib/array/base/assert/is-safe-data-type-cast", + "version": "0.0.0", + "description": "Determine if an array data type can be safely cast to another array data type.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "include": "./include", + "lib": "./lib", + "src": "./src", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "base", + "array", + "casting", + "safe", + "cast", + "promotion", + "test", + "assert", + "check", + "validate", + "validation", + "valid", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/base/assert/is-safe-data-type-cast/test/test.js b/base/assert/is-safe-data-type-cast/test/test.js new file mode 100644 index 00000000..20d0d009 --- /dev/null +++ b/base/assert/is-safe-data-type-cast/test/test.js @@ -0,0 +1,59 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var dtypes = require( './../../../../dtypes' ); +var safeCasts = require( './../../../../safe-casts' ); +var isSafeCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); +var SAFE_CASTS = safeCasts(); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof isSafeCast, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns a boolean indicating if an array data type can be safely cast to another array data type', function test( t ) { + var expected; + var actual; + var dt; + var i; + var j; + + for ( i = 0; i < DTYPES.length; i++ ) { + dt = DTYPES[ i ]; + for ( j = 0; j < DTYPES.length; j++ ) { + expected = ( SAFE_CASTS[ dt ][ DTYPES[j] ] > 0 ); + actual = isSafeCast( dt, DTYPES[ j ] ); + t.strictEqual( actual, expected, 'returns expected value. from: '+dt+'. to: '+DTYPES[j]+'.' ); + } + } + t.end(); +}); diff --git a/base/assert/is-same-kind-data-type-cast/README.md b/base/assert/is-same-kind-data-type-cast/README.md new file mode 100644 index 00000000..286ce534 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/README.md @@ -0,0 +1,118 @@ + + +# isSameKindCast + +> Determine whether an array [data type][@stdlib/array/dtypes] can be safely cast to, or is of the same "kind" as, another array [data type][@stdlib/array/dtypes]. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var isSameKindCast = require( '@stdlib/array/base/assert/is-same-kind-data-type-cast' ); +``` + +#### isSameKindCast( from, to ) + +Returns a `boolean` indicating whether an array [data type][@stdlib/array/dtypes] can be safely cast to, or is of the same "kind" as, another array [data type][@stdlib/array/dtypes] (e.g., casting between signed integers or between floats). + +```javascript +var bool = isSameKindCast( 'float32', 'float64' ); +// returns true + +bool = isSameKindCast( 'uint16', 'int16' ); +// returns false +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var cartesianSquare = require( '@stdlib/array/cartesian-square' ); +var dtypes = require( '@stdlib/array/dtypes' ); +var isSameKindCast = require( '@stdlib/array/base/assert/is-same-kind-data-type-cast' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can cast from one data type to another... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Allowed cast? %s.', dt[i].join( ' => ' ), isSameKindCast.apply( null, dt[i] ) ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/assert/is-same-kind-data-type-cast/benchmark/benchmark.js b/base/assert/is-same-kind-data-type-cast/benchmark/benchmark.js new file mode 100644 index 00000000..1ad99522 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/benchmark/benchmark.js @@ -0,0 +1,61 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var dtypes = require( './../../../../dtypes' ); +var pkg = require( './../package.json' ).name; +var isSameKindCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var out; + var N; + var i; + var j; + var k; + + N = DTYPES.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + j = i % N; + k = (i+1) % N; + out = isSameKindCast( DTYPES[ j ], DTYPES[ k ] ); + if ( typeof out !== 'boolean' ) { + b.fail( 'should return a boolean' ); + } + } + b.toc(); + if ( !isBoolean( out ) ) { + b.fail( 'should return a boolean' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/base/assert/is-same-kind-data-type-cast/docs/repl.txt b/base/assert/is-same-kind-data-type-cast/docs/repl.txt new file mode 100644 index 00000000..f9a04499 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/docs/repl.txt @@ -0,0 +1,31 @@ + +{{alias}}( from, to ) + Returns a boolean indicating whether a provided array data type can be + safely cast to, or is of the same "kind" as, another array data type. + + Parameters + ---------- + from: string + Array data type. + + to: string + Array data type. + + Returns + ------- + bool: boolean + Boolean indicating whether a provided data type can be cast to another + data type. + + Examples + -------- + > var bool = {{alias}}( 'float32', 'float64' ) + true + > bool = {{alias}}( 'uint16', 'int32' ) + true + > bool = {{alias}}( 'uint16', 'int16' ) + false + + See Also + -------- + diff --git a/base/assert/is-same-kind-data-type-cast/docs/types/index.d.ts b/base/assert/is-same-kind-data-type-cast/docs/types/index.d.ts new file mode 100644 index 00000000..fb1574ae --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/docs/types/index.d.ts @@ -0,0 +1,40 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Returns a boolean indicating if a provided array data type can be safely cast to, or is of the same "kind" as, another array data type. +* +* @param from - array data type +* @param to - array data type +* @returns boolean indicating if a data type can be cast to another data type +* +* @example +* var bool = isSameKindCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSameKindCast( 'uint16', 'int16' ); +* // returns false +*/ +declare function isSameKindCast( from: string, to: string ): boolean; + + +// EXPORTS // + +export = isSameKindCast; diff --git a/base/assert/is-same-kind-data-type-cast/docs/types/test.ts b/base/assert/is-same-kind-data-type-cast/docs/types/test.ts new file mode 100644 index 00000000..91facf94 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/docs/types/test.ts @@ -0,0 +1,58 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import isSameKindCast = require( './index' ); + + +// TESTS // + +// The function returns a boolean... +{ + isSameKindCast( 'float32', 'float64' ); // $ExpectType boolean + isSameKindCast( 'float64', 'int32' ); // $ExpectType boolean +} + +// The compiler throws an error if the function is provided a first argument which is not a string... +{ + isSameKindCast( true, 'int32' ); // $ExpectError + isSameKindCast( false, 'int32' ); // $ExpectError + isSameKindCast( null, 'int32' ); // $ExpectError + isSameKindCast( undefined, 'int32' ); // $ExpectError + isSameKindCast( 123, 'int32' ); // $ExpectError + isSameKindCast( [], 'int32' ); // $ExpectError + isSameKindCast( {}, 'int32' ); // $ExpectError + isSameKindCast( ( x: number ): number => x, 'int32' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a string... +{ + isSameKindCast( 'float64', true ); // $ExpectError + isSameKindCast( 'float64', false ); // $ExpectError + isSameKindCast( 'float64', null ); // $ExpectError + isSameKindCast( 'float64', undefined ); // $ExpectError + isSameKindCast( 'float64', 123 ); // $ExpectError + isSameKindCast( 'float64', [] ); // $ExpectError + isSameKindCast( 'float64', {} ); // $ExpectError + isSameKindCast( 'float64', ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + isSameKindCast(); // $ExpectError + isSameKindCast( 'float64' ); // $ExpectError +} diff --git a/base/assert/is-same-kind-data-type-cast/examples/index.js b/base/assert/is-same-kind-data-type-cast/examples/index.js new file mode 100644 index 00000000..e36b1bc7 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/examples/index.js @@ -0,0 +1,32 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var cartesianSquare = require( './../../../../cartesian-square' ); +var dtypes = require( './../../../../dtypes' ); +var isSameKindCast = require( './../lib' ); + +// Generate a list of dtype pairs: +var dt = cartesianSquare( dtypes() ); + +// For each data type pair, determine whether one can cast from one data type to another... +var i; +for ( i = 0; i < dt.length; i++ ) { + console.log( '%s. Allowed cast? %s.', dt[i].join( ' => ' ), isSameKindCast.apply( null, dt[i] ) ); +} diff --git a/base/assert/is-same-kind-data-type-cast/lib/index.js b/base/assert/is-same-kind-data-type-cast/lib/index.js new file mode 100644 index 00000000..167a98bb --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/lib/index.js @@ -0,0 +1,43 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Determine if an array data type can be safely cast to, or is of the same "kind" as, another array data type. +* +* @module @stdlib/array/base/assert/is-same-kind-data-type-cast +* +* @example +* var isSameKindCast = require( '@stdlib/array/base/assert/is-same-kind-data-type-cast' ); +* +* var bool = isSameKindCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSameKindCast( 'uint16', 'int16' ); +* // returns false +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/assert/is-same-kind-data-type-cast/lib/main.js b/base/assert/is-same-kind-data-type-cast/lib/main.js new file mode 100644 index 00000000..c1d3b73d --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/lib/main.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var sameKindCasts = require( './../../../../same-kind-casts' ); + + +// VARIABLES // + +var TABLE = sameKindCasts(); + + +// MAIN // + +/** +* Returns a boolean indicating if a provided array data type can be safely cast to, or is of the same "kind" as, another array data type. +* +* @param {string} from - array data type +* @param {string} to - array data type +* @returns {boolean} boolean indicating if a data type can be cast to another data type +* +* @example +* var bool = isSameKindCast( 'float32', 'float64' ); +* // returns true +* +* bool = isSameKindCast( 'uint16', 'int16' ); +* // returns false +*/ +function isSameKindCast( from, to ) { + if ( from === to ) { + return true; + } + return ( TABLE[ from ][ to ] > 0 ); +} + + +// EXPORTS // + +module.exports = isSameKindCast; diff --git a/base/assert/is-same-kind-data-type-cast/package.json b/base/assert/is-same-kind-data-type-cast/package.json new file mode 100644 index 00000000..38f6410b --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/package.json @@ -0,0 +1,76 @@ +{ + "name": "@stdlib/array/base/assert/is-same-kind-data-type-cast", + "version": "0.0.0", + "description": "Determine if an array data type can be safely cast to, or is of the same kind as, another array data type.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "include": "./include", + "lib": "./lib", + "src": "./src", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "base", + "array", + "casting", + "safe", + "cast", + "kind", + "promotion", + "test", + "assert", + "check", + "validate", + "validation", + "valid", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/base/assert/is-same-kind-data-type-cast/test/test.js b/base/assert/is-same-kind-data-type-cast/test/test.js new file mode 100644 index 00000000..ef31f9a7 --- /dev/null +++ b/base/assert/is-same-kind-data-type-cast/test/test.js @@ -0,0 +1,59 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var dtypes = require( './../../../../dtypes' ); +var sameKindCasts = require( './../../../../same-kind-casts' ); +var isSameKindCast = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); +var SAME_KIND_CASTS = sameKindCasts(); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof isSameKindCast, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns a boolean indicating if an array data type can be cast to another array data type', function test( t ) { + var expected; + var actual; + var dt; + var i; + var j; + + for ( i = 0; i < DTYPES.length; i++ ) { + dt = DTYPES[ i ]; + for ( j = 0; j < DTYPES.length; j++ ) { + expected = ( SAME_KIND_CASTS[ dt ][ DTYPES[j] ] > 0 ); + actual = isSameKindCast( dt, DTYPES[ j ] ); + t.strictEqual( actual, expected, 'returns expected value. from: '+dt+'. to: '+DTYPES[j]+'.' ); + } + } + t.end(); +}); diff --git a/base/assert/lib/index.js b/base/assert/lib/index.js index 7555f003..f1a77609 100644 --- a/base/assert/lib/index.js +++ b/base/assert/lib/index.js @@ -81,6 +81,33 @@ setReadOnly( ns, 'isComplex64Array', require( './../../../base/assert/is-complex */ setReadOnly( ns, 'isComplex128Array', require( './../../../base/assert/is-complex128array' ) ); +/** +* @name isMostlySafeDataTypeCast +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/assert/is-mostly-safe-data-type-cast} +*/ +setReadOnly( ns, 'isMostlySafeDataTypeCast', require( './../../../base/assert/is-mostly-safe-data-type-cast' ) ); + +/** +* @name isSafeDataTypeCast +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/assert/is-safe-data-type-cast} +*/ +setReadOnly( ns, 'isSafeDataTypeCast', require( './../../../base/assert/is-safe-data-type-cast' ) ); + +/** +* @name isSameKindDataTypeCast +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/assert/is-same-kind-data-type-cast} +*/ +setReadOnly( ns, 'isSameKindDataTypeCast', require( './../../../base/assert/is-same-kind-data-type-cast' ) ); + // EXPORTS // diff --git a/base/fancy-slice-assign/README.md b/base/fancy-slice-assign/README.md new file mode 100644 index 00000000..99b8d8c8 --- /dev/null +++ b/base/fancy-slice-assign/README.md @@ -0,0 +1,202 @@ + + +# sliceAssign + +> Assign element values from a broadcasted input array to corresponding elements in an output array. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var sliceAssign = require( '@stdlib/array/base/fancy-slice-assign' ); +``` + +#### slice( x, y, s, strict ) + +Assigns element values from a broadcasted input array to corresponding elements in an output array. + +```javascript +var Slice = require( '@stdlib/slice/ctor' ); + +var x = [ 1, 2, 3, 4 ]; +var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; + +var s = new Slice( null, null, -2 ); +// returns + +var out = sliceAssign( x, y, s, false ); +// returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] + +var bool = ( out === y ); +// returns true +``` + +The function supports the following parameters: + +- **x**: input array. +- **y**: output array. +- **s**: [slice][@stdlib/slice/ctor] object specifying the output array slice. +- **strict**: boolean indicating whether to enforce strict bounds checking. + +
+ + + + + +
+ +## Notes + +- The input array **must** be broadcast compatible with the output array slice (i.e., contain only one element or the same number of elements as in the slice). +- The input array must have a [data type][@stdlib/array/dtypes] which can be [safely cast][@stdlib/array/safe-casts] to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the [same kind][@stdlib/array/same-kind-casts] (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). + +
+ + + + + +
+ +## Examples + + + +```javascript +var zeroTo = require( '@stdlib/array/zero-to' ); +var zeros = require( '@stdlib/array/zeros' ); +var Slice = require( '@stdlib/slice/ctor' ); +var sliceAssign = require( '@stdlib/array/base/fancy-slice-assign' ); + +var x = zeroTo( 10, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +var y = zeros( 10, 'generic' ); +// returns [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + +var s = new Slice(); +var out = sliceAssign( x, y, s, false ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( null, null, -2 ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 4, 0, 3, 0, 2, 0, 1, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( -2, null, -2 ); +out = sliceAssign( x, y, s, false ); +// returns [ 4, 0, 3, 0, 2, 0, 1, 0, 0, 0 ] + +x = zeroTo( 6, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 2, -2 ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 0, 0, 1, 2, 3, 4, 5, 0, 0 ] + +x = zeroTo( 3, 'generic' ); +// returns [ 0, 1, 2 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 2, 5 ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 ] + +x = zeroTo( 3, 'generic' ); +// returns [ 0, 1, 2 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 4, 1, -1 ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 5 ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 5, null ); +out = sliceAssign( x, y, s, false ); +// returns [ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4 ] +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/fancy-slice-assign/benchmark/benchmark.float64.js b/base/fancy-slice-assign/benchmark/benchmark.float64.js new file mode 100644 index 00000000..def1ee7f --- /dev/null +++ b/base/fancy-slice-assign/benchmark/benchmark.float64.js @@ -0,0 +1,108 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var isnan = require( '@stdlib/assert/is-nan' ).isPrimitive; +var zeroTo = require( './../../../zero-to' ); +var zeros = require( './../../../zeros' ); +var Slice = require( '@stdlib/slice/ctor' ); +var pkg = require( './../package.json' ).name; +var sliceAssign = require( './../lib' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var x = zeroTo( len, 'float64' ); + var y = zeros( len, 'float64' ); + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var values; + var out; + var v; + var i; + + values = [ + new Slice(), + new Slice(), + new Slice() + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = sliceAssign( x, y, values[ i%values.length ], false ); + v = out[ i%len ]; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( out[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var f; + var i; + + min = 1; // 10^min + max = 6; // 10^max + + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + f = createBenchmark( len ); + bench( pkg+':dtype=float64,len='+len, f ); + } +} + +main(); diff --git a/base/fancy-slice-assign/benchmark/benchmark.generic.js b/base/fancy-slice-assign/benchmark/benchmark.generic.js new file mode 100644 index 00000000..18fafea9 --- /dev/null +++ b/base/fancy-slice-assign/benchmark/benchmark.generic.js @@ -0,0 +1,108 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var isnan = require( '@stdlib/assert/is-nan' ).isPrimitive; +var zeroTo = require( './../../../zero-to' ); +var zeros = require( './../../../zeros' ); +var Slice = require( '@stdlib/slice/ctor' ); +var pkg = require( './../package.json' ).name; +var sliceAssign = require( './../lib' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var x = zeroTo( len, 'generic' ); + var y = zeros( len, 'generic' ); + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var values; + var out; + var v; + var i; + + values = [ + new Slice(), + new Slice(), + new Slice() + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = sliceAssign( x, y, values[ i%values.length ], false ); + v = out[ i%len ]; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( out[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var f; + var i; + + min = 1; // 10^min + max = 6; // 10^max + + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + f = createBenchmark( len ); + bench( pkg+':dtype=generic,len='+len, f ); + } +} + +main(); diff --git a/base/fancy-slice-assign/docs/repl.txt b/base/fancy-slice-assign/docs/repl.txt new file mode 100644 index 00000000..c2586e35 --- /dev/null +++ b/base/fancy-slice-assign/docs/repl.txt @@ -0,0 +1,42 @@ + +{{alias}}( x, y, s, strict ) + Assigns element values from a broadcasted input array to corresponding + elements in an output array. + + Parameters + ---------- + x: ArrayLikeObject + Input array. The input array must be broadcast compatible with the + output array and must have a data type which can be safely cast to the + output array data type. Floating-point data types (both real and + complex) are allowed to downcast to a lower precision data type of the + same kind (e.g., element values from a 'float64' input array can be + assigned to corresponding elements in a 'float32' output array). + + y: ArrayLikeObject + Output array. + + s: Slice + Slice object. + + strict: boolean + Boolean indicating whether to enforce strict bounds checking. + + Returns + ------- + out: Array|TypedArray|Object + Output array. + + Examples + -------- + > var x = [ 1, 2, 3, 4 ]; + > var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; + > var s = new {{alias:@stdlib/slice/ctor}}( null, null, 2 ); + > var out = {{alias}}( x, y, s, false ) + [ 1, 0, 2, 0, 3, 0, 4, 0 ] + > var b = ( out === y ) + true + + See Also + -------- + diff --git a/base/fancy-slice-assign/docs/types/index.d.ts b/base/fancy-slice-assign/docs/types/index.d.ts new file mode 100644 index 00000000..dd0149a7 --- /dev/null +++ b/base/fancy-slice-assign/docs/types/index.d.ts @@ -0,0 +1,475 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +import { Collection, Complex128Array, Complex64Array, ComplexTypedArray, AccessorArrayLike } from '@stdlib/types/array'; +import { ComplexLike } from '@stdlib/types/complex'; +import { Slice } from '@stdlib/types/slice'; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Float64Array = require( '@stdlib/array/float64' ); +* +* var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); +* var y = new Float64Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0.0, 4.0, 0.0, 3.0, 0.0, 2.0, 0.0, 1.0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Float64Array, s: Slice, strict: boolean ): Float64Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Float32Array = require( '@stdlib/array/float32' ); +* +* var x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] ); +* var y = new Float32Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0.0, 4.0, 0.0, 3.0, 0.0, 2.0, 0.0, 1.0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Float32Array, s: Slice, strict: boolean ): Float32Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int32Array = require( '@stdlib/array/int32' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4 ] ); +* var y = new Int32Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Int32Array, s: Slice, strict: boolean ): Int32Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int16Array = require( '@stdlib/array/int16' ); +* +* var x = new Int16Array( [ 1, 2, 3, 4 ] ); +* var y = new Int16Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Int16Array, s: Slice, strict: boolean ): Int16Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int8Array = require( '@stdlib/array/int8' ); +* +* var x = new Int8Array( [ 1, 2, 3, 4 ] ); +* var y = new Int8Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Int8Array, s: Slice, strict: boolean ): Int8Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint32Array = require( '@stdlib/array/uint32' ); +* +* var x = new Uint32Array( [ 1, 2, 3, 4 ] ); +* var y = new Uint32Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Uint32Array, s: Slice, strict: boolean ): Uint32Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint16Array = require( '@stdlib/array/uint16' ); +* +* var x = new Uint16Array( [ 1, 2, 3, 4 ] ); +* var y = new Uint16Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Uint16Array, s: Slice, strict: boolean ): Uint16Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint8Array = require( '@stdlib/array/uint8' ); +* +* var x = new Uint8Array( [ 1, 2, 3, 4 ] ); +* var y = new Uint8Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Uint8Array, s: Slice, strict: boolean ): Uint8Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint8ClampedArray = require( '@stdlib/array/uint8c' ); +* +* var x = new Uint8ClampedArray( [ 1, 2, 3, 4 ] ); +* var y = new Uint8ClampedArray( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: Uint8ClampedArray, s: Slice, strict: boolean ): Uint8ClampedArray; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Complex128Array = require( '@stdlib/array/complex128' ); +* +* var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] ); +* var y = new Complex128Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] ); +* +* var s = new Slice( null, null, 2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 1.0, 2.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: ComplexTypedArray | AccessorArrayLike, y: Complex128Array, s: Slice, strict: boolean ): Complex128Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Complex64Array = require( '@stdlib/array/complex64' ); +* +* var x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); +* var y = new Complex64Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] ); +* +* var s = new Slice( null, null, 2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 1.0, 2.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: ComplexTypedArray | AccessorArrayLike, y: Complex64Array, s: Slice, strict: boolean ): Complex64Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = [ 1, 2, 3, 4 ]; +* var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; +* +* var s = new Slice( null, null, 2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 1, 0, 2, 0, 3, 0, 4, 0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection, y: Array, s: Slice, strict: boolean ): Array; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); +* var y = toAccessorArray( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, 2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection | AccessorArrayLike, y: AccessorArrayLike, s: Slice, strict: boolean ): AccessorArrayLike; + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* ## Notes +* +* - The input array must be broadcast compatible with the output array slice to which elements will be assigned (i.e., contain only one element or the same number of elements as in the slice). +* - The input array must have a data type which can be safely cast to the output array data type. Floating-point data types (both real and complex) are allowed to downcast to a lower precision data type of the same kind (e.g., element values from a `'float64'` input array can be assigned to corresponding elements in a `'float32'` output array). +* +* @param x - input array +* @param y - output array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = [ 1, 2, 3, 4 ]; +* var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; +* +* var s = new Slice( null, null, 2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 1, 0, 2, 0, 3, 0, 4, 0 ] +* +* var bool = ( out === y ); +* // returns true +*/ +declare function sliceAssign( x: Collection, y: Collection, s: Slice, strict: boolean ): Collection; + + +// EXPORTS // + +export = sliceAssign; diff --git a/base/fancy-slice-assign/docs/types/test.ts b/base/fancy-slice-assign/docs/types/test.ts new file mode 100644 index 00000000..7aeeebab --- /dev/null +++ b/base/fancy-slice-assign/docs/types/test.ts @@ -0,0 +1,102 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Complex128Array = require( './../../../../complex128' ); +import Complex64Array = require( './../../../../complex64' ); +import Slice = require( '@stdlib/slice/ctor' ); +import sliceAssign = require( './index' ); + + +// TESTS // + +// The function returns an array... +{ + sliceAssign( [ 1, 2, 3 ], [ 1, 2, 3 ], new Slice(), false ); // $ExpectType number[] + sliceAssign( new Float64Array( [ 1, 2, 3 ] ), new Float64Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Float64Array + sliceAssign( new Float32Array( [ 1, 2, 3 ] ), new Float32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Float32Array + sliceAssign( new Int32Array( [ 1, 2, 3 ] ), new Int32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int32Array + sliceAssign( new Int16Array( [ 1, 2, 3 ] ), new Int16Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int16Array + sliceAssign( new Int8Array( [ 1, 2, 3 ] ), new Int8Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int8Array + sliceAssign( new Uint32Array( [ 1, 2, 3 ] ), new Uint32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint32Array + sliceAssign( new Uint16Array( [ 1, 2, 3 ] ), new Uint16Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint16Array + sliceAssign( new Uint8Array( [ 1, 2, 3 ] ), new Uint8Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint8Array + sliceAssign( new Uint8ClampedArray( [ 1, 2, 3 ] ), new Uint8ClampedArray( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint8ClampedArray + sliceAssign( new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ), new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), false ); // $ExpectType Complex128Array + sliceAssign( new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ), new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), false ); // $ExpectType Complex64Array +} + +// The compiler throws an error if the function is provided a first argument which is not a collection... +{ + sliceAssign( 5, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError + sliceAssign( true, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError + sliceAssign( false, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError + sliceAssign( null, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError + sliceAssign( void 0, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError + sliceAssign( {}, [ 1, 2, 3 ], new Slice(), false ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a collection... +{ + const x = [ 1, 2, 3 ]; + + sliceAssign( x, 5, new Slice(), false ); // $ExpectError + sliceAssign( x, true, new Slice(), false ); // $ExpectError + sliceAssign( x, false, new Slice(), false ); // $ExpectError + sliceAssign( x, null, new Slice(), false ); // $ExpectError + sliceAssign( x, void 0, new Slice(), false ); // $ExpectError + sliceAssign( x, {}, new Slice(), false ); // $ExpectError + sliceAssign( x, ( x: number ): number => x, new Slice(), false ); // $ExpectError +} + +// The compiler throws an error if the function is provided a third argument which is not a slice object... +{ + const x = [ 1, 2, 3 ]; + + sliceAssign( x, x, '5', false ); // $ExpectError + sliceAssign( x, x, true, false ); // $ExpectError + sliceAssign( x, x, false, false ); // $ExpectError + sliceAssign( x, x, null, false ); // $ExpectError + sliceAssign( x, x, void 0, false ); // $ExpectError + sliceAssign( x, x, {}, false ); // $ExpectError + sliceAssign( x, x, [], false ); // $ExpectError + sliceAssign( x, x, ( x: number ): number => x, false ); // $ExpectError +} + +// The compiler throws an error if the function is provided a fourth argument which is not a boolean... +{ + const x = [ 1, 2, 3 ]; + + sliceAssign( x, x, new Slice(), '5' ); // $ExpectError + sliceAssign( x, x, new Slice(), 5 ); // $ExpectError + sliceAssign( x, x, new Slice(), null ); // $ExpectError + sliceAssign( x, x, new Slice(), void 0 ); // $ExpectError + sliceAssign( x, x, new Slice(), {} ); // $ExpectError + sliceAssign( x, x, new Slice(), [] ); // $ExpectError + sliceAssign( x, x, new Slice(), ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + const x = [ 1, 2, 3 ]; + + sliceAssign(); // $ExpectError + sliceAssign( x ); // $ExpectError + sliceAssign( x, x ); // $ExpectError + sliceAssign( x, x, new Slice() ); // $ExpectError + sliceAssign( x, x, new Slice(), false, {} ); // $ExpectError +} diff --git a/base/fancy-slice-assign/examples/index.js b/base/fancy-slice-assign/examples/index.js new file mode 100644 index 00000000..712b99ec --- /dev/null +++ b/base/fancy-slice-assign/examples/index.js @@ -0,0 +1,98 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var zeroTo = require( './../../../zero-to' ); +var zeros = require( './../../../zeros' ); +var Slice = require( '@stdlib/slice/ctor' ); +var sliceAssign = require( './../lib' ); + +var x = zeroTo( 10, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +var y = zeros( 10, 'generic' ); +// returns [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] + +var s = new Slice(); +var out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( null, null, -2 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 4, 0, 3, 0, 2, 0, 1, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( -2, null, -2 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 4, 0, 3, 0, 2, 0, 1, 0, 0, 0 ] + +x = zeroTo( 6, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 2, -2 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 0, 0, 1, 2, 3, 4, 5, 0, 0 ] + +x = zeroTo( 3, 'generic' ); +// returns [ 0, 1, 2 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 2, 5 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 ] + +x = zeroTo( 3, 'generic' ); +// returns [ 0, 1, 2 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 4, 1, -1 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 0, 2, 1, 0, 0, 0, 0, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 5 ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 ] + +x = zeroTo( 5, 'generic' ); +// returns [ 0, 1, 2, 3, 4 ] + +y = zeros( 10, 'generic' ); +s = new Slice( 5, null ); +out = sliceAssign( x, y, s, false ); +console.log( out ); +// => [ 0, 0, 0, 0, 0, 0, 1, 2, 3, 4 ] diff --git a/base/fancy-slice-assign/lib/index.js b/base/fancy-slice-assign/lib/index.js new file mode 100644 index 00000000..b02b9998 --- /dev/null +++ b/base/fancy-slice-assign/lib/index.js @@ -0,0 +1,67 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Assign element values from a broadcasted input array to corresponding elements in an output array. +* +* @module @stdlib/array/base/fancy-slice-assign +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var sliceAssign = require( '@stdlib/array/base/fancy-slice-assign' ); +* +* var x = [ 1, 2, 3, 4 ]; +* var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* var Slice = require( '@stdlib/slice/ctor' ); +* var sliceAssign = require( '@stdlib/array/base/fancy-slice-assign' ); +* +* var x = new Int32Array( [ 5 ] ); +* var y = new Int32Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 5, 0, 5, 0, 5, 0, 5 ] +* +* var bool = ( out === y ); +* // returns true +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/fancy-slice-assign/lib/main.js b/base/fancy-slice-assign/lib/main.js new file mode 100644 index 00000000..2eb0d0d7 --- /dev/null +++ b/base/fancy-slice-assign/lib/main.js @@ -0,0 +1,126 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isMostlySafeCast = require( './../../../base/assert/is-mostly-safe-data-type-cast' ); +var normalizeSlice = require( '@stdlib/slice/base/normalize-slice' ); +var sliceLength = require( '@stdlib/slice/base/length' ); +var dtype = require( './../../../dtype' ); +var gcopy = require( '@stdlib/blas/base/gcopy' ).ndarray; +var format = require( '@stdlib/string/format' ); + + +// MODULES // + +/** +* Assigns element values from a broadcasted input array to corresponding elements in an output array. +* +* @param {Collection} x - input array +* @param {Collection} y - output array +* @param {Slice} s - slice object +* @param {boolean} strict - boolean indicating whether to enforce strict bounds checking +* @throws {RangeError} slice exceeds array bounds +* @throws {Error} input array must be broadcast compatible with an output array view +* @throws {TypeError} input array cannot be safely cast to the output array data type +* @returns {Collection} output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = [ 1, 2, 3, 4 ]; +* var y = [ 0, 0, 0, 0, 0, 0, 0, 0 ]; +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 4, 0, 3, 0, 2, 0, 1 ] +* +* var bool = ( out === y ); +* // returns true +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = new Int32Array( [ 5 ] ); +* var y = new Int32Array( [ 0, 0, 0, 0, 0, 0, 0, 0 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var out = sliceAssign( x, y, s, false ); +* // returns [ 0, 5, 0, 5, 0, 5, 0, 5 ] +* +* var bool = ( out === y ); +* // returns true +*/ +function sliceAssign( x, y, s, strict ) { + var xlen; + var ylen; + var xdt; + var ydt; + var ns; + var xs; + var N; + + xdt = dtype( x ) || 'generic'; + ydt = dtype( y ) || 'generic'; + + xlen = x.length; + ylen = y.length; + + // Safe casts are always allowed and allow same kind casts (i.e., downcasts) only when the output data type is floating-point... + if ( !isMostlySafeCast( xdt, ydt ) ) { + throw new TypeError( format( 'invalid argument. Input array values cannot be safely cast to the output array data type. Data types: [%s, %s].', xdt, ydt ) ); + } + // Normalize the slice object base on the output array length: + ns = normalizeSlice( s, ylen, true ); + + // Check whether the slice exceeds the array bounds... + if ( ns.code ) { + if ( strict ) { + throw new RangeError( format( 'invalid argument. Slice exceeds array bounds. Array length: %d.', ylen ) ); + } + // Normalize again, this time allowing for out-of-bounds indices: + ns = normalizeSlice( s, ylen, false ); + } + // Compute the slice length: + N = sliceLength( ns ); + + // Broadcast the input array: + if ( xlen === 1 ) { + xs = 0; + } else if ( xlen === N ) { + xs = 1; + } else { + throw new Error( format( 'invalid argument. Input array and the output array slice are broadcast incompatible. Array length: %u. Desired length: %u.', xlen, N ) ); + } + // Copy elements to the output array: + gcopy( N, x, xs, 0, y, ns.step, ns.start ); + + return y; +} + + +// EXPORTS // + +module.exports = sliceAssign; diff --git a/base/fancy-slice-assign/package.json b/base/fancy-slice-assign/package.json new file mode 100644 index 00000000..433503d9 --- /dev/null +++ b/base/fancy-slice-assign/package.json @@ -0,0 +1,68 @@ +{ + "name": "@stdlib/array/base/fancy-slice-assign", + "version": "0.0.0", + "description": "Assign element values from a broadcasted input array to corresponding elements in an output array.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "data", + "structure", + "array", + "generic", + "copy", + "slice", + "shallow", + "fancy", + "subsequence", + "subseq", + "assign", + "assignment" + ] +} diff --git a/base/fancy-slice-assign/test/test.js b/base/fancy-slice-assign/test/test.js new file mode 100644 index 00000000..a7c0b3b1 --- /dev/null +++ b/base/fancy-slice-assign/test/test.js @@ -0,0 +1,734 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var AccessorArray = require( './../../../base/accessor' ); +var Float64Array = require( './../../../float64' ); +var Int32Array = require( './../../../int32' ); +var zeros = require( './../../../zeros' ); +var Slice = require( '@stdlib/slice/ctor' ); +var sliceAssign = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof sliceAssign, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if provided an input array which cannot be safely cast to the output array data type', function test( t ) { + var values; + var x; + var i; + + x = zeros( 5, 'float64' ); + + values = [ + zeros( 5, 'uint8' ), + zeros( 5, 'int8' ), + zeros( 5, 'int16' ), + zeros( 5, 'uint16' ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + sliceAssign( x, value, new Slice(), false ); + }; + } +}); + +tape( 'the function throws an error if provided an input array which is not broadcast compatible with the output array slice', function test( t ) { + var values; + var y; + var i; + + y = zeros( 5, 'float64' ); + + values = [ + zeros( 2, 'float64' ), + zeros( 3, 'float64' ), + zeros( 4, 'float64' ), + zeros( 10, 'float64' ), + zeros( 0, 'float64' ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided ' + values[ i ] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + sliceAssign( value, y, new Slice(), false ); + }; + } +}); + +tape( 'when `strict` is `true`, the function throws an error if provided a slice which is out-of-bounds', function test( t ) { + var values; + var x; + var i; + + x = zeros( 5, 'generic' ); + + values = [ + new Slice( 10, 20 ), + new Slice( -20, -10 ), + new Slice( 0, 100 ), + new Slice( 0, -100 ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + sliceAssign( x, x, value, true ); + }; + } +}); + +tape( 'when `strict` is `false`, the function returns the output array unchanged if provided a slice which is out-of-bounds', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = [ 1 ]; + y = zeros( x.length, 'generic' ); + actual = sliceAssign( x, y, new Slice( 10, 20 ), false ); + + expected = zeros( x.length, 'generic' ); + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1 ] ); + y = zeros( x.length, 'int32' ); + actual = sliceAssign( x, y, new Slice( -20, -10 ), false ); + + expected = zeros( x.length, 'int32' ); + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 1 ] ); + y = zeros( x.length, 'generic' ); + actual = sliceAssign( x, y, new Slice( 0, -100 ), false ); + + expected = zeros( x.length, 'generic' ); + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1.0 ] ); + y = zeros( x.length, 'generic' ); + actual = sliceAssign( x, y, new Slice( -10, -20 ), false ); + + expected = zeros( x.length, 'float64' ); + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function performs slice assignment with support for broadcasting (generic)', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = [ 1, 2, 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 1, 2, 3 ]; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 3, 2, 1 ]; + actual = sliceAssign( x, y, new Slice( null, null, -1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 3, 0, 1 ]; + actual = sliceAssign( x, y, new Slice( null, null, -2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 1, 0, 3 ]; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 2, 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 0, 2, 3 ]; + actual = sliceAssign( x, y, new Slice( 1, null ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 2 ]; + y = zeros( 3, 'generic' ); + + expected = [ 0, 2, 0 ]; + actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1 ]; + y = zeros( 3, 'generic' ); + + expected = [ 0, 0, 0 ]; + actual = sliceAssign( x, y, new Slice( 1, 1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Broadcasting: + x = [ 1 ]; + y = zeros( 3, 'generic' ); + + expected = [ 1, 1, 1 ]; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 3 ]; + y = zeros( 3, 'generic' ); + + expected = [ 3, 0, 3 ]; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function performs slice assignment with support for broadcasting (float64)', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = new Float64Array( [ 1.0, 2.0, 3.0 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 1.0, 2.0, 3.0 ] ); + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1.0, 2.0, 3.0 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 3.0, 2.0, 1.0 ] ); + actual = sliceAssign( x, y, new Slice( null, null, -1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 3 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 3.0, 0.0, 1.0 ] ); + actual = sliceAssign( x, y, new Slice( null, null, -2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 3 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 1.0, 0.0, 3.0 ] ); + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 2, 3 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 0.0, 2.0, 3.0 ] ); + actual = sliceAssign( x, y, new Slice( 1, null ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 2 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 0.0, 2.0, 0.0 ] ); + actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 0.0, 0.0, 0.0 ] ); + actual = sliceAssign( x, y, new Slice( 1, 1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Broadcasting: + x = new Float64Array( [ 1 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 1.0, 1.0, 1.0 ] ); + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 3 ] ); + y = zeros( 3, 'float64' ); + + expected = new Float64Array( [ 3.0, 0.0, 3.0 ] ); + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function performs slice assignment with support for broadcasting (int32)', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 1, 2, 3 ] ); + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 3, 2, 1 ] ); + actual = sliceAssign( x, y, new Slice( null, null, -1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 3, 0, 1 ] ); + actual = sliceAssign( x, y, new Slice( null, null, -2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 1, 0, 3 ] ); + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 2, 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 0, 2, 3 ] ); + actual = sliceAssign( x, y, new Slice( 1, null ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 2 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 0, 2, 0 ] ); + actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 0, 0, 0 ] ); + actual = sliceAssign( x, y, new Slice( 1, 1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Broadcasting: + x = new Int32Array( [ 1 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 1, 1, 1 ] ); + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 3 ] ); + y = zeros( 3, 'int32' ); + + expected = new Int32Array( [ 3, 0, 3 ] ); + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function performs slice assignment with support for broadcasting (accessors)', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = new AccessorArray( [ 1, 2, 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 1, 2, 3 ]; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 1, 2, 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 3, 2, 1 ]; + actual = sliceAssign( x, y, new Slice( null, null, -1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 1, 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 3, 0, 1 ]; + actual = sliceAssign( x, y, new Slice( null, null, -2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 1, 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 1, 0, 3 ]; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 2, 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 0, 2, 3 ]; + actual = sliceAssign( x, y, new Slice( 1, null ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 2 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 0, 2, 0 ]; + actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 1 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 0, 0, 0 ]; + actual = sliceAssign( x, y, new Slice( 1, 1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Broadcasting: + x = new AccessorArray( [ 1 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 1, 1, 1 ]; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new AccessorArray( [ 3 ] ); + y = zeros( 3, 'generic' ); + + expected = [ 3, 0, 3 ]; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function performs slice assignment with support for broadcasting (array-like)', function test( t ) { + var expected; + var actual; + var x; + var y; + + x = { + 'length': 3, + '0': 1, + '1': 2, + '2': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 1, + '1': 2, + '2': 3 + }; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 3, + '0': 1, + '1': 2, + '2': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 3, + '1': 2, + '2': 1 + }; + actual = sliceAssign( x, y, new Slice( null, null, -1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 2, + '0': 1, + '1': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 3, + '1': 0, + '2': 1 + }; + actual = sliceAssign( x, y, new Slice( null, null, -2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 2, + '0': 1, + '1': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 1, + '1': 0, + '2': 3 + }; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 2, + '0': 2, + '1': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 0, + '1': 2, + '2': 3 + }; + actual = sliceAssign( x, y, new Slice( 1, null ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 1, + '0': 2 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 0, + '1': 2, + '2': 0 + }; + actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 1, + '0': 1 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + actual = sliceAssign( x, y, new Slice( 1, 1 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Broadcasting: + x = { + 'length': 1, + '0': 1 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 1, + '1': 1, + '2': 1 + }; + actual = sliceAssign( x, y, new Slice(), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = { + 'length': 1, + '0': 3 + }; + y = { + 'length': 3, + '0': 0, + '1': 0, + '2': 0 + }; + + expected = { + 'length': 3, + '0': 3, + '1': 0, + '2': 3 + }; + actual = sliceAssign( x, y, new Slice( null, null, 2 ), false ); + + t.strictEqual( actual, y, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); diff --git a/base/fancy-slice/README.md b/base/fancy-slice/README.md new file mode 100644 index 00000000..0e709512 --- /dev/null +++ b/base/fancy-slice/README.md @@ -0,0 +1,161 @@ + + +# slice + +> Return a shallow copy of a portion of an array. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var slice = require( '@stdlib/array/base/fancy-slice' ); +``` + +#### slice( x, s, strict ) + +Returns a shallow copy of a portion of an array. + +```javascript +var Slice = require( '@stdlib/slice/ctor' ); + +var x = [ 1, 2, 3, 4, 5, 6 ]; + +var s = new Slice( 1, 4 ); +var out = slice( x, s, false ); +// returns [ 2, 3, 4 ] + +var bool = ( out === x ); +// returns false +``` + +The function supports the following parameters: + +- **x**: input array. +- **s**: [slice][@stdlib/slice/ctor] object. +- **strict**: boolean indicating whether to enforce strict bounds checking. + +
+ + + + + +
+ +## Notes + +- If provided an array-like object having an unknown [data type][@stdlib/array/dtype], the function copies input array elements to a new generic array. + +
+ + + + + +
+ +## Examples + + + +```javascript +var zeroTo = require( '@stdlib/array/zero-to' ); +var Slice = require( '@stdlib/slice/ctor' ); +var slice = require( '@stdlib/array/base/fancy-slice' ); + +var x = zeroTo( 10, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +var s = new Slice(); +var y = slice( x, s, false ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +s = new Slice( null, null, -2 ); +y = slice( x, s, false ); +// returns [ 9, 7, 5, 3, 1 ] + +s = new Slice( -2, null, -2 ); +y = slice( x, s, false ); +// returns [ 8, 6, 4, 2, 0 ] + +s = new Slice( 2, -2 ); +y = slice( x, s, false ); +// returns [ 2, 3, 4, 5, 6, 7 ] + +s = new Slice( 2, 5 ); +y = slice( x, s, false ); +// returns [ 2, 3, 4 ] + +s = new Slice( 4, 1, -1 ); +y = slice( x, s, false ); +// returns [ 4, 3, 2 ] + +s = new Slice( 5 ); +y = slice( x, s, false ); +// returns [ 0, 1, 2, 3, 4 ] + +s = new Slice( 5, null ); +y = slice( x, s, false ); +// returns [ 5, 6, 7, 8, 9 ] +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/base/fancy-slice/benchmark/benchmark.float64.js b/base/fancy-slice/benchmark/benchmark.float64.js new file mode 100644 index 00000000..04217ae2 --- /dev/null +++ b/base/fancy-slice/benchmark/benchmark.float64.js @@ -0,0 +1,104 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var isCollection = require( '@stdlib/assert/is-collection' ); +var zeroTo = require( './../../../zero-to' ); +var Slice = require( '@stdlib/slice/ctor' ); +var pkg = require( './../package.json' ).name; +var slice = require( './../lib' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var x = zeroTo( len, 'float64' ); + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var values; + var out; + var i; + + values = [ + new Slice(), + new Slice(), + new Slice() + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = slice( x, values[ i%values.length ], false ); + if ( out.length !== len ) { + b.fail( 'unexpected length' ); + } + } + b.toc(); + if ( !isCollection( out ) ) { + b.fail( 'should return an array' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var f; + var i; + + min = 1; // 10^min + max = 6; // 10^max + + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + f = createBenchmark( len ); + bench( pkg+':dtype=float64,len='+len, f ); + } +} + +main(); diff --git a/base/fancy-slice/benchmark/benchmark.generic.js b/base/fancy-slice/benchmark/benchmark.generic.js new file mode 100644 index 00000000..90ca5128 --- /dev/null +++ b/base/fancy-slice/benchmark/benchmark.generic.js @@ -0,0 +1,104 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var isCollection = require( '@stdlib/assert/is-collection' ); +var zeroTo = require( './../../../zero-to' ); +var Slice = require( '@stdlib/slice/ctor' ); +var pkg = require( './../package.json' ).name; +var slice = require( './../lib' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var x = zeroTo( len, 'generic' ); + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var values; + var out; + var i; + + values = [ + new Slice(), + new Slice(), + new Slice() + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = slice( x, values[ i%values.length ], false ); + if ( out.length !== len ) { + b.fail( 'unexpected length' ); + } + } + b.toc(); + if ( !isCollection( out ) ) { + b.fail( 'should return an array' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var f; + var i; + + min = 1; // 10^min + max = 6; // 10^max + + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + f = createBenchmark( len ); + bench( pkg+':dtype=generic,len='+len, f ); + } +} + +main(); diff --git a/base/fancy-slice/docs/repl.txt b/base/fancy-slice/docs/repl.txt new file mode 100644 index 00000000..69d27957 --- /dev/null +++ b/base/fancy-slice/docs/repl.txt @@ -0,0 +1,32 @@ + +{{alias}}( x, s, strict ) + Returns a shallow copy of a portion of an array. + + If provided an array-like object having an unknown data type, the function + copies input array elements to a new generic array. + + Parameters + ---------- + x: ArrayLikeObject + Input array. + + s: Slice + Slice object. + + strict: boolean + Boolean indicating whether to enforce strict bounds checking. + + Returns + ------- + out: Array|TypedArray|Object + Output array. + + Examples + -------- + > var s = new {{alias:@stdlib/slice/ctor}}( 1, 3 ); + > var out = {{alias}}( [ 1, 2, 3, 4 ], s, false ) + [ 2, 3 ] + + See Also + -------- + diff --git a/base/fancy-slice/docs/types/index.d.ts b/base/fancy-slice/docs/types/index.d.ts new file mode 100644 index 00000000..b6e6b334 --- /dev/null +++ b/base/fancy-slice/docs/types/index.d.ts @@ -0,0 +1,256 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +import { Collection, Complex128Array, Complex64Array, AccessorArrayLike } from '@stdlib/types/array'; +import { Slice } from '@stdlib/types/slice'; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Float64Array = require( '@stdlib/array/float64' ); +* +* var x = new Float64Array( [ 1.0, 2.0, 3.0 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3.0, 2.0, 1.0 ] +*/ +declare function slice( x: Float64Array, s: Slice, strict: boolean ): Float64Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Float32Array = require( '@stdlib/array/float32' ); +* +* var x = new Float32Array( [ 1.0, 2.0, 3.0 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3.0, 2.0, 1.0 ] +*/ +declare function slice( x: Float32Array, s: Slice, strict: boolean ): Float32Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int32Array = require( '@stdlib/array/int32' ); +* +* var x = new Int32Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Int32Array, s: Slice, strict: boolean ): Int32Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int16Array = require( '@stdlib/array/int16' ); +* +* var x = new Int16Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Int16Array, s: Slice, strict: boolean ): Int16Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Int8Array = require( '@stdlib/array/int8' ); +* +* var x = new Int8Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Int8Array, s: Slice, strict: boolean ): Int8Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint32Array = require( '@stdlib/array/uint32' ); +* +* var x = new Uint32Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Uint32Array, s: Slice, strict: boolean ): Uint32Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint16Array = require( '@stdlib/array/uint16' ); +* +* var x = new Uint16Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Uint16Array, s: Slice, strict: boolean ): Uint16Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint8Array = require( '@stdlib/array/uint8' ); +* +* var x = new Uint8Array( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Uint8Array, s: Slice, strict: boolean ): Uint8Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Uint8ClampedArray = require( '@stdlib/array/uint8c' ); +* +* var x = new Uint8ClampedArray( [ 1, 2, 3 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 3, 2, 1 ] +*/ +declare function slice( x: Uint8ClampedArray, s: Slice, strict: boolean ): Uint8ClampedArray; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Complex128Array = require( '@stdlib/array/complex128' ); +* +* var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 5.0, 6.0, 3.0, 4.0, 1.0, 2.0 ] +*/ +declare function slice( x: Complex128Array, s: Slice, strict: boolean ): Complex128Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var Complex64Array = require( '@stdlib/array/complex64' ); +* +* var x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 5.0, 6.0, 3.0, 4.0, 1.0, 2.0 ] +*/ +declare function slice( x: Complex64Array, s: Slice, strict: boolean ): Complex64Array; + +/** +* Returns a shallow copy of a portion of an array. +* +* @param x - input array +* @param s - slice object +* @param strict - boolean indicating whether to enforce strict bounds checking +* @returns output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = [ 1, 2, 3, 4, 5, 6 ]; +* +* var out = slice( x, new Slice( null, null, -1 ), false ); +* // returns [ 6, 5, 4, 3, 2, 1 ] +*/ +declare function slice( x: Collection | AccessorArrayLike, s: Slice, strict: boolean ): Array; + + +// EXPORTS // + +export = slice; diff --git a/base/fancy-slice/docs/types/test.ts b/base/fancy-slice/docs/types/test.ts new file mode 100644 index 00000000..0026474c --- /dev/null +++ b/base/fancy-slice/docs/types/test.ts @@ -0,0 +1,99 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import Complex128Array = require( './../../../../complex128' ); +import Complex64Array = require( './../../../../complex64' ); +import Slice = require( '@stdlib/slice/ctor' ); +import slice = require( './index' ); + + +// TESTS // + +// The function returns an array... +{ + slice( [ 1, 2, 3 ], new Slice(), false ); // $ExpectType number[] + slice( new Float64Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Float64Array + slice( new Float32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Float32Array + slice( new Int32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int32Array + slice( new Int16Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int16Array + slice( new Int8Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Int8Array + slice( new Uint32Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint32Array + slice( new Uint16Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint16Array + slice( new Uint8Array( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint8Array + slice( new Uint8ClampedArray( [ 1, 2, 3 ] ), new Slice(), false ); // $ExpectType Uint8ClampedArray + slice( new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), false ); // $ExpectType Complex128Array + slice( new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), false ); // $ExpectType Complex64Array + + slice( [ 1, 2, 3 ], new Slice(), true ); // $ExpectType number[] + slice( new Float64Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Float64Array + slice( new Float32Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Float32Array + slice( new Int32Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Int32Array + slice( new Int16Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Int16Array + slice( new Int8Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Int8Array + slice( new Uint32Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Uint32Array + slice( new Uint16Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Uint16Array + slice( new Uint8Array( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Uint8Array + slice( new Uint8ClampedArray( [ 1, 2, 3 ] ), new Slice(), true ); // $ExpectType Uint8ClampedArray + slice( new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), true ); // $ExpectType Complex128Array + slice( new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ), new Slice(), true ); // $ExpectType Complex64Array +} + +// The compiler throws an error if the function is provided a first argument which is not a collection... +{ + slice( 5, new Slice(), false ); // $ExpectError + slice( true, new Slice(), false ); // $ExpectError + slice( false, new Slice(), false ); // $ExpectError + slice( null, new Slice(), false ); // $ExpectError + slice( void 0, new Slice(), false ); // $ExpectError + slice( {}, new Slice(), false ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a slice object... +{ + const x = [ 1, 2, 3 ]; + + slice( x, '5', false ); // $ExpectError + slice( x, true, false ); // $ExpectError + slice( x, false, false ); // $ExpectError + slice( x, null, false ); // $ExpectError + slice( x, void 0, false ); // $ExpectError + slice( x, {}, false ); // $ExpectError + slice( x, [], false ); // $ExpectError + slice( x, ( x: number ): number => x, false ); // $ExpectError +} + +// The compiler throws an error if the function is provided a third argument which is not a boolean... +{ + const x = [ 1, 2, 3 ]; + + slice( x, new Slice(), '5' ); // $ExpectError + slice( x, new Slice(), 5 ); // $ExpectError + slice( x, new Slice(), null ); // $ExpectError + slice( x, new Slice(), void 0 ); // $ExpectError + slice( x, new Slice(), {} ); // $ExpectError + slice( x, new Slice(), [] ); // $ExpectError + slice( x, new Slice(), ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + slice(); // $ExpectError + slice( [ 1, 2, 3 ] ); // $ExpectError + slice( [ 1, 2, 3 ], new Slice() ); // $ExpectError + slice( [ 1, 2, 3 ], new Slice(), false, {} ); // $ExpectError +} diff --git a/base/fancy-slice/examples/index.js b/base/fancy-slice/examples/index.js new file mode 100644 index 00000000..8ddee02b --- /dev/null +++ b/base/fancy-slice/examples/index.js @@ -0,0 +1,66 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var zeroTo = require( './../../../zero-to' ); +var Slice = require( '@stdlib/slice/ctor' ); +var slice = require( './../lib' ); + +var x = zeroTo( 10, 'generic' ); +// returns [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +var s = new Slice(); +var y = slice( x, s, false ); +console.log( y ); +// => [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + +s = new Slice( null, null, -2 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 9, 7, 5, 3, 1 ] + +s = new Slice( -2, null, -2 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 8, 6, 4, 2, 0 ] + +s = new Slice( 2, -2 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 2, 3, 4, 5, 6, 7 ] + +s = new Slice( 2, 5 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 2, 3, 4 ] + +s = new Slice( 4, 1, -1 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 4, 3, 2 ] + +s = new Slice( 5 ); +y = slice( x, s, false ); +console.log( y ); +// => [ 0, 1, 2, 3, 4 ] + +s = new Slice( 5, null ); +y = slice( x, s, false ); +console.log( y ); +// => [ 5, 6, 7, 8, 9 ] diff --git a/base/fancy-slice/lib/index.js b/base/fancy-slice/lib/index.js new file mode 100644 index 00000000..e2d570d9 --- /dev/null +++ b/base/fancy-slice/lib/index.js @@ -0,0 +1,65 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Return a shallow copy of a portion of an array. +* +* @module @stdlib/array/base/fancy-slice +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* var slice = require( '@stdlib/array/base/fancy-slice' ); +* +* var x = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var y = slice( x, s, false ); +* // returns [ 8, 6, 4, 2 ] +* +* var out = ( y === x ); +* // returns false +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* var Slice = require( '@stdlib/slice/ctor' ); +* var slice = require( '@stdlib/array/base/fancy-slice' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var y = slice( x, s, false ); +* // returns [ 8, 6, 4, 2 ] +* +* var out = ( y === x ); +* // returns false +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/fancy-slice/lib/main.js b/base/fancy-slice/lib/main.js new file mode 100644 index 00000000..a2031670 --- /dev/null +++ b/base/fancy-slice/lib/main.js @@ -0,0 +1,112 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var normalizeSlice = require( '@stdlib/slice/base/normalize-slice' ); +var sliceLength = require( '@stdlib/slice/base/length' ); +var zeros = require( './../../../base/zeros' ); +var dtype = require( './../../../dtype' ); +var gcopy = require( '@stdlib/blas/base/gcopy' ).ndarray; +var format = require( '@stdlib/string/format' ); + + +// MODULES // + +/** +* Returns a shallow copy of a portion of an array. +* +* @param {Collection} x - input array +* @param {Slice} s - slice object +* @param {boolean} strict - boolean indicating whether to enforce strict bounds checking +* @throws {RangeError} slice exceeds array bounds +* @returns {Collection} output array +* +* @example +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var y = slice( x, s, false ); +* // returns [ 8, 6, 4, 2 ] +* +* var out = ( y === x ); +* // returns false +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* var Slice = require( '@stdlib/slice/ctor' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); +* +* var s = new Slice( null, null, -2 ); +* // returns +* +* var y = slice( x, s, false ); +* // returns [ 8, 6, 4, 2 ] +* +* var out = ( y === x ); +* // returns false +*/ +function slice( x, s, strict ) { + var out; + var len; + var ns; + var dt; + var N; + + len = x.length; + + // Normalize the slice object base on the array length: + ns = normalizeSlice( s, len, true ); + + // Check whether the slice exceeds the array bounds... + if ( ns.code ) { + if ( strict ) { + throw new RangeError( format( 'invalid argument. Slice exceeds array bounds. Array length: %d.', len ) ); + } + // Normalize again, this time allowing for out-of-bounds indices: + ns = normalizeSlice( s, len, false ); + } + // Compute the slice length: + N = sliceLength( ns ); + + // Resolve the input array data type: + dt = dtype( x ); + + // Allocate an output array: + if ( dt === 'generic' || dt === null ) { // note: if we were provided an "exotic" array object, fallback to always returning a "generic" array + out = zeros( N ); + } else { + out = new x.constructor( N ); // note: this should accommodate array species which inherit from built-in/known constructors and we assume that all constructors support providing a length argument + } + // Copy elements to the output array: + gcopy( N, x, ns.step, ns.start, out, 1, 0 ); + + return out; +} + + +// EXPORTS // + +module.exports = slice; diff --git a/base/fancy-slice/package.json b/base/fancy-slice/package.json new file mode 100644 index 00000000..56485656 --- /dev/null +++ b/base/fancy-slice/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/array/base/fancy-slice", + "version": "0.0.0", + "description": "Return a shallow copy of a portion of an array.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "data", + "structure", + "array", + "generic", + "copy", + "slice", + "shallow", + "fancy", + "subsequence", + "subseq" + ] +} diff --git a/base/fancy-slice/test/test.js b/base/fancy-slice/test/test.js new file mode 100644 index 00000000..e7f732dc --- /dev/null +++ b/base/fancy-slice/test/test.js @@ -0,0 +1,420 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var AccessorArray = require( './../../../base/accessor' ); +var Float64Array = require( './../../../float64' ); +var Int32Array = require( './../../../int32' ); +var isArray = require( '@stdlib/assert/is-array' ); +var isFloat64Array = require( '@stdlib/assert/is-float64array' ); +var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var Slice = require( '@stdlib/slice/ctor' ); +var slice = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof slice, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'when `strict` is `true`, the function throws an error if provided a slice which is out-of-bounds', function test( t ) { + var values; + var i; + + values = [ + new Slice( 10, 20 ), + new Slice( -20, -10 ), + new Slice( 0, 100 ), + new Slice( 0, -100 ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + slice( [ 1, 2, 3, 4 ], value, true ); + }; + } +}); + +tape( 'when `strict` is `false`, the function returns an empty array if provided a slice which is out-of-bounds', function test( t ) { + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + actual = slice( x, new Slice( 10, 20 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, [], 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + actual = slice( x, new Slice( -20, -10 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, new Int32Array( 0 ), 'returns expected value' ); + + x = new AccessorArray( [ 1, 2, 3, 4 ] ); + actual = slice( x, new Slice( 0, -100 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, [], 'returns expected value' ); + + x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + actual = slice( x, new Slice( -10, -20 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, new Float64Array( 0 ), 'returns expected value' ); + + t.end(); +}); + +tape( 'the function slices an array-like object (generic)', function test( t ) { + var expected; + var actual; + var x; + + x = [ 1, 2, 3 ]; + + expected = [ 1, 2, 3 ]; + actual = slice( x, new Slice(), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 3, 2, 1 ]; + actual = slice( x, new Slice( null, null, -1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 3, 1 ]; + actual = slice( x, new Slice( null, null, -2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 1, 3 ]; + actual = slice( x, new Slice( null, null, 2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 2, 3 ]; + actual = slice( x, new Slice( 1, null ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 2 ]; + actual = slice( x, new Slice( 1, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = []; + actual = slice( x, new Slice( 1, 1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function slices an array-like object (float64)', function test( t ) { + var expected; + var actual; + var x; + + x = new Float64Array( [ 1.0, 2.0, 3.0 ] ); + + expected = new Float64Array( [ 1.0, 2.0, 3.0 ] ); + actual = slice( x, new Slice( null ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [ 3.0, 2.0, 1.0 ] ); + actual = slice( x, new Slice( x.length-1, null, -1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [ 3.0, 1.0 ] ); + actual = slice( x, new Slice( x.length-1, null, -2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [ 1.0, 3.0 ] ); + actual = slice( x, new Slice( 0, null, 2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [ 2.0, 3.0 ] ); + actual = slice( x, new Slice( 1, x.length ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [ 2.0 ] ); + actual = slice( x, new Slice( 1, -1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Float64Array( [] ); + actual = slice( x, new Slice( 1, 1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isFloat64Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function slices an array-like object (int32)', function test( t ) { + var expected; + var actual; + var x; + + x = new Int32Array( [ 1, 2, 3 ] ); + + expected = new Int32Array( [ 1, 2, 3 ] ); + actual = slice( x, new Slice( null, null ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Int32Array( [ 1, 3 ] ); + actual = slice( x, new Slice( null, null, 2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Int32Array( [ 2 ] ); + actual = slice( x, new Slice( x.length-2, null, -2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Int32Array( [ 1, 2 ] ); + actual = slice( x, new Slice( x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Int32Array( [ 1 ] ); + actual = slice( x, new Slice( x.length-2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = new Int32Array( [] ); + actual = slice( x, new Slice( 0, x.length-3 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isInt32Array( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function slices an array-like object (accessors)', function test( t ) { + var expected; + var actual; + var x; + + x = new AccessorArray( [ 1, 2, 3, 4 ] ); + + expected = [ 1, 2, 3, 4 ]; + actual = slice( x, new Slice(), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 4, 3, 2, 1 ]; + actual = slice( x, new Slice( null, null, -1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 3, 1 ]; + actual = slice( x, new Slice( x.length-2, null, -2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 2, 4 ]; + actual = slice( x, new Slice( 1, null, 2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 1, 2, 3 ]; + actual = slice( x, new Slice( null, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 2, 3 ]; + actual = slice( x, new Slice( 1, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 3 ]; + actual = slice( x, new Slice( 2, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = []; + actual = slice( x, new Slice( 3, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function slices an array-like object (array-like)', function test( t ) { + var expected; + var actual; + var x; + + x = { + 'length': 4, + '0': 1, + '1': 2, + '2': 3, + '3': 4 + }; + + expected = [ 1, 2, 3, 4 ]; + actual = slice( x, new Slice( 0, x.length ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 4, 3, 2 ]; + actual = slice( x, new Slice( x.length-1, 0, -1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 4, 2 ]; + actual = slice( x, new Slice( x.length-1, 0, -2 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 1, 2, 3 ]; + actual = slice( x, new Slice( 0, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 2, 3 ]; + actual = slice( x, new Slice( 1, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = [ 3 ]; + actual = slice( x, new Slice( 2, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = []; + actual = slice( x, new Slice( 3, x.length-1 ), false ); + + t.notEqual( actual, x, 'returns different reference' ); + t.strictEqual( isArray( actual ), true, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an empty array if provided an array of length `0`', function test( t ) { + var expected; + var actual; + + expected = []; + actual = slice( [], new Slice(), false ); + + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = []; + actual = slice( new Float64Array( 0 ), new Slice(), false ); + + t.deepEqual( actual, expected, 'returns expected value' ); + + expected = []; + actual = slice( new AccessorArray( [] ), new Slice(), false ); + + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); diff --git a/base/lib/index.js b/base/lib/index.js index 2ab06da2..faaa9a1d 100644 --- a/base/lib/index.js +++ b/base/lib/index.js @@ -459,6 +459,24 @@ setReadOnly( ns, 'everyBy', require( './../../base/every-by' ) ); */ setReadOnly( ns, 'everyByRight', require( './../../base/every-by-right' ) ); +/** +* @name fancySlice +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/fancy-slice} +*/ +setReadOnly( ns, 'fancySlice', require( './../../base/fancy-slice' ) ); + +/** +* @name fancySliceAssign +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/fancy-slice-assign} +*/ +setReadOnly( ns, 'fancySliceAssign', require( './../../base/fancy-slice-assign' ) ); + /** * @name filled * @memberof ns diff --git a/lib/index.js b/lib/index.js index 78e6f670..64a0598d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -319,6 +319,15 @@ setReadOnly( ns, 'logspace', require( './../logspace' ) ); */ setReadOnly( ns, 'arrayMinDataType', require( './../min-dtype' ) ); +/** +* @name arrayMostlySafeCasts +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/mostly-safe-casts} +*/ +setReadOnly( ns, 'arrayMostlySafeCasts', require( './../mostly-safe-casts' ) ); + /** * @name anans * @memberof ns diff --git a/mostly-safe-casts/README.md b/mostly-safe-casts/README.md new file mode 100644 index 00000000..939f56ca --- /dev/null +++ b/mostly-safe-casts/README.md @@ -0,0 +1,136 @@ + + +# Mostly Safe Casts + +> Return a list of array [data types][@stdlib/array/dtypes] to which a provided array [data type][@stdlib/array/dtypes] can be safely cast and, for floating-point data types, can be downcast. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var mostlySafeCasts = require( '@stdlib/array/mostly-safe-casts' ); +``` + +#### mostlySafeCasts( \[dtype] ) + +If provided a `dtype` argument, returns a list of array [data types][@stdlib/array/dtypes] to which a provided array [data type][@stdlib/array/dtypes] can be safely cast and, for floating-point data types, can be downcast. + +```javascript +var out = mostlySafeCasts( 'float32' ); +// e.g., returns [ 'float32', 'float64', ... ] +``` + +If not provided a `dtype` argument, the function returns a casting table. + +```javascript +var out = mostlySafeCasts(); +// returns {...} + +var f32 = out[ 'float32' ]; +// returns {...} + +var v = f32[ 'float64' ]; +// returns 1 +``` + +If provided an unrecognized or unsupported `dtype`, the function returns `null`. + +```javascript +var out = mostlySafeCasts( 'foo' ); +// returns null +``` + +
+ + + + + +
+ +
+ + + + + +
+ +## Examples + + + +```javascript +var dtypes = require( '@stdlib/array/dtypes' ); +var mostlySafeCasts = require( '@stdlib/array/mostly-safe-casts' ); + +// Get the list of supported array data types: +var DTYPES = dtypes(); + +// Print the list of array data types to which a data type can be cast... +var list; +var i; +for ( i = 0; i < DTYPES.length; i++ ) { + list = mostlySafeCasts( DTYPES[ i ] ); + console.log( '%s: %s', DTYPES[ i ], list.join( ', ' ) ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/mostly-safe-casts/benchmark/benchmark.js b/mostly-safe-casts/benchmark/benchmark.js new file mode 100644 index 00000000..14374397 --- /dev/null +++ b/mostly-safe-casts/benchmark/benchmark.js @@ -0,0 +1,71 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var dtypes = require( './../../dtypes' ); +var pkg = require( './../package.json' ).name; +var mostlySafeCasts = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var out; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = mostlySafeCasts(); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::dtype', function benchmark( b ) { + var out; + var dt; + var i; + + dt = dtypes(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = mostlySafeCasts( dt[ i%dt.length ] ); + if ( out.length === 0 ) { + b.fail( 'should not be empty' ); + } + } + b.toc(); + if ( !isStringArray( out ) ) { + b.fail( 'should return an array of strings' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/mostly-safe-casts/docs/repl.txt b/mostly-safe-casts/docs/repl.txt new file mode 100644 index 00000000..ffe97879 --- /dev/null +++ b/mostly-safe-casts/docs/repl.txt @@ -0,0 +1,27 @@ + +{{alias}}( [dtype] ) + Returns a list of array data types to which a provided array data type can + be safely cast and, for floating-point data types, can be downcast. + + If not provided an array data type, the function returns a casting table. + + If provided an unrecognized array data type, the function returns `null`. + + Parameters + ---------- + dtype: any (optional) + Array data type value. + + Returns + ------- + out: Object|Array|null + Array data types to which a data type can be cast. + + Examples + -------- + > var out = {{alias}}( 'float32' ) + + + See Also + -------- + diff --git a/mostly-safe-casts/docs/types/index.d.ts b/mostly-safe-casts/docs/types/index.d.ts new file mode 100644 index 00000000..23eab4ff --- /dev/null +++ b/mostly-safe-casts/docs/types/index.d.ts @@ -0,0 +1,41 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/** +* Returns a list of array data types to which a provided array data type can be safely cast and, for floating-point data types, can be downcast. +* +* ## Notes +* +* - If not provided an array data type, the function returns a casting table. +* - If provided an unrecognized array data type, the function returns `null`. +* +* @param dtype - array data type value +* @returns list of array data types or null +* +* @example +* var list = mostlySafeCasts( 'float32' ); +* // returns [...] +*/ +declare function mostlySafeCasts( dtype?: any ): any; // FIXME: use overloads to improve this definition + + +// EXPORTS // + +export = mostlySafeCasts; diff --git a/mostly-safe-casts/docs/types/test.ts b/mostly-safe-casts/docs/types/test.ts new file mode 100644 index 00000000..8866c042 --- /dev/null +++ b/mostly-safe-casts/docs/types/test.ts @@ -0,0 +1,34 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import mostlySafeCasts = require( './index' ); + + +// TESTS // + +// The function returns an object, array of strings, or null... +{ + mostlySafeCasts(); // $ExpectType any + mostlySafeCasts( 'float32' ); // $ExpectType any + mostlySafeCasts( 'float' ); // $ExpectType any +} + +// The compiler throws an error if the function is provided more than one argument... +{ + mostlySafeCasts( 'float32', 123 ); // $ExpectError +} diff --git a/mostly-safe-casts/examples/index.js b/mostly-safe-casts/examples/index.js new file mode 100644 index 00000000..5e63a45a --- /dev/null +++ b/mostly-safe-casts/examples/index.js @@ -0,0 +1,33 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var dtypes = require( './../../dtypes' ); +var mostlySafeCasts = require( './../lib' ); + +// Get the list of supported array data types: +var DTYPES = dtypes(); + +// Print the list of array data types to which a data type can be cast... +var list; +var i; +for ( i = 0; i < DTYPES.length; i++ ) { + list = mostlySafeCasts( DTYPES[ i ] ); + console.log( '%s: %s', DTYPES[ i ], list.join( ', ' ) ); +} diff --git a/mostly-safe-casts/lib/data.json b/mostly-safe-casts/lib/data.json new file mode 100644 index 00000000..b120b5b8 --- /dev/null +++ b/mostly-safe-casts/lib/data.json @@ -0,0 +1,170 @@ +{ + "float64": { + "float64": 1, + "float32": 1, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "float32": { + "float64": 1, + "float32": 1, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "int32": { + "float64": 1, + "float32": 0, + "int32": 1, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 0, + "generic": 1 + }, + "int16": { + "float64": 1, + "float32": 1, + "int32": 1, + "int16": 1, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "int8": { + "float64": 1, + "float32": 1, + "int32": 1, + "int16": 1, + "int8": 1, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "uint32": { + "float64": 1, + "float32": 0, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 1, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 0, + "generic": 1 + }, + "uint16": { + "float64": 1, + "float32": 1, + "int32": 1, + "int16": 0, + "int8": 0, + "uint32": 1, + "uint16": 1, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "uint8": { + "float64": 1, + "float32": 1, + "int32": 1, + "int16": 1, + "int8": 0, + "uint32": 1, + "uint16": 1, + "uint8": 1, + "uint8c": 1, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "uint8c": { + "float64": 1, + "float32": 1, + "int32": 1, + "int16": 1, + "int8": 0, + "uint32": 1, + "uint16": 1, + "uint8": 1, + "uint8c": 1, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "complex128": { + "float64": 0, + "float32": 0, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "complex64": { + "float64": 0, + "float32": 0, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 1, + "complex64": 1, + "generic": 1 + }, + "generic": { + "float64": 0, + "float32": 0, + "int32": 0, + "int16": 0, + "int8": 0, + "uint32": 0, + "uint16": 0, + "uint8": 0, + "uint8c": 0, + "complex128": 0, + "complex64": 0, + "generic": 1 + } +} diff --git a/mostly-safe-casts/lib/index.js b/mostly-safe-casts/lib/index.js new file mode 100644 index 00000000..14cbc333 --- /dev/null +++ b/mostly-safe-casts/lib/index.js @@ -0,0 +1,40 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Return a list of array data types to which a provided array data type can be safely cast and, for floating-point data types, can be downcast. +* +* @module @stdlib/array/mostly-safe-casts +* +* @example +* var mostlySafeCasts = require( '@stdlib/array/mostly-safe-casts' ); +* +* var list = mostlySafeCasts( 'float32' ); +* // returns [...] +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/mostly-safe-casts/lib/main.js b/mostly-safe-casts/lib/main.js new file mode 100644 index 00000000..c0612a63 --- /dev/null +++ b/mostly-safe-casts/lib/main.js @@ -0,0 +1,135 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var objectKeys = require( '@stdlib/utils/keys' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var resolve = require( '@stdlib/strided/base/dtype-resolve-str' ); +var CASTS = require( './data.json' ); + + +// VARIABLES // + +var TABLE; + + +// FUNCTIONS // + +/** +* Generates a full table of casts for each array data type. +* +* @private +* @returns {Object} table +*/ +function generateFullTable() { + var dtypes; + var ntypes; + var out; + var tmp; + var dt1; + var dt2; + var o; + var j; + var i; + + out = {}; + dtypes = objectKeys( CASTS ); + ntypes = dtypes.length; + for ( i = 0; i < ntypes; i++ ) { + dt1 = dtypes[ i ]; + o = CASTS[ dt1 ]; + tmp = {}; + for ( j = 0; j < ntypes; j++ ) { + dt2 = dtypes[ j ]; + tmp[ dt2 ] = o[ dt2 ]; + } + out[ dt1 ] = tmp; + } + return out; +} + +/** +* Generates a table of casts for each array data type. +* +* @private +* @returns {Object} table +*/ +function generateTable() { + var dtypes; + var ntypes; + var out; + var tmp; + var dt1; + var dt2; + var o; + var j; + var i; + + out = {}; + dtypes = objectKeys( CASTS ); + ntypes = dtypes.length; + for ( i = 0; i < ntypes; i++ ) { + dt1 = dtypes[ i ]; + o = CASTS[ dt1 ]; + tmp = []; + for ( j = 0; j < ntypes; j++ ) { + dt2 = dtypes[ j ]; + if ( o[ dt2 ] === 1 ) { + tmp.push( dt2 ); + } + } + out[ dt1 ] = tmp; + } + return out; +} + + +// MAIN // + +/** +* Returns a list of array data types to which a provided array data type can be safely cast and, for floating-point data types, can be downcast. +* +* @param {*} [dtype] - array data type value +* @returns {(Object|StringArray|null)} list of array data types or null +* +* @example +* var list = mostlySafeCasts( 'float32' ); +* // returns [...] +*/ +function mostlySafeCasts( dtype ) { + if ( arguments.length === 0 ) { + return generateFullTable(); + } + if ( TABLE === void 0 ) { + // Lazily generate table... + TABLE = generateTable(); + } + dtype = resolve( dtype ); + if ( hasOwnProp( TABLE, dtype ) ) { + return TABLE[ dtype ].slice(); + } + return null; +} + + +// EXPORTS // + +module.exports = mostlySafeCasts; diff --git a/mostly-safe-casts/package.json b/mostly-safe-casts/package.json new file mode 100644 index 00000000..5501e85d --- /dev/null +++ b/mostly-safe-casts/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/array/mostly-safe-casts", + "version": "0.0.0", + "description": "Return a list of array data types to which a provided array data type can be safely cast and, for floating-point data types, can be downcast.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdtypes", + "types", + "array", + "casting", + "cast", + "rules", + "promotion", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/mostly-safe-casts/test/test.js b/mostly-safe-casts/test/test.js new file mode 100644 index 00000000..7e1f842f --- /dev/null +++ b/mostly-safe-casts/test/test.js @@ -0,0 +1,75 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var dtypes = require( './../../dtypes' ); +var isStringArray = require( '@stdlib/assert/is-string-array' ).primitives; +var mostlySafeCasts = require( './../lib' ); + + +// VARIABLES // + +var DTYPES = dtypes(); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof mostlySafeCasts, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'if not provided a data type, the function returns a table', function test( t ) { + var out = mostlySafeCasts(); + t.strictEqual( typeof out, 'object', 'returns an object' ); + t.strictEqual( out[ 'float32' ][ 'float64' ], 1, 'returns expected value' ); + t.end(); +}); + +tape( 'the function returns a list of array data types to which a provided array data type can be cast', function test( t ) { + var list; + var i; + for ( i = 0; i < DTYPES.length; i++ ) { + list = mostlySafeCasts( DTYPES[ i ] ); + t.strictEqual( isStringArray( list ), true, 'returns an array of strings when provided '+DTYPES[ i ] ); + } + t.end(); +}); + +tape( 'if provided an unrecognized or unsupported data type, the function returns `null`', function test( t ) { + var values; + var i; + + values = [ + 'beep', + 'boop', + 'foo', + 'bar', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.strictEqual( mostlySafeCasts( values[ i ] ), null, 'returns expected value when provided '+values[ i ] ); + } + t.end(); +}); diff --git a/package.json b/package.json index 066ed331..5b5f661d 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "@stdlib/iter": "github:stdlib-js/iter#main", "@stdlib/math": "github:stdlib-js/math#main", "@stdlib/ndarray": "github:stdlib-js/ndarray#main", + "@stdlib/slice": "github:stdlib-js/slice#main", "@stdlib/strided": "github:stdlib-js/strided#main", "@stdlib/string": "github:stdlib-js/string#main", "@stdlib/symbol": "github:stdlib-js/symbol#main", diff --git a/pool/lib/factory.js b/pool/lib/factory.js index a0341b98..5423e275 100644 --- a/pool/lib/factory.js +++ b/pool/lib/factory.js @@ -32,8 +32,8 @@ var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only var ctors = require( './../../typed-ctors' ); var reinterpret64 = require( '@stdlib/strided/base/reinterpret-complex64' ); var reinterpret128 = require( '@stdlib/strided/base/reinterpret-complex128' ); -var accessors = require( './../../base/accessors' ); -var adtype = require( './../../dtype' ); +var resolveGetter = require( './../../base/resolve-getter' ); +var resolveSetter = require( './../../base/resolve-setter' ); var ARRAY_DEFAULTS = require( './../../defaults' ); var format = require( '@stdlib/string/format' ); var ArrayBuffer = require( './../../buffer' ); @@ -257,9 +257,9 @@ function factory( options ) { out.set( arr ); return out; } - // Wrap the arrays in order to account for the possibility that `arr` is a complex number array. As we don't prohibit other "unsafe" casts (e.g., providing a `Float64Array` and specifying a `dtype` of `uint8`), we don't prohibit providing a complex number array and specifying a real `dtype`. The results will probably be unexpected/gibberish, but I am not sure we should be overly pedantic in ensuring users don't do ill-advised things... - get = accessors( adtype( arr ) ).accessors[ 0 ]; - set = accessors( dtype ).accessors[ 1 ]; + // Resolve element accessors in order to account for the possibility that `arr` is a complex number array. As we don't prohibit other "unsafe" casts (e.g., providing a `Float64Array` and specifying a `dtype` of `uint8`), we don't prohibit providing a complex number array and specifying a real `dtype`. The results will probably be unexpected/gibberish, but I am not sure we should be overly pedantic in ensuring users don't do ill-advised things... + get = resolveGetter( arr ); + set = resolveSetter( out ); for ( i = 0; i < len; i++ ) { set( out, i, get( arr, i ) ); } diff --git a/promotion-rules/README.md b/promotion-rules/README.md index 1fa9bbfb..94f1274b 100644 --- a/promotion-rules/README.md +++ b/promotion-rules/README.md @@ -150,10 +150,10 @@ for ( i = 0; i < DTYPES.length; i++ ) {