From 92a9c5108e840a39c6e819373f887c6295b97e60 Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Tue, 18 Jun 2024 07:08:32 +0000 Subject: [PATCH] Auto-generated commit --- CHANGELOG.md | 47 +- base/put/README.md | 1 + base/put/docs/repl.txt | 6 +- base/put/test/test.js | 2 +- index/README.md | 10 + index/examples/index.js | 10 + index/lib/main.js | 2 + index/test/test.js | 119 ++ lib/index.js | 9 + put/README.md | 170 +++ put/benchmark/benchmark.js | 78 + put/benchmark/benchmark.length.js | 113 ++ put/docs/repl.txt | 57 + put/docs/types/index.d.ts | 223 +++ put/docs/types/test.ts | 100 ++ put/examples/index.js | 41 + put/lib/defaults.js | 42 + put/lib/index.js | 48 + put/lib/main.js | 117 ++ put/lib/validate.js | 67 + put/package.json | 62 + put/test/test.js | 904 +++++++++++ put/test/test.validate.js | 128 ++ to-fancy/README.md | 5 + to-fancy/benchmark/benchmark.set.js | 38 + to-fancy/docs/types/index.d.ts | 114 +- to-fancy/docs/types/test.ts | 2 + to-fancy/examples/index.js | 6 + to-fancy/lib/get_elements.js | 1 - to-fancy/lib/set.js | 5 + to-fancy/lib/set_elements.js | 97 ++ to-fancy/lib/set_slice.js | 3 +- to-fancy/lib/validator.js | 38 +- to-fancy/test/test.set.integer_array.js | 1864 +++++++++++++++++++++++ to-fancy/test/test.set.integers.js | 70 + to-fancy/test/test.set.invalid.js | 131 ++ 36 files changed, 4609 insertions(+), 121 deletions(-) create mode 100644 put/README.md create mode 100644 put/benchmark/benchmark.js create mode 100644 put/benchmark/benchmark.length.js create mode 100644 put/docs/repl.txt create mode 100644 put/docs/types/index.d.ts create mode 100644 put/docs/types/test.ts create mode 100644 put/examples/index.js create mode 100644 put/lib/defaults.js create mode 100644 put/lib/index.js create mode 100644 put/lib/main.js create mode 100644 put/lib/validate.js create mode 100644 put/package.json create mode 100644 put/test/test.js create mode 100644 put/test/test.validate.js create mode 100644 to-fancy/lib/set_elements.js create mode 100644 to-fancy/test/test.set.integer_array.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e3c3c9d..76c70d80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@
-## Unreleased (2024-06-17) +## Unreleased (2024-06-18)
@@ -20,6 +20,7 @@ ##### Features +- [`e1993a6`](https://github.com/stdlib-js/stdlib/commit/e1993a6ee84bd212b5a00210e360b14e2a979f3a) - add `put` to namespace - [`3edcfe5`](https://github.com/stdlib-js/stdlib/commit/3edcfe5d814fd12a56dbe492ddc78663721f5acd) - update namespace TypeScript declarations [(#2303)](https://github.com/stdlib-js/stdlib/pull/2303) - [`f4a14dd`](https://github.com/stdlib-js/stdlib/commit/f4a14dd55d10d1ce0390d24710c2998a3b112313) - add `BooleanArray` to namespace - [`0adcae5`](https://github.com/stdlib-js/stdlib/commit/0adcae51386086e2ef5fb5d78402389cff776deb) - update namespace TypeScript declarations [(#1340)](https://github.com/stdlib-js/stdlib/pull/1340) @@ -1374,6 +1375,7 @@ This release closes the following issue: ##### Features +- [`b834046`](https://github.com/stdlib-js/stdlib/commit/b834046b3c0a54c0eccf7b6abc393402093d0398) - add boolean array support - [`96e896a`](https://github.com/stdlib-js/stdlib/commit/96e896a39be08912b2e06dfb6b671ec13d042412) - add support for boolean array indices - [`248fcf3`](https://github.com/stdlib-js/stdlib/commit/248fcf38684e61e81b14998ed6d24e0fc9283333) - add `array/index` @@ -1576,6 +1578,38 @@ This release closes the following issue: +
+ +#### [@stdlib/array/put](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/put) + +
+ +
+ +##### Features + +- [`58ffc76`](https://github.com/stdlib-js/stdlib/commit/58ffc769c95c9821f65dd095066e9401e468e000) - add `array/put` + +
+ + + +
+ +##### Bug Fixes + +- [`778764b`](https://github.com/stdlib-js/stdlib/commit/778764b2749e6799bfec2d20820f73f0e302fecc) - support collections with unknown data types + +
+ + + +
+ +
+ + +
#### [@stdlib/array/safe-casts](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/safe-casts) @@ -1654,6 +1688,7 @@ This release closes the following issue: ##### Features +- [`b079d65`](https://github.com/stdlib-js/stdlib/commit/b079d653226019925581555fdaf9aa927ec69c0e) - add support for integer array indexing assignment - [`96e896a`](https://github.com/stdlib-js/stdlib/commit/96e896a39be08912b2e06dfb6b671ec13d042412) - add support for boolean array indices - [`962c155`](https://github.com/stdlib-js/stdlib/commit/962c155e95241834642825085dd4aff8c2f875b3) - add boolean array tests - [`415d506`](https://github.com/stdlib-js/stdlib/commit/415d506180557388d51b876c50139f1c9f1a7760) - attach `ArrayIndex` constructor to the main export @@ -1904,6 +1939,16 @@ A total of 13 people contributed to this release. Thank you to the following con
+- [`b079d65`](https://github.com/stdlib-js/stdlib/commit/b079d653226019925581555fdaf9aa927ec69c0e) - **feat:** add support for integer array indexing assignment _(by Athan Reines)_ +- [`b834046`](https://github.com/stdlib-js/stdlib/commit/b834046b3c0a54c0eccf7b6abc393402093d0398) - **feat:** add boolean array support _(by Athan Reines)_ +- [`778764b`](https://github.com/stdlib-js/stdlib/commit/778764b2749e6799bfec2d20820f73f0e302fecc) - **fix:** support collections with unknown data types _(by Athan Reines)_ +- [`e1993a6`](https://github.com/stdlib-js/stdlib/commit/e1993a6ee84bd212b5a00210e360b14e2a979f3a) - **feat:** add `put` to namespace _(by Athan Reines)_ +- [`3503cae`](https://github.com/stdlib-js/stdlib/commit/3503cae80842f44c3a16627edc52fc1384e0ce29) - **docs:** add note _(by Athan Reines)_ +- [`1c809a5`](https://github.com/stdlib-js/stdlib/commit/1c809a5492dd9dc592bda2dbe6a4a6a1bf156bf1) - **docs:** add note _(by Athan Reines)_ +- [`0a4b603`](https://github.com/stdlib-js/stdlib/commit/0a4b6039c6ab0468f01e96db98157fe6c516c2a5) - **docs:** add note _(by Athan Reines)_ +- [`58ffc76`](https://github.com/stdlib-js/stdlib/commit/58ffc769c95c9821f65dd095066e9401e468e000) - **feat:** add `array/put` _(by Athan Reines)_ +- [`ca3bd75`](https://github.com/stdlib-js/stdlib/commit/ca3bd752ba18c92d006ebba9c927e2ee9afefacd) - **test:** update description _(by Athan Reines)_ +- [`2d3329c`](https://github.com/stdlib-js/stdlib/commit/2d3329cd56424e2cea94fc50b3ffcf21af50fcca) - **docs:** fix return type _(by Athan Reines)_ - [`d626ffa`](https://github.com/stdlib-js/stdlib/commit/d626ffac9f0504be236c94afd4b920032272c8bf) - **feat:** update namespace TypeScript declarations [(#2394)](https://github.com/stdlib-js/stdlib/pull/2394) _(by stdlib-bot, Athan Reines)_ - [`915d3e7`](https://github.com/stdlib-js/stdlib/commit/915d3e77ccd6bdb8a8145e5be832e0db50854613) - **docs:** fix missing asterisk _(by Athan Reines)_ - [`6adfd9a`](https://github.com/stdlib-js/stdlib/commit/6adfd9a5b8df1771ac41681f1167c480e8d89c1d) - **docs:** fix missing asterisk _(by Athan Reines)_ diff --git a/base/put/README.md b/base/put/README.md index a8c34782..01a30cea 100644 --- a/base/put/README.md +++ b/base/put/README.md @@ -81,6 +81,7 @@ var bool = ( out === x ); ## Notes - The function mutates the input array `x`. +- Because each index is only validated at the time of replacing a particular element, mutation may occur even when one or more indices are out-of-bounds, including when the index [mode][@stdlib/ndarray/base/ind] indicates to raise an exception.
diff --git a/base/put/docs/repl.txt b/base/put/docs/repl.txt index 411e0946..2cebb7d2 100644 --- a/base/put/docs/repl.txt +++ b/base/put/docs/repl.txt @@ -7,6 +7,10 @@ The function mutates the input array. + Because each index is only validated at the time of replacing a particular + element, mutation may occur even when one or more indices are out-of-bounds, + including when the index mode indicates to raise an exception. + If `indices` is an empty array, the function returns the input array unchanged. @@ -34,7 +38,7 @@ Returns ------- - out: Array + out: ArrayLikeObject Input array. Examples diff --git a/base/put/test/test.js b/base/put/test/test.js index 5ed3badd..d7003594 100644 --- a/base/put/test/test.js +++ b/base/put/test/test.js @@ -146,7 +146,7 @@ tape( 'the function replaces elements in an array (generic)', function test( t ) t.end(); }); -tape( 'the function replaces elements in an array (generic broadcasting)', function test( t ) { +tape( 'the function replaces elements in an array (generic, broadcasting)', function test( t ) { var expected; var indices; var actual; diff --git a/index/README.md b/index/README.md index c82f2fef..135c478d 100644 --- a/index/README.md +++ b/index/README.md @@ -397,6 +397,7 @@ var o = idx.toJSON(); ```javascript var Uint8Array = require( '@stdlib/array/uint8' ); var Int32Array = require( '@stdlib/array/int32' ); +var BooleanArray = require( '@stdlib/array/bool' ); var ArrayIndex = require( '@stdlib/array/index' ); var x = new Uint8Array( [ 1, 0, 1, 0 ] ); @@ -417,6 +418,15 @@ o = ArrayIndex.get( i.id ); console.log( 'Type: %s. Data type: %s.', o.type, o.dtype ); +x = new BooleanArray( [ true, false, true, false ] ); +i = new ArrayIndex( x ); +// returns + +o = ArrayIndex.get( i.id ); +// returns {...} + +console.log( 'Type: %s. Data type: %s.', o.type, o.dtype ); + x = new Int32Array( [ 1, 3, 4, 7 ] ); i = new ArrayIndex( x ); // returns diff --git a/index/examples/index.js b/index/examples/index.js index f64908f4..3adfc357 100644 --- a/index/examples/index.js +++ b/index/examples/index.js @@ -20,6 +20,7 @@ var Uint8Array = require( './../../uint8' ); var Int32Array = require( './../../int32' ); +var BooleanArray = require( './../../bool' ); var ArrayIndex = require( './../lib' ); var x = new Uint8Array( [ 1, 0, 1, 0 ] ); @@ -40,6 +41,15 @@ o = ArrayIndex.get( i.id ); console.log( 'Type: %s. Data type: %s.', o.type, o.dtype ); +x = new BooleanArray( [ true, false, true, false ] ); +i = new ArrayIndex( x ); +// returns + +o = ArrayIndex.get( i.id ); +// returns {...} + +console.log( 'Type: %s. Data type: %s.', o.type, o.dtype ); + x = new Int32Array( [ 1, 3, 4, 7 ] ); i = new ArrayIndex( x ); // returns diff --git a/index/lib/main.js b/index/lib/main.js index 1200a1f3..23bfc90b 100644 --- a/index/lib/main.js +++ b/index/lib/main.js @@ -102,6 +102,8 @@ function ArrayIndex( x ) { t = 'int'; } else if ( dt === 'uint8' ) { t = 'mask'; + } else if ( dt === 'bool' ) { + t = 'bool'; } else { throw new TypeError( 'invalid argument. First argument must be a valid index array.' ); } diff --git a/index/test/test.js b/index/test/test.js index 2fdc3264..1827b4de 100644 --- a/index/test/test.js +++ b/index/test/test.js @@ -26,6 +26,7 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var Uint8Array = require( './../../uint8' ); var Int32Array = require( './../../int32' ); var Float64Array = require( './../../float64' ); +var BooleanArray = require( './../../bool' ); var toAccessorArray = require( './../../base/to-accessor-array' ); var array2json = require( './../../to-json' ); var ArrayIndex = require( './../lib' ); @@ -54,6 +55,9 @@ tape( 'the function is a constructor', function test( t ) { x = new ArrayIndex( new Uint8Array( [ 1, 0, 1 ] ) ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = new ArrayIndex( new BooleanArray( [ 1, 0, 1 ] ) ); + t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = new ArrayIndex( new Int32Array( [ 1, 0, 1 ] ) ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); @@ -75,6 +79,9 @@ tape( 'the function is a constructor (options)', function test( t ) { x = new ArrayIndex( new Uint8Array( [ 1, 0, 1 ] ), {} ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = new ArrayIndex( new BooleanArray( [ 1, 0, 1 ] ), {} ); + t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = new ArrayIndex( new Int32Array( [ 1, 0, 1 ] ), {} ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); @@ -99,6 +106,9 @@ tape( 'the function does not require the `new` keyword', function test( t ) { x = idx( new Uint8Array( [ 1, 0, 1 ] ) ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = idx( new BooleanArray( [ 1, 0, 1 ] ) ); + t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = idx( new Int32Array( [ 1, 0, 1 ] ) ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); @@ -123,6 +133,9 @@ tape( 'the function does not require the `new` keyword (options)', function test x = idx( new Uint8Array( [ 1, 0, 1 ] ), {} ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = idx( new BooleanArray( [ 1, 0, 1 ] ), {} ); + t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); + x = idx( new Int32Array( [ 1, 0, 1 ] ), {} ); t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' ); @@ -306,6 +319,11 @@ tape( 'the function returns an instance having a `data` property which returns t t.strictEqual( idx.data, x, 'returns expected value' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( idx.data, x, 'returns expected value' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -347,6 +365,12 @@ tape( 'the function returns an instance having a `data` property which throws an ArrayIndex.get( idx.id ); t.throws( invalidated( idx ), Error, 'throws an error' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + ArrayIndex.get( idx.id ); + t.throws( invalidated( idx ), Error, 'throws an error' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -392,6 +416,11 @@ tape( 'the function returns an instance having a `dtype` property which returns t.strictEqual( idx.dtype, 'uint8', 'returns expected value' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( idx.dtype, 'bool', 'returns expected value' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -433,6 +462,12 @@ tape( 'the function returns an instance having a `dtype` property which throws a ArrayIndex.get( idx.id ); t.throws( invalidated( idx ), Error, 'throws an error' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + ArrayIndex.get( idx.id ); + t.throws( invalidated( idx ), Error, 'throws an error' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -480,6 +515,11 @@ tape( 'the function returns an instance having an `id` property which returns th t.strictEqual( isString( idx.id ), true, 'returns expected value' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( isString( idx.id ), true, 'returns expected value' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -531,6 +571,12 @@ tape( 'the function returns an instance having an `id` property which throws an ArrayIndex.get( idx.id ); t.throws( invalidated( idx ), Error, 'throws an error' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + ArrayIndex.get( idx.id ); + t.throws( invalidated( idx ), Error, 'throws an error' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -613,6 +659,11 @@ tape( 'the function returns an instance having a `type` property which returns t t.strictEqual( idx.type, 'mask', 'returns expected value' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( idx.type, 'bool', 'returns expected value' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -654,6 +705,12 @@ tape( 'the function returns an instance having a `type` property which throws an ArrayIndex.get( idx.id ); t.throws( invalidated( idx ), Error, 'throws an error' ); + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + idx = new ArrayIndex( x ); + + ArrayIndex.get( idx.id ); + t.throws( invalidated( idx ), Error, 'throws an error' ); + x = [ true, false, true, false ]; idx = new ArrayIndex( x ); @@ -751,6 +808,16 @@ tape( 'the function returns an instance having a custom `toJSON` method', functi actual = idx.toJSON(); t.deepEqual( actual, expected, 'returns expected value' ); + x = new BooleanArray( [ 1, 0, 1, 0 ] ); + idx = new ArrayIndex( x ); + + expected = { + 'type': 'ArrayIndex', + 'data': array2json( x ) + }; + actual = idx.toJSON(); + t.deepEqual( actual, expected, 'returns expected value' ); + x = new Int32Array( [ 1, 2, 3, 4 ] ); idx = new ArrayIndex( x ); @@ -831,6 +898,15 @@ tape( 'attached to the constructor is a `free` method to free an actively cached t.strictEqual( actual, true, 'returns expected value' ); t.strictEqual( idx.isCached, false, 'returns expected value' ); + x = new BooleanArray( [ 1, 0, 1, 0 ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( idx.isCached, true, 'returns expected value' ); + + actual = ArrayIndex.free( idx.id ); + t.strictEqual( actual, true, 'returns expected value' ); + t.strictEqual( idx.isCached, false, 'returns expected value' ); + x = new Uint8Array( [ 1, 0, 1, 0 ] ); idx = new ArrayIndex( x ); @@ -889,6 +965,15 @@ tape( 'attached to the constructor is a `free` method to free an actively cached t.strictEqual( actual, true, 'returns expected value' ); t.strictEqual( idx.isCached, false, 'returns expected value' ); + x = new BooleanArray( [ 1, 0, 1, 0 ] ); + idx = new ArrayIndex( x, opts ); + + t.strictEqual( idx.isCached, true, 'returns expected value' ); + + actual = ArrayIndex.free( idx.id ); + t.strictEqual( actual, true, 'returns expected value' ); + t.strictEqual( idx.isCached, false, 'returns expected value' ); + x = new Uint8Array( [ 1, 0, 1, 0 ] ); idx = new ArrayIndex( x, opts ); @@ -974,6 +1059,20 @@ tape( 'attached to the constructor is a `free` method which returns `false` if a actual = ArrayIndex.free( id ); t.strictEqual( actual, false, 'returns expected value' ); + // Boolean: + x = new BooleanArray( [ true, false, true, false ] ); + idx = new ArrayIndex( x ); + + t.strictEqual( idx.isCached, true, 'returns expected value' ); + + id = idx.id; + actual = ArrayIndex.free( id ); + t.strictEqual( actual, true, 'returns expected value' ); + t.strictEqual( idx.isCached, false, 'returns expected value' ); + + actual = ArrayIndex.free( id ); + t.strictEqual( actual, false, 'returns expected value' ); + // Mask: x = new Uint8Array( [ 1, 0, 1, 0 ] ); idx = new ArrayIndex( x ); @@ -1061,6 +1160,18 @@ tape( 'attached to the constructor is a `get` method to return index array data' t.deepEqual( actual, expected, 'returns expected value' ); t.strictEqual( actual.data, x, 'returns expected value' ); + x = new BooleanArray( [ 1, 0, 1, 0 ] ); + idx = new ArrayIndex( x ); + + expected = { + 'data': x, + 'type': 'bool', + 'dtype': 'bool' + }; + actual = ArrayIndex.get( idx.id ); + t.deepEqual( actual, expected, 'returns expected value' ); + t.strictEqual( actual.data, x, 'returns expected value' ); + x = new Uint8Array( [ 1, 0, 1, 0 ] ); idx = new ArrayIndex( x ); @@ -1175,6 +1286,14 @@ tape( 'attached to the constructor is a `get` method which returns `null` if una actual = ArrayIndex.get( id ); t.strictEqual( actual, null, 'returns expected value' ); + x = new BooleanArray( [ 1, 0, 1, 0 ] ); + idx = new ArrayIndex( x ); + + id = idx.id; + ArrayIndex.free( id ); + actual = ArrayIndex.get( id ); + t.strictEqual( actual, null, 'returns expected value' ); + x = new Uint8Array( [ 1, 0, 1, 0 ] ); idx = new ArrayIndex( x ); diff --git a/lib/index.js b/lib/index.js index 1aaf0ac9..19f4f14f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -454,6 +454,15 @@ setReadOnly( ns, 'typedarraypool', require( './../pool' ) ); */ setReadOnly( ns, 'promotionRules', require( './../promotion-rules' ) ); +/** +* @name put +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/put} +*/ +setReadOnly( ns, 'put', require( './../put' ) ); + /** * @name typedarrayReviver * @memberof ns diff --git a/put/README.md b/put/README.md new file mode 100644 index 00000000..7a26708d --- /dev/null +++ b/put/README.md @@ -0,0 +1,170 @@ + + +# put + +> Replace specified elements of an array with provided values. + +
+ +## Usage + +```javascript +var put = require( '@stdlib/array/put' ); +``` + +#### put( x, indices, values\[, options] ) + +Replaces specified elements of an array with provided values. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = put( x, [ 1, 3 ], [ 20, 40 ] ); +// returns [ 1, 20, 3, 40 ] + +var bool = ( out === x ); +// returns true +``` + +The function supports the following parameters: + +- **x**: input array. +- **indices**: list of indices. +- **values**: values to set. When `indices` contains one or more elements, `values` must be broadcast [compatible][@stdlib/ndarray/base/broadcast-shapes] with `indices` (i.e., must have either one element or the same number of elements as `indices`). +- **options**: function options. + +The function supports the following options: + +- **mode**: index [mode][@stdlib/ndarray/base/ind]. Default: `'normalize'`. + +If `indices` is an empty array, the function returns the input array unchanged. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = put( x, [], [ 20, 40 ] ); +// returns [ 1, 2, 3, 4 ] +``` + +The function supports broadcasting a `values` array containing a single element against an `indices` array containing one or more elements. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = put( x, [ 1, 3 ], [ 20 ] ); +// returns [ 1, 20, 3, 20 ] +``` + +By default, the function normalizes negative integer indices to positive integer index equivalents. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = put( x, [ -3, -1 ], [ 20, 40 ] ); +// returns [ 1, 20, 3, 40 ] +``` + +To specify an alternative index [mode][@stdlib/ndarray/base/ind], provide a `mode` option. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = put( x, [ -10, 10 ], [ 20, 40 ], { + 'mode': 'clamp' +}); +// returns [ 20, 2, 3, 40 ] +``` + +
+ + + +
+ +## Notes + +- The function mutates the input array `x`. +- Because each index is only validated at the time of replacing a particular element, mutation may occur even when one or more indices are out-of-bounds, including when the index [mode][@stdlib/ndarray/base/ind] indicates to raise an exception. +- The `values` array must have a [data type][@stdlib/array/dtypes] which can be [safely cast][@stdlib/array/safe-casts] to the input 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'` values array can be assigned to corresponding elements in a `'float32'` input array). + +
+ + + +
+ +## Examples + + + +```javascript +var filledBy = require( '@stdlib/array/base/filled-by' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var linspace = require( '@stdlib/array/base/linspace' ); +var put = require( '@stdlib/array/put' ); + +// Generate a linearly spaced array: +var x = linspace( 0, 100, 11 ); +console.log( x ); + +// Generate an array of random indices: +var N = discreteUniform( 5, 15 ); +var indices = filledBy( N, discreteUniform.factory( 0, x.length-1 ) ); +console.log( indices ); + +// Generate an array of random values: +var values = filledBy( N, discreteUniform.factory( 1000, 2000 ) ); +console.log( values ); + +// Update a random sample of elements in `x`: +var out = put( x, indices, values ); +console.log( out ); +``` + +
+ + + + + + + + + + + + + + diff --git a/put/benchmark/benchmark.js b/put/benchmark/benchmark.js new file mode 100644 index 00000000..c1c50409 --- /dev/null +++ b/put/benchmark/benchmark.js @@ -0,0 +1,78 @@ +/** +* @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 isArray = require( '@stdlib/assert/is-array' ); +var zeroTo = require( './../../base/zero-to' ); +var pkg = require( './../package.json' ).name; +var put = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::no_broadcasting:len=100', function benchmark( b ) { + var idx; + var x; + var i; + var v; + + x = zeroTo( 100 ); + idx = zeroTo( 100 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = put( x, idx, x ); + if ( typeof v !== 'object' ) { + b.fail( 'should return an array' ); + } + } + b.toc(); + if ( !isArray( v ) ) { + b.fail( 'should return an array' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::broadcasting:len=100', function benchmark( b ) { + var idx; + var x; + var i; + var v; + + x = zeroTo( 100 ); + idx = zeroTo( 100 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = put( x, idx, [ i ] ); + if ( typeof v !== 'object' ) { + b.fail( 'should return an array' ); + } + } + b.toc(); + if ( !isArray( v ) ) { + b.fail( 'should return an array' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/put/benchmark/benchmark.length.js b/put/benchmark/benchmark.length.js new file mode 100644 index 00000000..0f57eada --- /dev/null +++ b/put/benchmark/benchmark.length.js @@ -0,0 +1,113 @@ +/** +* @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 discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); +var zeroTo = require( './../../base/zero-to' ); +var isArray = require( '@stdlib/assert/is-array' ); +var pkg = require( './../package.json' ).name; +var put = require( './../lib' ); + + +// VARIABLES // + +var opts = { + 'dtype': 'generic' +}; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var values; + var idx; + var x; + + x = discreteUniform( len, 0, 10, opts ); + idx = zeroTo( len ); + values = [ + discreteUniform( len, -10, 0, opts ), + discreteUniform( len, 0, 10, opts ) + ]; + + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var v; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = put( x, idx, values[ i%values.length ] ); + if ( typeof v !== 'object' ) { + b.fail( 'should return an array' ); + } + } + b.toc(); + if ( !isArray( v ) ) { + 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+':len='+len, f ); + } +} + +main(); diff --git a/put/docs/repl.txt b/put/docs/repl.txt new file mode 100644 index 00000000..f18926db --- /dev/null +++ b/put/docs/repl.txt @@ -0,0 +1,57 @@ + +{{alias}}( x, indices, values[, options] ) + Replaces specified elements of an array with provided values. + + The function supports broadcasting a `values` array containing a single + element against an `indices` array containing one or more elements. + + The function mutates the input array. + + Because each index is only validated at the time of replacing a particular + element, mutation may occur even when one or more indices are out-of-bounds, + including when the index mode indicates to raise an exception. + + If `indices` is an empty array, the function returns the input array + unchanged. + + Parameters + ---------- + x: ArrayLikeObject + Input array. + + indices: ArrayLikeObject + List of element indices. + + values: ArrayLikeObject + Values to set. When `indices` contains one or more elements, `values` + must be broadcast compatible with `indices` (i.e., must have either one + element or the same number of elements as `indices`). + + options: Object (optional) + Function options. + + options.mode: string (optional) + Specifies how to handle an index outside the interval [0, max], where + `max` is the maximum possible array index. If equal to 'throw', the + function throws an error. If equal to 'normalize', the function throws + an error if provided an out-of-bounds normalized index. If equal to + 'wrap', the function wraps around an index using modulo arithmetic. If + equal to 'clamp', the function sets an index to either 0 (minimum index) + or the maximum index. Default: 'normalize'. + + Returns + ------- + out: ArrayLikeObject + Input array. + + Examples + -------- + > var x = [ 1, 2, 3, 4 ]; + > var out = {{alias}}( x, [ 1, 3 ], [ 20, 40 ] ) + [ 1, 20, 3, 40 ] + > var bool = ( out === x ) + true + + See Also + -------- + diff --git a/put/docs/types/index.d.ts b/put/docs/types/index.d.ts new file mode 100644 index 00000000..eb81faeb --- /dev/null +++ b/put/docs/types/index.d.ts @@ -0,0 +1,223 @@ +/* +* @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, AccessorArrayLike, TypedArray, ComplexTypedArray, BooleanTypedArray } from '@stdlib/types/array'; +import { ComplexLike } from '@stdlib/types/complex'; +import { Mode } from '@stdlib/types/ndarray'; + +/** +* Index array. +*/ +type IndexArray = Collection | AccessorArrayLike; + +/** +* Values array. +*/ +type ValuesArray = Collection | AccessorArrayLike; + +/** +* Interface describing function options. +*/ +interface Options { + /** + * Index mode. + */ + mode?: Mode; +} + +/** +* Replaces specified elements of an array with provided values. +* +* @param x - input array +* @param indices - list of element indices +* @param values - values to set +* @param options - function options +* @returns input array +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4 ] ); +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4 ] ); +* +* var out = put( x, [ 1, 2 ], [ 30 ] ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function put( x: T, indices: IndexArray, values: ValuesArray, options?: Options ): T; + +/** +* Replaces specified elements of an array with provided values. +* +* @param x - input array +* @param indices - list of element indices +* @param values - values to set +* @param options - function options +* @returns input array +* +* @example +* var Complex128Array = require( '@stdlib/array/complex128' ); +* +* var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* +* var indices = [ 1, 2 ]; +* var values = new Complex128Array( [ 20.0, 30.0, 40, 5.0 ] ); +* +* var out = put( x, indices, values ); +* // returns +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var Complex128Array = require( '@stdlib/array/complex128' ); +* +* var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* +* var indices = [ 1, 2 ]; +* var values = new Complex128Array( [ 20.0, 30.0 ] ); +* +* var out = put( x, indices, values ); +* // returns +* +* var bool = ( out === x ); +* // returns true +*/ +declare function put( x: T, indices: IndexArray, values: ValuesArray, options?: Options ): T; + +/** +* Replaces specified elements of an array with provided values. +* +* @param x - input array +* @param indices - list of element indices +* @param values - values to set +* @param options - function options +* @returns input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var out = put( x, [ 1, 2 ], [ 30 ] ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function put( x: Array, indices: IndexArray, values: ValuesArray, options?: Options ): Array; + +/** +* Replaces specified elements of an array with provided values. +* +* @param x - input array +* @param indices - list of element indices +* @param values - values to set +* @param options - function options +* @returns input array +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); +* +* var out = put( x, [ 1, 2 ], [ 30 ] ); +* +* var bool = ( out === x ); +* // returns true +*/ +declare function put( x: AccessorArrayLike, indices: IndexArray, values: ValuesArray, options?: Options ): AccessorArrayLike; + +/** +* Replaces specified elements of an array with provided values. +* +* @param x - input array +* @param indices - list of element indices +* @param values - values to set +* @param options - function options +* @returns input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var out = put( x, [ 1, 2 ], [ 30 ] ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function put( x: Collection, indices: IndexArray, values: ValuesArray, options?: Options ): Collection; + + +// EXPORTS // + +export = put; diff --git a/put/docs/types/test.ts b/put/docs/types/test.ts new file mode 100644 index 00000000..9822cada --- /dev/null +++ b/put/docs/types/test.ts @@ -0,0 +1,100 @@ +/* +* @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 Complex128 = require( '@stdlib/complex/float64' ); +import AccessorArray = require( './../../../base/accessor' ); +import put = require( './index' ); + + +// TESTS // + +// The function returns an array... +{ + put( [ 1, 2, 3, 4 ], [ 1, 3 ], [ 20, 30 ] ); // $ExpectType number[] + put( [ 1, 2, 3, 4 ], [ 1, 3 ], [ 20, 30 ] ); // $ExpectType number[] + put( [ '1', '2', '3', '4' ], [ 1, 3 ], [ 20, 30 ] ); // $ExpectType (string | number)[] + put( [ 1, 2, 3, 4 ], [ 1, 3 ], [ true, true ] ); // $ExpectType (number | boolean)[] + + put( new Int32Array( [ 1, 2, 3, 4 ] ), [ 1, 3 ], [ 20, 30 ] ); // $ExpectType Int32Array + put( new Complex128Array( [ 1, 2, 3, 4 ] ), [ 1, 3 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ] ); // $ExpectType Complex128Array + put( new Complex64Array( [ 1, 2, 3, 4 ] ), [ 1, 3 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ] ); // $ExpectType Complex64Array + put( new AccessorArray( [ 1, 2, 3, 4 ] ), [ 1, 3 ], new AccessorArray( [ 20, 30 ] ) ); // $ExpectType AccessorArrayLike +} + +// The compiler throws an error if the function is provided a first argument which is not an array-like object... +{ + put( 1, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError + put( true, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError + put( false, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError + put( null, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError + put( void 0, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError + put( {}, [ 1, 3 ], [ 20, 30 ] ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not an array-like object containing numbers... +{ + put( [], 1, [ 20, 30 ] ); // $ExpectError + put( [], true, [ 20, 30 ] ); // $ExpectError + put( [], false, [ 20, 30 ] ); // $ExpectError + put( [], null, [ 20, 30 ] ); // $ExpectError + put( [], void 0, [ 20, 30 ] ); // $ExpectError + put( [], {}, [ 20, 30 ] ); // $ExpectError +} + +// The compiler throws an error if the function is provided a third argument which is not an array-like object... +{ + put( [], [ 1, 3 ], 1 ); // $ExpectError + put( [], [ 1, 3 ], true ); // $ExpectError + put( [], [ 1, 3 ], false ); // $ExpectError + put( [], [ 1, 3 ], null ); // $ExpectError + put( [], [ 1, 3 ], void 0 ); // $ExpectError + put( [], [ 1, 3 ], {} ); // $ExpectError +} + +// The compiler throws an error if the function is provided a fourth argument which is not an object... +{ + put( [], [ 1, 3 ], [ 20, 30 ], '1' ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], 1 ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], true ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], false ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], null ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], [] ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided a `mode` option which is not a valid index mode... +{ + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': '1' } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': 1 } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': true } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': false } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': null } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': {} } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': [] } ); // $ExpectError + put( [], [ 1, 3 ], [ 20, 30 ], { 'mode': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + put(); // $ExpectError + put( [] ); // $ExpectError + put( [], [] ); // $ExpectError + put( [], [], [], {}, {} ); // $ExpectError +} diff --git a/put/examples/index.js b/put/examples/index.js new file mode 100644 index 00000000..3d08887f --- /dev/null +++ b/put/examples/index.js @@ -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. +*/ + +'use strict'; + +var filledBy = require( './../../base/filled-by' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var linspace = require( './../../base/linspace' ); +var put = require( './../lib' ); + +// Generate a linearly spaced array: +var x = linspace( 0, 100, 11 ); +console.log( x ); + +// Generate an array of random indices: +var N = discreteUniform( 5, 15 ); +var indices = filledBy( N, discreteUniform.factory( 0, x.length-1 ) ); +console.log( indices ); + +// Generate an array of random values: +var values = filledBy( N, discreteUniform.factory( 1000, 2000 ) ); +console.log( values ); + +// Update a random sample of elements in `x`: +var out = put( x, indices, values ); +console.log( out ); diff --git a/put/lib/defaults.js b/put/lib/defaults.js new file mode 100644 index 00000000..ea262044 --- /dev/null +++ b/put/lib/defaults.js @@ -0,0 +1,42 @@ +/** +* @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'; + +// MAIN // + +/** +* Returns default options. +* +* @private +* @returns {Object} default options +* +* @example +* var o = defaults(); +* // returns {...} +*/ +function defaults() { + return { + 'mode': 'normalize' + }; +} + + +// EXPORTS // + +module.exports = defaults; diff --git a/put/lib/index.js b/put/lib/index.js new file mode 100644 index 00000000..81663e27 --- /dev/null +++ b/put/lib/index.js @@ -0,0 +1,48 @@ +/** +* @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'; + +/** +* Replace specified elements of an array with provided values. +* +* @module @stdlib/array/put +* +* @example +* var put = require( '@stdlib/array/put' ); +* +* var x = [ 1, 2, 3, 4 ]; +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/put/lib/main.js b/put/lib/main.js new file mode 100644 index 00000000..b817e005 --- /dev/null +++ b/put/lib/main.js @@ -0,0 +1,117 @@ +/** +* @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 isRealDataType = require( './../../base/assert/is-real-data-type' ); +var isComplexDataType = require( './../../base/assert/is-complex-floating-point-data-type' ); +var isCollection = require( '@stdlib/assert/is-collection' ); +var base = require( './../../base/put' ); +var dtype = require( './../../dtype' ); +var convert = require( './../../convert' ); +var format = require( '@stdlib/string/format' ); +var defaults = require( './defaults.js' ); +var validate = require( './validate.js' ); + + +// MAIN // + +/** +* Replaces specified elements of an array with provided values. +* +* @param {Collection} x - input array +* @param {IntegerArray} indices - list of indices +* @param {Collection} values - values to set +* @param {Options} [options] - function options +* @param {string} [options.mode='normalize'] - index mode +* @throws {TypeError} first argument must be a collection +* @throws {TypeError} second argument must be a collection +* @throws {TypeError} third argument must be a collection +* @throws {TypeError} options argument must be an object +* @throws {Error} must provide valid options +* @throws {Error} third argument must be broadcast compatible with the second argument +* @throws {TypeError} third argument cannot be safely cast to the data type of the first argument +* @returns {Collection} input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, values ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var indices = [ 1, 2 ]; +* var values = [ 20, 30 ]; +* +* var out = put( x, indices, [ 30 ] ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +function put( x, indices, values ) { + var opts; + var err; + var xdt; + var vdt; + if ( !isCollection( x ) ) { + throw new TypeError( format( 'invalid argument. First argument must be an array-like object. Value: `%s`.', x ) ); + } + if ( !isCollection( indices ) ) { + throw new TypeError( format( 'invalid argument. Second argument must be an array-like object. Value: `%s`.', indices ) ); + } + if ( !isCollection( values ) ) { + throw new TypeError( format( 'invalid argument. Third argument must be an array-like object. Value: `%s`.', values ) ); + } + opts = defaults(); + if ( arguments.length > 3 ) { + err = validate( opts, arguments[ 3 ] ); + if ( err ) { + throw err; + } + } + xdt = dtype( x ) || 'generic'; + vdt = dtype( values ) || 'generic'; + + // Safe casts are always allowed and allow same kind casts (i.e., downcasts) only when the input array data type is floating-point... + if ( !isMostlySafeCast( vdt, xdt ) ) { + throw new TypeError( format( 'invalid argument. Third argument cannot be safely cast to the input array data type. Data types: [%s, %s].', vdt, xdt ) ); + } + // When performing a real-to-complex assignment, interpret the real-valued array as containing real components with implied imaginary components equal to zero and explicitly convert to a complex-valued array... + if ( isComplexDataType( xdt ) && isRealDataType( vdt ) ) { + values = convert( values, xdt ); + } + // Replace values in the input array: + return base( x, indices, values, opts.mode ); +} + + +// EXPORTS // + +module.exports = put; diff --git a/put/lib/validate.js b/put/lib/validate.js new file mode 100644 index 00000000..24e7153e --- /dev/null +++ b/put/lib/validate.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'; + +// MODULES // + +var isObject = require( '@stdlib/assert/is-plain-object' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var isIndexMode = require( '@stdlib/ndarray/base/assert/is-index-mode' ); +var modes = require( '@stdlib/ndarray/index-modes' ); +var format = require( '@stdlib/string/format' ); + + +// MAIN // + +/** +* Validates function options. +* +* @private +* @param {Object} opts - destination object +* @param {Options} options - function options +* @param {string} [options.mode] - index mode +* @returns {(Error|null)} null or an error object +* +* @example +* var opts = {}; +* var options = { +* 'mode': 'normalize' +* }; +* var err = validate( opts, options ); +* if ( err ) { +* throw err; +* } +*/ +function validate( opts, options ) { + if ( !isObject( options ) ) { + return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'mode' ) ) { + opts.mode = options.mode; + if ( !isIndexMode( opts.mode ) ) { + return new TypeError( format( 'invalid option. `%s` option must be one of the following: "%s". Option: `%s`.', 'mode', modes().join( '", "' ), opts.mode ) ); + } + } + return null; +} + + +// EXPORTS // + +module.exports = validate; diff --git a/put/package.json b/put/package.json new file mode 100644 index 00000000..4dba39bd --- /dev/null +++ b/put/package.json @@ -0,0 +1,62 @@ +{ + "name": "@stdlib/array/put", + "version": "0.0.0", + "description": "Replace specified elements of an array with provided values.", + "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", + "utilities", + "utils", + "generic", + "array", + "set", + "replace", + "put", + "update" + ] +} diff --git a/put/test/test.js b/put/test/test.js new file mode 100644 index 00000000..73e3c765 --- /dev/null +++ b/put/test/test.js @@ -0,0 +1,904 @@ +/** +* @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. +*/ + +/* eslint-disable max-len */ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var Float64Array = require( './../../float64' ); +var Float32Array = require( './../../float32' ); +var Complex128Array = require( './../../complex128' ); +var Complex64Array = require( './../../complex64' ); +var Int32Array = require( './../../int32' ); +var Int8Array = require( './../../int8' ); +var BooleanArray = require( './../../bool' ); +var zeros = require( './../../zeros' ); +var toAccessorArray = require( './../../base/to-accessor-array' ); +var isSameComplex64Array = require( '@stdlib/assert/is-same-complex64array' ); +var isSameComplex128Array = require( '@stdlib/assert/is-same-complex128array' ); +var isAccessorArray = require( '@stdlib/assert/is-accessor-array' ); +var put = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof put, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if provided a first argument which is not a collection', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( value, [], [] ); + }; + } +}); + +tape( 'the function throws an error if provided a first argument which is not a collection (options)', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( value, [], [], {} ); + }; + } +}); + +tape( 'the function throws an error if provided a second argument which is not a collection', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( [], value, [] ); + }; + } +}); + +tape( 'the function throws an error if provided a second argument which is not a collection (options)', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( [], value, [], {} ); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which is not a collection', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( [], [], value ); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which is not a collection (options)', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + function noop() {} + ]; + 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() { + put( [], [], value, {} ); + }; + } +}); + +tape( 'the function throws an error if provided an options argument which is not an object', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + [], + function noop() {} + ]; + 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() { + put( [], [], [], value ); + }; + } +}); + +tape( 'the function throws an error if provided a `mode` option which is not a valid index mode', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + 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() { + put( [], [], [], { + 'mode': value + }); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which is not broadcast compatible with the second argument (generic)', function test( t ) { + var values; + var i; + + values = [ + [], + [ 1, 2, 3 ], + [ 1, 2, 3, 4 ], + [ 1, 2, 3, 4, 5 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided an array of length ' + values[ i ].length ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + put( [ 1, 2, 3, 4 ], [ 1, 2 ], value ); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which is not broadcast compatible with the second argument (typed)', function test( t ) { + var values; + var i; + + values = [ + [], + [ 1, 2, 3 ], + [ 1, 2, 3, 4 ], + [ 1, 2, 3, 4, 5 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided an array of length ' + values[ i ].length ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + put( new Int32Array( [ 1, 2, 3, 4 ] ), [ 1, 2 ], value ); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which is not broadcast compatible with the second argument (accessors)', function test( t ) { + var values; + var i; + + values = [ + [], + [ 1, 2, 3 ], + [ 1, 2, 3, 4 ], + [ 1, 2, 3, 4, 5 ] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided an array of length ' + values[ i ].length ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + put( toAccessorArray( [ 1, 2, 3, 4 ] ), toAccessorArray( [ 1, 2 ] ), toAccessorArray( value ) ); + }; + } +}); + +tape( 'the function throws an error if provided a third argument which cannot be safely cast to the input array data type', function test( t ) { + var values; + var x; + var i; + + values = zeros( 5, 'float64' ); + + x = [ + zeros( 5, 'uint8' ), + zeros( 5, 'int8' ), + zeros( 5, 'int16' ), + zeros( 5, 'uint16' ) + ]; + for ( i = 0; i < x.length; i++ ) { + t.throws( badValue( x[ i ] ), TypeError, 'throws an error when provided ' + x[ i ] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + put( value, zeros( 5, 'generic' ), values ); + }; + } +}); + +tape( 'the function replaces elements in an array (generic)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 3 ]; + actual = put( x, indices, [ 20, 40 ] ); + expected = [ 1, 20, 3, 40 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, [ 20, 30, 40, 50 ] ); + expected = [ 1, 30, 3, 50 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, [ 20, 30, 40, 50 ] ); + expected = [ 50, 40, 30, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, [ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ] ); + expected = [ 1, 100, 3, 4 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (generic, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 3 ]; + actual = put( x, indices, [ 20 ] ); + expected = [ 1, 20, 3, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, [ 20 ] ); + expected = [ 1, 20, 3, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, [ 20 ] ); + expected = [ 20, 20, 20, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, [ 100 ] ); + expected = [ 1, 100, 3, 4 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, generic)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 3 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20, 40 ] ) ); + expected = [ 1, 20, 3, 40 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20, 30, 40, 50 ] ) ); + expected = [ 1, 30, 3, 50 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 3, 2, 1, 0 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20, 30, 40, 50 ] ) ); + expected = [ 50, 40, 30, 20 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ] ) ); + expected = [ 1, 100, 3, 4 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, generic, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 3 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20 ] ) ); + expected = [ 1, 20, 3, 20 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20 ] ) ); + expected = [ 1, 20, 3, 20 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 3, 2, 1, 0 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 20 ] ) ); + expected = [ 20, 20, 20, 20 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + indices = toAccessorArray( [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ); + actual = put( toAccessorArray( x ), indices, toAccessorArray( [ 100 ] ) ); + expected = [ 1, 100, 3, 4 ]; + t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' ); + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (int32)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 3 ]; + actual = put( x, indices, new Int32Array( [ 20, 40 ] ) ); + expected = new Int32Array( [ 1, 20, 3, 40 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, new Int32Array( [ 20, 30, 40, 50 ] ) ); + expected = new Int32Array( [ 1, 30, 3, 50 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, new Int32Array( [ 20, 30, 40, 50 ] ) ); + expected = new Int32Array( [ 50, 40, 30, 20 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Upcasting: + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, new Int8Array( [ 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 ] ) ); + expected = new Int32Array( [ 1, 100, 3, 4 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (int32, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 3 ]; + actual = put( x, indices, new Int32Array( [ 20 ] ) ); + expected = new Int32Array( [ 1, 20, 3, 20 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, new Int32Array( [ 20 ] ) ); + expected = new Int32Array( [ 1, 20, 3, 20 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, new Int32Array( [ 20 ] ) ); + expected = new Int32Array( [ 20, 20, 20, 20 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Upcasting: + x = new Int32Array( [ 1, 2, 3, 4 ] ); + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, new Int8Array( [ 100 ] ) ); + expected = new Int32Array( [ 1, 100, 3, 4 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (float64)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 1, 3 ]; + actual = put( x, indices, new Float64Array( [ 20.0, 40.0 ] ) ); + expected = new Float64Array( [ 1.0, 20.0, 3.0, 40.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, new Float64Array( [ 20.0, 30.0, 40.0, 50.0 ] ) ); + expected = new Float64Array( [ 1.0, 30.0, 3.0, 50.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Downcast: + x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, new Float64Array( [ 20.0, 30.0, 40.0, 50.0 ] ) ); + expected = new Float32Array( [ 50.0, 40.0, 30.0, 20.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Upcasting: + x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, new Float64Array( [ 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0 ] ) ); + expected = new Complex128Array( [ 1.0, 2.0, 100.0, 0.0, 5.0, 6.0, 7.0, 8.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (float64, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 1, 3 ]; + actual = put( x, indices, new Float64Array( [ 20.0 ] ) ); + expected = new Float64Array( [ 1.0, 20.0, 3.0, 20.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 1, 1, 3, 3 ]; + actual = put( x, indices, new Float64Array( [ 20.0 ] ) ); + expected = new Float64Array( [ 1.0, 20.0, 3.0, 20.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Downcast: + x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] ); + indices = [ 3, 2, 1, 0 ]; + actual = put( x, indices, new Float64Array( [ 20.0 ] ) ); + expected = new Float32Array( [ 20.0, 20.0, 20.0, 20.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + // Upcasting: + x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + actual = put( x, indices, new Float64Array( [ 100.0 ] ) ); + expected = new Complex128Array( [ 1.0, 2.0, 100.0, 0.0, 5.0, 6.0, 7.0, 8.0 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, complex64)', function test( t ) { + var expected; + var indices; + var actual; + var values; + var x; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new Complex64Array( [ 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0 ] ); + expected = new Complex64Array( [ 1.0, 2.0, 30.0, 40.0, 5.0, 6.0, 70.0, 80.0 ] ); + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' ); + + // Downcast: + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new Complex128Array( [ 10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0 ] ); + expected = new Complex64Array( [ 1.0, 2.0, 30.0, 40.0, 5.0, 6.0, 70.0, 80.0 ] ); + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, complex64, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var values; + var x; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new Complex64Array( [ 100.0, 200.0 ] ); + expected = new Complex64Array( [ 1.0, 2.0, 100.0, 200.0, 5.0, 6.0, 100.0, 200.0 ] ); + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' ); + + // Downcast: + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new Complex128Array( [ 100.0, 200.0 ] ); + expected = new Complex64Array( [ 1.0, 2.0, 100.0, 200.0, 5.0, 6.0, 100.0, 200.0 ] ); + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' ); + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, boolean)', function test( t ) { + var expected; + var indices; + var actual; + var values; + var x; + var v; + var i; + + x = new BooleanArray( [ true, false, false, true ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new BooleanArray( [ false, true, false, true ] ); + expected = [ true, true, false, true ]; + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < indices.length; i++ ) { + v = actual.get( i ); + t.strictEqual( v, expected[ i ], 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, boolean, broadcasting)', function test( t ) { + var expected; + var indices; + var actual; + var values; + var x; + var v; + var i; + + x = new BooleanArray( [ true, false, false, true ] ); + indices = toAccessorArray( [ 1, 1, 3, 3 ] ); + values = new BooleanArray( [ true ] ); + expected = [ true, true, false, true ]; + actual = put( x, indices, values ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < indices.length; i++ ) { + v = actual.get( i ); + t.strictEqual( v, expected[ i ], 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function returns the input array unchanged if provided a second argument which is empty', function test( t ) { + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + actual = put( x, [], [ 5, 6, 7, 8 ] ); + + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, [ 1, 2, 3, 4 ], 'returns expected value' ); + + t.end(); +}); + +tape( 'by default, the function normalizes negative indices', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + + indices = [ -1, -2, -3, -4 ]; + actual = put( x, indices, [ 5, 6, 7, 8 ] ); + expected = [ 8, 7, 6, 5 ]; + + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'by default, the function throws an error if provided an out-of-bounds index', function test( t ) { + var indices; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = [ 2, 50, 1, 2 ]; + + t.throws( badValue, RangeError, 'throws an error' ); + t.end(); + + function badValue() { + put( x, indices, [ 100 ] ); + } +}); + +tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index', function test( t ) { + var indices; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = [ 4, 5, 1, 2 ]; + + t.throws( badValue, RangeError, 'throws an error' ); + t.end(); + + function badValue() { + put( x, indices, [ 200 ], { + 'mode': 'throw' + }); + } +}); + +tape( 'when the "mode" is "normalize", the function normalizes negative indices', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + + indices = [ -1, -2, -3, -4 ]; + actual = put( x, indices, [ 5, 6, 7, 8 ], { + 'mode': 'normalize' + }); + expected = [ 8, 7, 6, 5 ]; + + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index', function test( t ) { + var indices; + var x; + + x = [ 1, 2, 3, 4 ]; + indices = [ 2, 50, 1, 2 ]; + + t.throws( badValue, RangeError, 'throws an error' ); + t.end(); + + function badValue() { + put( x, indices, [ 100 ], { + 'mode': 'normalize' + }); + } +}); + +tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + + indices = [ -10, 10, -5, 5 ]; + actual = put( x, indices, [ 100, 200, 300, 400 ], { + 'mode': 'clamp' + }); + expected = [ 300, 2, 3, 400 ]; + + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices', function test( t ) { + var expected; + var indices; + var actual; + var x; + + x = [ 1, 2, 3, 4 ]; + + indices = [ -10, 10, -5, 5 ]; + actual = put( x, indices, [ 100, 200, 300, 400 ], { + 'mode': 'wrap' + }); + expected = [ 1, 400, 200, 300 ]; + + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); diff --git a/put/test/test.validate.js b/put/test/test.validate.js new file mode 100644 index 00000000..5001a5e6 --- /dev/null +++ b/put/test/test.validate.js @@ -0,0 +1,128 @@ +/** +* @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 validate = require( './../lib/validate.js' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof validate, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns an error if not provided an options object', function test( t ) { + var values; + var err; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + err = validate( {}, values[i] ); + t.strictEqual( err instanceof TypeError, true, 'returns an error when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns an error if provided a `mode` option which is not a valid index mode', function test( t ) { + var values; + var err; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + err = validate( {}, { + 'mode': values[i] + }); + t.strictEqual( err instanceof TypeError, true, 'returns an error when provided '+values[i] ); + } + t.end(); +}); + +tape( 'the function returns `null` if all options are valid', function test( t ) { + var expected; + var options; + var opts; + var err; + + options = { + 'mode': 'throw' + }; + opts = {}; + + expected = { + 'mode': 'throw' + }; + + err = validate( opts, options ); + + t.strictEqual( err, null, 'returns expected value' ); + t.deepEqual( opts, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function ignores unrecognized options', function test( t ) { + var options; + var opts; + var err; + + options = { + 'beep': 'boop', + 'foo': 5, + 'bar': {} + }; + + opts = {}; + + err = validate( opts, options ); + + t.strictEqual( err, null, 'returns expected value' ); + t.deepEqual( opts, {}, 'returns expected value' ); + + t.end(); +}); diff --git a/to-fancy/README.md b/to-fancy/README.md index ddd9788c..ae71c5ef 100644 --- a/to-fancy/README.md +++ b/to-fancy/README.md @@ -456,6 +456,7 @@ im = imag( v ); ```javascript var Uint8Array = require( '@stdlib/array/uint8' ); var Int32Array = require( '@stdlib/array/int32' ); +var BooleanArray = require( '@stdlib/array/bool' ); var array2fancy = require( '@stdlib/array/to-fancy' ); var x = [ 1, 2, 3, 4, 5, 6 ]; @@ -492,6 +493,10 @@ i = idx( [ true, false, false, true, true, true ] ); // boolean array z = y[ i ]; // returns [ 1, -9, -8, 6 ] +i = idx( new BooleanArray( [ true, false, false, true, true, true ] ) ); // boolean array +z = y[ i ]; +// returns [ 1, -9, -8, 6 ] + i = idx( new Uint8Array( [ 0, 0, 1, 0, 0, 1 ] ) ); // mask array z = y[ i ]; // returns [ 1, 2, -9, -8 ] diff --git a/to-fancy/benchmark/benchmark.set.js b/to-fancy/benchmark/benchmark.set.js index 40da6d3e..0f3ef99f 100644 --- a/to-fancy/benchmark/benchmark.set.js +++ b/to-fancy/benchmark/benchmark.set.js @@ -155,3 +155,41 @@ bench( pkg+'::set,subsequence:len=1', opts, function benchmark( b ) { b.pass( 'benchmark finished' ); b.end(); }); + +bench( pkg+'::set,integer_array:len=1', opts, function benchmark( b ) { + var values; + var base; + var opts; + var idx; + var x; + var v; + var i; + + base = zeroTo( 100, 'generic' ); + x = array2fancy( base ); + + opts = { + 'persist': true + }; + values = [ + array2fancy.idx( [ 0 ], opts ), + array2fancy.idx( [ 1 ], opts ), + array2fancy.idx( [ 2 ], opts ) + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + idx = values[ i%values.length ]; + x[ idx ] = i * 2; + v = base[ i%3 ]; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( v ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/to-fancy/docs/types/index.d.ts b/to-fancy/docs/types/index.d.ts index 3fb91698..190fa5b8 100644 --- a/to-fancy/docs/types/index.d.ts +++ b/to-fancy/docs/types/index.d.ts @@ -20,7 +20,7 @@ /// -import { Collection, ArrayLike, AccessorArrayLike, Complex128Array, Complex64Array, ArrayIndexObject } from '@stdlib/types/array'; +import { Collection, ArrayLike, AccessorArrayLike, ComplexTypedArray, TypedArray, BooleanTypedArray, ArrayIndexObject } from '@stdlib/types/array'; import ArrayIndex = require( './../../../index' ); /** @@ -74,17 +74,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1.0, 2.0, 3.0, 4.0 ] - */ - ( x: Float64Array, options?: Options ): Float64Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Float32Array = require( './../../../float32' ); @@ -96,17 +85,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1.0, 2.0, 3.0, 4.0 ] - */ - ( x: Float32Array, options?: Options ): Float32Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Complex128Array = require( './../../../complex128' ); @@ -118,17 +96,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1.0, 2.0, 3.0, 4.0 ] - */ - ( x: Complex128Array, options?: Options ): Complex128Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Complex64Array = require( './../../../complex64' ); @@ -140,17 +107,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1.0, 2.0, 3.0, 4.0 ] - */ - ( x: Complex64Array, options?: Options ): Complex64Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Int32Array = require( './../../../int32' ); @@ -162,17 +118,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Int32Array, options?: Options ): Int32Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Int16Array = require( './../../../int16' ); @@ -184,17 +129,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Int16Array, options?: Options ): Int16Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Int8Array = require( './../../../int8' ); @@ -206,17 +140,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Int8Array, options?: Options ): Int8Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Uint32Array = require( './../../../uint32' ); @@ -228,17 +151,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Uint32Array, options?: Options ): Uint32Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Uint16Array = require( './../../../uint16' ); @@ -250,17 +162,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Uint16Array, options?: Options ): Uint16Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Uint8Array = require( './../../../uint8' ); @@ -272,17 +173,6 @@ interface Array2Fancy { * * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] - */ - ( x: Uint8Array, options?: Options ): Uint8Array; - - /** - * Converts an array to an object supporting fancy indexing. - * - * @param x - input array - * @param options - function options - * @param options.strict - boolean indicating whether to enforce strict bounds checking - * @param options.cache - cache for resolving array index objects - * @returns fancy array * * @example * var Uint8ClampedArray = require( './../../../uint8c' ); @@ -295,7 +185,7 @@ interface Array2Fancy { * var v = y[ ':' ]; * // returns [ 1, 2, 3, 4 ] */ - ( x: Uint8ClampedArray, options?: Options ): Uint8ClampedArray; + ( x: T, options?: Options ): T; /** * Converts an array to an object supporting fancy indexing. diff --git a/to-fancy/docs/types/test.ts b/to-fancy/docs/types/test.ts index 970828fa..3a3d80e7 100644 --- a/to-fancy/docs/types/test.ts +++ b/to-fancy/docs/types/test.ts @@ -38,6 +38,7 @@ import array2fancy = require( './index' ); array2fancy( new Uint8ClampedArray( [ 1, 2, 3 ] ) ); // $ExpectType Uint8ClampedArray array2fancy( new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ) ); // $ExpectType Complex128Array array2fancy( new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ) ); // $ExpectType Complex64Array + array2fancy( new BooleanArray( [ true, false, true ] ) ); // $ExpectType BooleanArray const opts = { 'strict': true @@ -54,6 +55,7 @@ import array2fancy = require( './index' ); array2fancy( new Uint8ClampedArray( [ 1, 2, 3 ] ), opts ); // $ExpectType Uint8ClampedArray array2fancy( new Complex128Array( [ 1, 2, 3, 4, 5, 6 ] ), opts ); // $ExpectType Complex128Array array2fancy( new Complex64Array( [ 1, 2, 3, 4, 5, 6 ] ), opts ); // $ExpectType Complex64Array + array2fancy( new BooleanArray( [ true, false, true ] ), opts ); // $ExpectType BooleanArray } // The compiler throws an error if the function is provided a first argument which is not an array-like value... diff --git a/to-fancy/examples/index.js b/to-fancy/examples/index.js index 37d789a0..978f0067 100644 --- a/to-fancy/examples/index.js +++ b/to-fancy/examples/index.js @@ -20,6 +20,7 @@ var Uint8Array = require( './../../uint8' ); var Int32Array = require( './../../int32' ); +var BooleanArray = require( './../../bool' ); var array2fancy = require( './../lib' ); var x = [ 1, 2, 3, 4, 5, 6 ]; @@ -63,6 +64,11 @@ z = y[ i ]; console.log( z ); // => [ 1, -9, -8, 6 ] +i = idx( new BooleanArray( [ true, false, false, true, true, true ] ) ); // boolean array +z = y[ i ]; +console.log( z ); +// => [ 1, -9, -8, 6 ] + i = idx( new Uint8Array( [ 0, 0, 1, 0, 0, 1 ] ) ); // mask array z = y[ i ]; console.log( z ); diff --git a/to-fancy/lib/get_elements.js b/to-fancy/lib/get_elements.js index 8e8e3252..93c649bd 100644 --- a/to-fancy/lib/get_elements.js +++ b/to-fancy/lib/get_elements.js @@ -36,7 +36,6 @@ var prop2array = require( './prop2array.js' ); * @param {Object} target - target object * @param {string} property - index string * @param {Object} ctx - context object -* @param {boolean} ctx.strict - boolean indicating whether to enforce strict bounds checking * @param {Object} ctx.cache - cache for resolving array index objects * @param {Function} ctx.postGetArray - function to process a retrieved array * @throws {Error} invalid array index diff --git a/to-fancy/lib/set.js b/to-fancy/lib/set.js index 7e7622bd..df65012d 100644 --- a/to-fancy/lib/set.js +++ b/to-fancy/lib/set.js @@ -23,6 +23,8 @@ var isString = require( '@stdlib/assert/is-string' ).isPrimitive; var hasProperty = require( '@stdlib/assert/has-property' ); var isIntegerString = require( './is_integer_string.js' ); +var isArrayIndexString = require( './is_array_index_string.js' ); +var setElements = require( './set_elements.js' ); var setElement = require( './set_element.js' ); var setValue = require( './set_value.js' ); var setSlice = require( './set_slice.js' ); @@ -71,6 +73,9 @@ function factory( ctx ) { if ( hasProperty( property ) || !isString( property ) ) { return setValue( target, property, value, ctx ); } + if ( isArrayIndexString( property ) ) { + return setElements( target, property, value, ctx ); + } out = setSlice( target, property, value, receiver, ctx ); if ( out ) { return out; diff --git a/to-fancy/lib/set_elements.js b/to-fancy/lib/set_elements.js new file mode 100644 index 00000000..47856f9e --- /dev/null +++ b/to-fancy/lib/set_elements.js @@ -0,0 +1,97 @@ +/** +* @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 isCollection = require( '@stdlib/assert/is-collection' ); +var scalar2array = require( './../../from-scalar' ); +var put = require( './../../put' ); +var format = require( '@stdlib/string/format' ); +var prop2array = require( './prop2array.js' ); +var errMessage = require( './error_message.js' ); + + +// MAIN // + +/** +* Replaces the elements specified by an array index. +* +* @private +* @param {Object} target - target object +* @param {string} property - index string +* @param {*} value - new value(s) +* @param {Object} ctx - context object +* @param {string} ctx.dtype - array data type +* @param {Object} ctx.cache - cache for resolving array index objects +* @param {Function} ctx.validator - function for validating new values +* @param {(Function|null)} ctx.preSetElement - function for normalizing new values (if necessary) +* @throws {Error} invalid array index +* @throws {RangeError} index exceeds array bounds +* @throws {Error} assigned value must be broadcast compatible with target array selection +* @throws {TypeError} assigned value cannot be safely cast to the target array data type +* @throws {TypeError} target array must have a supported data type +* @returns {boolean} boolean indicating whether assignment succeeded +*/ +function setElements( target, property, value, ctx ) { + var idx; + var err; + var v; + + idx = prop2array( property, ctx.cache ); + if ( isCollection( value ) ) { + // When handling collections, we delegate to implementation APIs (see below) to perform argument validation (e.g., ensuring a (mostly) safe cast, broadcast compatibility, etc), so we just reassign the value here: + v = value; + } else { + // When provided a "scalar", we need to check whether the value can be safely cast to the target array data type: + err = ctx.validator( value, ctx.dtype ); + if ( err ) { + throw err; + } + if ( ctx.preSetElement ) { + v = ctx.preSetElement( value ); + } else { + v = value; + } + // As the scalar can be safely cast, convert the scalar to an array having the same data type as the target array to allow for broadcasting during assignment: + v = scalar2array( v, ctx.dtype ); + } + if ( idx.type === 'int' ) { + try { + put( target, idx.data, v ); + } catch ( err ) { + throw new err.constructor( errMessage( err.message ) ); + } + return true; + } + if ( idx.type === 'bool' ) { + // FIXME: where( idx.data, target, value ); + return false; + } + if ( idx.type === 'mask' ) { + // FIXME: where( idx.data, value, target ); + return false; + } + throw new Error( format( 'invalid operation. Unrecognized array index type. Value: `%s`.', idx.type ) ); +} + + +// EXPORTS // + +module.exports = setElements; diff --git a/to-fancy/lib/set_slice.js b/to-fancy/lib/set_slice.js index d23c4778..8b20889f 100644 --- a/to-fancy/lib/set_slice.js +++ b/to-fancy/lib/set_slice.js @@ -40,6 +40,7 @@ var errMessage = require( './error_message.js' ); * @param {Object} ctx - context object * @param {string} ctx.dtype - array data type * @param {boolean} ctx.strict - boolean indicating whether to enforce strict bounds checking +* @param {Function} ctx.validator - function for validating new values * @throws {Error} invalid slice operation * @throws {RangeError} slice exceeds array bounds * @throws {Error} assigned value must be broadcast compatible with target array view @@ -71,10 +72,10 @@ function setSlice( target, property, value, receiver, ctx ) { } try { sliceAssign( v, receiver, s, ctx.strict ); - return true; } catch ( err ) { throw new err.constructor( errMessage( err.message ) ); } + return true; } diff --git a/to-fancy/lib/validator.js b/to-fancy/lib/validator.js index cd66ee3a..c34b0456 100644 --- a/to-fancy/lib/validator.js +++ b/to-fancy/lib/validator.js @@ -22,10 +22,12 @@ var isNumber = require( '@stdlib/assert/is-number' ).isPrimitive; var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive; +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isComplexLike = require( '@stdlib/assert/is-complex-like' ); var isRealFloatingDataType = require( './../../base/assert/is-real-floating-point-data-type' ); var isUnsignedIntegerDataType = require( './../../base/assert/is-unsigned-integer-data-type' ); var isSignedIntegerDataType = require( './../../base/assert/is-signed-integer-data-type' ); +var isBooleanDataType = require( './../../base/assert/is-boolean-data-type' ); var isSafeCast = require( './../../base/assert/is-safe-data-type-cast' ); var minDataType = require( './../../min-dtype' ); var minSignedIntegerDataType = require( './../../base/min-signed-integer-dtype' ); @@ -52,7 +54,32 @@ function validateGeneric() { } /** -* Verifies whether a provided value can be safely assigned to an element in an array have a real-valued floating-point data type. +* Verifies whether a provided value can be safely assigned to an element in an array having a boolean data type. +* +* @private +* @param {*} value - input value +* @param {string} dtype - array data type +* @returns {(Error|null)} error object or null +* +* @example +* var err = validateBoolean( true, 'bool' ); +* // returns null +* +* @example +* var Complex128 = require( '@stdlib/complex/float64/ctor' ); +* +* var err = validateBoolean( new Complex128( 5.0, 6.0 ), 'bool' ); +* // returns +*/ +function validateBoolean( value, dtype ) { + if ( isBoolean( value ) ) { + return null; + } + return new TypeError( format( 'invalid operation. Assigned value cannot be safely cast to the target array data type. Data types: [%s, %s].', typeof value, dtype ) ); +} + +/** +* Verifies whether a provided value can be safely assigned to an element in an array having a real-valued floating-point data type. * * @private * @param {*} value - input value @@ -80,7 +107,7 @@ function validateRealFloating( value, dtype ) { } /** -* Verifies whether a provided value can be safely assigned to an element in an array have a complex-valued floating-point data type. +* Verifies whether a provided value can be safely assigned to an element in an array having a complex-valued floating-point data type. * * @private * @param {*} value - input value @@ -105,7 +132,7 @@ function validateComplexFloating( value, dtype ) { } /** -* Verifies whether a provided value can be safely assigned to an element in an array have a signed integer data type. +* Verifies whether a provided value can be safely assigned to an element in an array having a signed integer data type. * * @private * @param {*} value - input value @@ -139,7 +166,7 @@ function validateSignedInteger( value, dtype ) { } /** -* Verifies whether a provided value can be safely assigned to an element in an array have an unsigned integer data type. +* Verifies whether a provided value can be safely assigned to an element in an array having an unsigned integer data type. * * @private * @param {*} value - input value @@ -201,6 +228,9 @@ function validator( dtype ) { if ( isSignedIntegerDataType( dtype ) ) { return validateSignedInteger; } + if ( isBooleanDataType( dtype ) ) { + return validateBoolean; + } // Case: isComplexDataType( dtype ) === true return validateComplexFloating; } diff --git a/to-fancy/test/test.set.integer_array.js b/to-fancy/test/test.set.integer_array.js new file mode 100644 index 00000000..d46d22dd --- /dev/null +++ b/to-fancy/test/test.set.integer_array.js @@ -0,0 +1,1864 @@ +/** +* @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 hasProxySupport = require( '@stdlib/assert/has-proxy-support' ); +var isSameComplex128Array = require( '@stdlib/assert/is-same-complex128array' ); +var isSameComplex64Array = require( '@stdlib/assert/is-same-complex64array' ); +var Complex128 = require( '@stdlib/complex/float64/ctor' ); +var Float64Array = require( './../../float64' ); +var Float32Array = require( './../../float32' ); +var Int32Array = require( './../../int32' ); +var Int8Array = require( './../../int8' ); +var Uint32Array = require( './../../uint32' ); +var Uint16Array = require( './../../uint16' ); +var Complex128Array = require( './../../complex128' ); +var Complex64Array = require( './../../complex64' ); +var toAccessorArray = require( './../../base/to-accessor-array' ); +var array2fancy = require( './../lib' ); + + +// VARIABLES // + +var opts = { + 'skip': !hasProxySupport() +}; + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof array2fancy, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment (generic)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = [ 5, 6, 7, 8 ]; + y[ idx ] = [ 5, 6, 7, 8 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = [ 5, 6, 3, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = [ 1, 5, 6, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = [ 5, 2, 6, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = [ 1, 6, 3, 5 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment ("unknown" dtype, accessor)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( toAccessorArray( x ) ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = [ 5, 6, 7, 8 ]; + y[ idx ] = [ 5, 6, 7, 8 ]; + + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( toAccessorArray( x ) ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = [ 5, 6, 3, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( toAccessorArray( x ) ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = [ 1, 5, 6, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( toAccessorArray( x ) ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = [ 5, 2, 6, 4 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( x, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( toAccessorArray( x ) ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = [ 1, 6, 3, 5 ]; + y[ idx ] = [ 5, 6 ]; + + t.deepEqual( x, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment (int32)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Int32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Int32Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Int32Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Int32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Int32Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Int32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Int32Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Int32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Int32Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Int32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment (uint32)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Uint32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Uint32Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Uint32Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Uint32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Uint32Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Uint32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Uint32Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Uint32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Uint32Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Uint32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment (float64)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Float64Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Float64Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Float64Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Float64Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Float64Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Float64Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting integer array assignment (complex128)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex128Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + y[ idx ] = new Complex128Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex128Array( [ 17, 18, 19, 20, 5, 6, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex128Array( [ 1, 2, 17, 18, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex128Array( [ 17, 18, 3, 4, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex128Array( [ 1, 2, 19, 20, 5, 6, 17, 18 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (generic, array)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = [ 5, 5, 5, 5 ]; + y[ idx ] = [ 5 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = [ 5, 5, 3, 4 ]; + y[ idx ] = [ 5 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = [ 1, 5, 5, 4 ]; + y[ idx ] = [ 5 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = [ 5, 2, 5, 4 ]; + y[ idx ] = [ 5 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = [ 1, 5, 3, 5 ]; + y[ idx ] = [ 5 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (generic, scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = [ 5, 5, 5, 5 ]; + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = [ 5, 5, 3, 4 ]; + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = [ 1, 5, 5, 4 ]; + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = [ 5, 2, 5, 4 ]; + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = [ 1, 5, 3, 5 ]; + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (float64, array)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Float64Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = new Float64Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Float64Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = new Float64Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Float64Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = new Float64Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Float64Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = new Float64Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Float64Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = new Float64Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (float64, scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Float64Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Float64Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Float64Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Float64Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Float64Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (int32, array)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Int32Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = new Int32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Int32Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = new Int32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Int32Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = new Int32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Int32Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = new Int32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Int32Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = new Int32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (int32, scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Int32Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Int32Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Int32Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Int32Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Int32Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (uint32, array)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Uint32Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = new Uint32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Uint32Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = new Uint32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Uint32Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = new Uint32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Uint32Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = new Uint32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Uint32Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = new Uint32Array( [ 5 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (uint32, scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Uint32Array( [ 5, 5, 5, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Uint32Array( [ 5, 5, 3, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Uint32Array( [ 1, 5, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Uint32Array( [ 5, 2, 5, 4 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Uint32Array( [ 1, 5, 3, 5 ] ); + y[ idx ] = 5; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (complex128, array)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex128Array( [ 9, 10, 9, 10, 9, 10, 9, 10 ] ); + y[ idx ] = new Complex128Array( [ 9, 10 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex128Array( [ 9, 10, 9, 10, 5, 6, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 9, 10 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex128Array( [ 1, 2, 9, 10, 9, 10, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 9, 10 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex128Array( [ 9, 10, 3, 4, 9, 10, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 9, 10 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex128Array( [ 1, 2, 9, 10, 5, 6, 9, 10 ] ); + y[ idx ] = new Complex128Array( [ 9, 10 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (complex128, complex scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex128Array( [ 9, 10, 9, 10, 9, 10, 9, 10 ] ); + y[ idx ] = new Complex128( 9, 10 ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex128Array( [ 9, 10, 9, 10, 5, 6, 7, 8 ] ); + y[ idx ] = new Complex128( 9, 10 ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex128Array( [ 1, 2, 9, 10, 9, 10, 7, 8 ] ); + y[ idx ] = new Complex128( 9, 10 ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex128Array( [ 9, 10, 3, 4, 9, 10, 7, 8 ] ); + y[ idx ] = new Complex128( 9, 10 ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex128Array( [ 1, 2, 9, 10, 5, 6, 9, 10 ] ); + y[ idx ] = new Complex128( 9, 10 ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting broadcasted integer array assignment (complex128, real scalar)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex128Array( [ 9, 0, 9, 0, 9, 0, 9, 0 ] ); + y[ idx ] = 9; + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex128Array( [ 9, 0, 9, 0, 5, 6, 7, 8 ] ); + y[ idx ] = 9; + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex128Array( [ 1, 2, 9, 0, 9, 0, 7, 8 ] ); + y[ idx ] = 9; + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex128Array( [ 9, 0, 3, 4, 9, 0, 7, 8 ] ); + y[ idx ] = 9; + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex128Array( [ 1, 2, 9, 0, 5, 6, 9, 0 ] ); + y[ idx ] = 9; + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting casting (generic, float64)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = [ 5, 6, 7, 8 ]; + y[ idx ] = new Float64Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = [ 5, 6, 3, 4 ]; + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = [ 1, 5, 6, 4 ]; + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = [ 5, 2, 6, 4 ]; + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = [ 1, 6, 3, 5 ]; + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting casting (float64, float32)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Float64Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Float32Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Float64Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Float32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Float64Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Float32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Float64Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Float32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Float64Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Float32Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting casting (int32, int8)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Int32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Int8Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Int32Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Int8Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Int32Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Int8Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Int32Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Int8Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Int32Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Int8Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting casting (uint32, uint16)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Uint32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Uint16Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Uint32Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Uint16Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Uint32Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Uint16Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Uint32Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Uint16Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Uint32Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Uint16Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting casting (complex128, complex64)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex128Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + y[ idx ] = new Complex64Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex128Array( [ 17, 18, 19, 20, 5, 6, 7, 8 ] ); + y[ idx ] = new Complex64Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex128Array( [ 1, 2, 17, 18, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex64Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex128Array( [ 17, 18, 3, 4, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex64Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex128Array( [ 1, 2, 19, 20, 5, 6, 17, 18 ] ); + y[ idx ] = new Complex64Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex128Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting downcasting of floating-point arrays (float32, float64)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Float32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Float32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Float64Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Float32Array( [ 5, 6, 3, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Float32Array( [ 1, 5, 6, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Float32Array( [ 5, 2, 6, 4 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + x = new Float32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Float32Array( [ 1, 6, 3, 5 ] ); + y[ idx ] = new Float64Array( [ 5, 6 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an array-like object supporting downcasting of floating-point arrays (complex64, complex128)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Complex64Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ] ); + expected = new Complex64Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + y[ idx ] = new Complex128Array( [ 9, 10, 11, 12, 13, 14, 15, 16 ] ); + + t.strictEqual( isSameComplex64Array( y, expected ), true, 'returns expected value' ); + + x = new Complex64Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1 ] ); + expected = new Complex64Array( [ 17, 18, 19, 20, 5, 6, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex64Array( y, expected ), true, 'returns expected value' ); + + x = new Complex64Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 1, 2 ] ); + expected = new Complex64Array( [ 1, 2, 17, 18, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex64Array( y, expected ), true, 'returns expected value' ); + + x = new Complex64Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 2 ] ); + expected = new Complex64Array( [ 17, 18, 3, 4, 19, 20, 7, 8 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex64Array( y, expected ), true, 'returns expected value' ); + + x = new Complex64Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ -1, -3 ] ); + expected = new Complex64Array( [ 1, 2, 19, 20, 5, 6, 17, 18 ] ); + y[ idx ] = new Complex128Array( [ 17, 18, 19, 20 ] ); + + t.strictEqual( isSameComplex64Array( y, expected ), true, 'returns expected value' ); + + t.end(); +}); + +tape( 'by default, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (generic)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'by default, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (typed)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'when `strict` is `true`, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (generic)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x, { + 'strict': true + }); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'when `strict` is `true`, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (typed)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x, { + 'strict': true + }); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'when `strict` is `false`, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (generic)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x, { + 'strict': false + }); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'when `strict` is `false`, the function returns an array-like object which throws an error when provided an integer array containing an index which is out-of-bounds (typed)', opts, function test( t ) { + var idx; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x, { + 'strict': false + }); + + for ( i = 0; i < 10; i++ ) { + idx = array2fancy.idx( [ x.length+i ] ); + t.throws( badValue( idx ), RangeError, 'throws an error when provided ' + idx.data ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = 5; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to assign a broadcast-incompatible array (generic)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + [], + [ 5, 6 ], + [ 5, 6, 7 ], + [ 5, 6, 7, 8, 9 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to assign a broadcast-incompatible array (int32)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + new Int32Array( [] ), + new Int32Array( [ 5, 6 ] ), + new Int32Array( [ 5, 6, 7 ] ), + new Int32Array( [ 5, 6, 7, 8, 9 ] ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (float64)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Float64Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + new Complex128Array( [ 5, 6 ] ), + new Complex128( 5, 6 ), + '5', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (complex128)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Complex128Array( [ 1, 2, 3, 4, 5, 6, 7, 8 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + '5', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (int32)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + new Uint32Array( [ 1 ] ), + new Uint32Array( [ 5, 6, 7, 8 ] ), + new Float64Array( [ 1 ] ), + new Float64Array( [ 5, 6, 7, 8 ] ), + new Float32Array( [ 1 ] ), + new Float32Array( [ 5, 6, 7, 8 ] ), + new Complex128Array( [ 5, 6 ] ), + 3.14, + -3.14, + new Complex128( 5, 6 ), + '5', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (int8)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Int8Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + new Int32Array( [ 1 ] ), + new Int32Array( [ 5, 6, 7, 8 ] ), + new Float64Array( [ 1 ] ), + new Float64Array( [ 5, 6, 7, 8 ] ), + new Float32Array( [ 1 ] ), + new Float32Array( [ 5, 6, 7, 8 ] ), + new Complex128Array( [ 5, 6 ] ), + 999999, + 3.14, + -3.14, + new Complex128( 5, 6 ), + '5', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (uint32)', function test( t ) { + var values; + var idx; + var x; + var y; + var i; + + x = new Uint32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + + values = [ + new Int32Array( [ 1 ] ), + new Int32Array( [ 5, 6, 7, 8 ] ), + new Float64Array( [ 1 ] ), + new Float64Array( [ 5, 6, 7, 8 ] ), + new Float32Array( [ 1 ] ), + new Float32Array( [ 5, 6, 7, 8 ] ), + new Complex128Array( [ 5, 6 ] ), + -3, + 3.14, + -3.14, + new Complex128( 5, 6 ), + '5', + true, + false + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] ); + } + + array2fancy.idx.free( idx ); + + t.end(); + + function badValue( value ) { + return function badValue() { + y[ idx ] = value; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when unable to resolve an index array (generic)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': false + }); + expected = [ 5, 6, 7, 8 ]; + y[ idx ] = [ 5, 6, 7, 8 ]; + + t.deepEqual( y, expected, 'returns expected value' ); + + t.throws( badValue( idx ), Error, 'throws an error' ); + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = [ 9, 10, 11, 12 ]; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when unable to resolve an index array (typed)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': false + }); + expected = new Int32Array( [ 5, 6, 7, 8 ] ); + y[ idx ] = new Int32Array( [ 5, 6, 7, 8 ] ); + + t.deepEqual( y, expected, 'returns expected value' ); + + t.throws( badValue( idx ), Error, 'throws an error' ); + t.end(); + + function badValue( value ) { + return function badValue() { + y[ value ] = new Int32Array( [ 9, 10, 11, 12 ] ); + }; + } +}); + +tape( 'the function returns an array-like object which supports persisted index arrays (generic)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + expected = [ 5, 6, 7, 8 ]; + + y[ idx ] = [ 5, 6, 7, 8 ]; + t.deepEqual( y, expected, 'returns expected value' ); + + expected = [ 9, 10, 11, 12 ]; + + y[ idx ] = [ 9, 10, 11, 12 ]; + t.deepEqual( y, expected, 'returns expected value' ); + + array2fancy.idx.free( idx ); + + t.end(); +}); + +tape( 'the function returns an array-like object which supports persisted index arrays (typed)', opts, function test( t ) { + var expected; + var idx; + var x; + var y; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + idx = array2fancy.idx( [ 0, 1, 2, 3 ], { + 'persist': true + }); + expected = new Int32Array( [ 5, 6, 7, 8 ] ); + + y[ idx ] = new Int32Array( [ 5, 6, 7, 8 ] ); + t.deepEqual( y, expected, 'returns expected value' ); + + expected = new Int32Array( [ 9, 10, 11, 12 ] ); + + y[ idx ] = new Int32Array( [ 9, 10, 11, 12 ] ); + t.deepEqual( y, expected, 'returns expected value' ); + + array2fancy.idx.free( idx ); + + t.end(); +}); diff --git a/to-fancy/test/test.set.integers.js b/to-fancy/test/test.set.integers.js index 1c336f4d..5c84cb2f 100644 --- a/to-fancy/test/test.set.integers.js +++ b/to-fancy/test/test.set.integers.js @@ -30,6 +30,7 @@ var Int32Array = require( './../../int32' ); var Float64Array = require( './../../float64' ); var Complex64Array = require( './../../complex64' ); var Complex128Array = require( './../../complex128' ); +var BooleanArray = require( './../../bool' ); var Complex128 = require( '@stdlib/complex/float64/ctor' ); var array2fancy = require( './../lib' ); @@ -87,6 +88,25 @@ tape( 'the function returns an array-like object supporting individual element a t.end(); }); +tape( 'the function returns an array-like object supporting individual element assignment (bool, positive integer indices)', function test( t ) { + var expected; + var x; + var y; + var i; + + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + y = array2fancy( x ); + + expected = new BooleanArray( [ 1, 1, 1, 1 ] ); + + for ( i = 0; i < x.length; i++ ) { + y[ i ] = true; + t.strictEqual( y[ i ], x.get( i ), 'returns expected value' ); + t.strictEqual( y[ i ], expected.get( i ), 'returns expected value' ); + } + t.end(); +}); + tape( 'the function returns an array-like object supporting individual element assignment (complex128, positive integer indices)', function test( t ) { var expected; var x; @@ -191,6 +211,27 @@ tape( 'the function returns an array-like object supporting individual element a t.end(); }); +tape( 'the function returns an array-like object supporting individual element assignment (bool, negative integer indices)', function test( t ) { + var expected; + var x; + var y; + var i; + var j; + + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + y = array2fancy( x ); + + expected = new BooleanArray( [ 1, 1, 1, 1 ] ); + + for ( i = 0; i < x.length; i++ ) { + j = i - x.length; + y[ j ] = true; + t.strictEqual( y[ j ], x.get( i ), 'returns expected value' ); + t.strictEqual( y[ j ], expected.get( i ), 'returns expected value' ); + } + t.end(); +}); + tape( 'the function returns an array-like object supporting individual element assignment (complex128, negative integer indices)', function test( t ) { var expected; var x; @@ -616,3 +657,32 @@ tape( 'the function returns an array-like object which throws an error when atte }; } }); + +tape( 'the function returns an array-like object which throws an error when attempting to perform an unsafe cast (bool)', function test( t ) { + var values; + var x; + var y; + var i; + + x = new BooleanArray( [ 0, 1, 0, 1 ] ); + y = array2fancy( x ); + + values = [ + 3.14, + -3.14, + new Complex128( 5, 6 ), + '5', + null, + 1 + ]; + 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() { + y[ 0 ] = value; + }; + } +}); diff --git a/to-fancy/test/test.set.invalid.js b/to-fancy/test/test.set.invalid.js index 7b10e88c..90b3ac1f 100644 --- a/to-fancy/test/test.set.invalid.js +++ b/to-fancy/test/test.set.invalid.js @@ -23,6 +23,7 @@ var tape = require( 'tape' ); var hasProxySupport = require( '@stdlib/assert/has-proxy-support' ); var Int32Array = require( './../../int32' ); +var Uint8Array = require( './../../uint8' ); var array2fancy = require( './../lib' ); @@ -152,3 +153,133 @@ tape( 'the function returns an array-like object which throws an error when prov }; } }); + +tape( 'the function returns an array-like object which throws an error when provided an invalid serialized array index (generic)', opts, function test( t ) { + var values; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x ); + + values = [ + 'ArrayIndex<9999999>', + 'ArrayIndex<9999999999>' + ]; + + 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() { + y[ value ] = 0; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when provided an invalid serialized array index (typed)', opts, function test( t ) { + var values; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x ); + + values = [ + 'ArrayIndex<9999999>', + 'ArrayIndex<9999999999>' + ]; + + 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() { + y[ value ] = 0; + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when provided an unsupported array index (generic)', opts, function test( t ) { + var values; + var x; + var y; + var i; + + x = [ 1, 2, 3, 4 ]; + y = array2fancy( x, { + 'cache': { + 'get': get + } + }); + + values = [ + array2fancy.idx( [ 0, 1, 2, 3 ] ), + array2fancy.idx( [ true, false, true, false ] ), + array2fancy.idx( new Uint8Array( [ 0, 1, 0, 1 ] ) ) + ]; + + 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() { + y[ value ] = 0; + }; + } + + function get() { + return { + 'data': [], + 'type': 'beep', + 'dtype': 'generic' + }; + } +}); + +tape( 'the function returns an array-like object which throws an error when provided an unsupported array index (typed)', opts, function test( t ) { + var values; + var x; + var y; + var i; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + y = array2fancy( x, { + 'cache': { + 'get': get + } + }); + + values = [ + array2fancy.idx( [ 0, 1, 2, 3 ] ), + array2fancy.idx( [ true, false, true, false ] ), + array2fancy.idx( new Uint8Array( [ 0, 1, 0, 1 ] ) ) + ]; + + 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() { + y[ value ] = 0; + }; + } + + function get() { + return { + 'data': [], + 'type': 'beep', + 'dtype': 'generic' + }; + } +});