From c5731b5f5901ec775bf5c756691b2acaa6e126ce Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Thu, 20 Jun 2024 01:55:02 +0000 Subject: [PATCH] Auto-generated commit --- CHANGELOG.md | 27 ++ base/lib/index.js | 9 + base/mskput/README.md | 135 ++++++++ base/mskput/benchmark/benchmark.js | 79 +++++ base/mskput/benchmark/benchmark.length.js | 113 +++++++ base/mskput/docs/repl.txt | 50 +++ base/mskput/docs/types/index.d.ts | 224 ++++++++++++++ base/mskput/docs/types/test.ts | 89 ++++++ base/mskput/examples/index.js | 42 +++ base/mskput/lib/index.js | 48 +++ base/mskput/lib/main.js | 280 +++++++++++++++++ base/mskput/package.json | 65 ++++ base/mskput/test/test.js | 361 ++++++++++++++++++++++ base/put/lib/main.js | 4 +- put/lib/main.js | 4 +- 15 files changed, 1526 insertions(+), 4 deletions(-) create mode 100644 base/mskput/README.md create mode 100644 base/mskput/benchmark/benchmark.js create mode 100644 base/mskput/benchmark/benchmark.length.js create mode 100644 base/mskput/docs/repl.txt create mode 100644 base/mskput/docs/types/index.d.ts create mode 100644 base/mskput/docs/types/test.ts create mode 100644 base/mskput/examples/index.js create mode 100644 base/mskput/lib/index.js create mode 100644 base/mskput/lib/main.js create mode 100644 base/mskput/package.json create mode 100644 base/mskput/test/test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index eee203a5..1125046a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ ##### Features +- [`20cd086`](https://github.com/stdlib-js/stdlib/commit/20cd0868236daf523fcd659d027e2277f7e1cb56) - add `mskput` to namespace - [`2827035`](https://github.com/stdlib-js/stdlib/commit/2827035933c44ebb301a44200ff9cd5ad73e9ef0) - add `where` to namespace - [`d626ffa`](https://github.com/stdlib-js/stdlib/commit/d626ffac9f0504be236c94afd4b920032272c8bf) - update namespace TypeScript declarations [(#2394)](https://github.com/stdlib-js/stdlib/pull/2394) - [`60fa5ac`](https://github.com/stdlib-js/stdlib/commit/60fa5ac214d2e5dfe310f93928a07515eeeb4a3b) - add `cuevery` to namespace @@ -921,6 +922,28 @@ This release closes the following issue: +
+ +#### [@stdlib/array/base/mskput](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/mskput) + +
+ +
+ +##### Features + +- [`e9bf843`](https://github.com/stdlib-js/stdlib/commit/e9bf843b45b204ca61eca213575aa4933026b09b) - add `array/base/mskput` + +
+ + + +
+ +
+ + +
#### [@stdlib/array/base/mskreject](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/mskreject) @@ -2009,6 +2032,10 @@ A total of 13 people contributed to this release. Thank you to the following con
+- [`20cd086`](https://github.com/stdlib-js/stdlib/commit/20cd0868236daf523fcd659d027e2277f7e1cb56) - **feat:** add `mskput` to namespace _(by Athan Reines)_ +- [`e9bf843`](https://github.com/stdlib-js/stdlib/commit/e9bf843b45b204ca61eca213575aa4933026b09b) - **feat:** add `array/base/mskput` _(by Athan Reines)_ +- [`33da247`](https://github.com/stdlib-js/stdlib/commit/33da2477cc34e5fcc931b39e996a373d043432e0) - **docs:** fix example _(by Athan Reines)_ +- [`7879bf0`](https://github.com/stdlib-js/stdlib/commit/7879bf0ecd89e0b274fb687ff090dd2b863346a3) - **docs:** fix example _(by Athan Reines)_ - [`299be6a`](https://github.com/stdlib-js/stdlib/commit/299be6aa293d738d6be5ef6c4a1aa2efb4cbb8d9) - **feat:** add boolean dtype support to `array/base/count-falsy` _(by Athan Reines)_ - [`09f1e11`](https://github.com/stdlib-js/stdlib/commit/09f1e11557f76c8fc6a8e3f9b60b06a8701ded3e) - **feat:** add boolean dtype support to `array/base/count-truthy` _(by Athan Reines)_ - [`b981bc3`](https://github.com/stdlib-js/stdlib/commit/b981bc30e83a7f88cdc2c0efca082fb31f9e1ac0) - **refactor:** avoid repeated property access _(by Athan Reines)_ diff --git a/base/lib/index.js b/base/lib/index.js index 29eaaa32..4d11d287 100644 --- a/base/lib/index.js +++ b/base/lib/index.js @@ -1035,6 +1035,15 @@ setReadOnly( ns, 'mskbinary2d', require( './../../base/mskbinary2d' ) ); */ setReadOnly( ns, 'mskfilter', require( './../../base/mskfilter' ) ); +/** +* @name mskput +* @memberof ns +* @readonly +* @type {Function} +* @see {@link module:@stdlib/array/base/mskput} +*/ +setReadOnly( ns, 'mskput', require( './../../base/mskput' ) ); + /** * @name mskreject * @memberof ns diff --git a/base/mskput/README.md b/base/mskput/README.md new file mode 100644 index 00000000..c2a9761d --- /dev/null +++ b/base/mskput/README.md @@ -0,0 +1,135 @@ + + +# mskput + +> Replace elements of an array with provided values according to a provided mask array. + +
+ +## Usage + +```javascript +var mskput = require( '@stdlib/array/base/mskput' ); +``` + +#### mskput( x, mask, values, mode ) + +Replaces elements of an array with provided values according to a provided mask array. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = mskput( x, [ 1, 0, 1, 0 ], [ 20, 40 ], 'throw' ); +// returns [ 1, 20, 3, 40 ] + +var bool = ( out === x ); +// returns true +``` + +The function supports the following parameters: + +- **x**: input array. +- **mask**: mask array. +- **values**: values to set. +- **mode**: string specifying whether to raise an exception when the number of `values` is less than the number of falsy `mask` values. + +The function supports the following modes: + +- `'throw'`: specifies that the function must raise an exception when the function is provided insufficient `values` to satisfy the `mask` array. +- `'repeat'`: specifies that the function must reuse provided `values` when replacing elements in `x` in order to satisfy the `mask` array. + +When `mode` is equal to `'repeat`', the function supports broadcasting a `values` array containing a single element against the number of falsy values in the `mask` array. + +```javascript +var x = [ 1, 2, 3, 4 ]; + +var out = mskput( x, [ 1, 0, 1, 0 ], [ 20 ], 'repeat' ); +// returns [ 1, 20, 3, 20 ] + +var bool = ( out === x ); +// returns true +``` + +
+ + + +
+ +## Notes + +- The function mutates the input array `x`. +- If a `mask` array element is falsy, the corresponding element in `x` is **replaced**; otherwise, the corresponding element in `x` is "masked" and thus left unchanged. + +
+ + + +
+ +## Examples + + + +```javascript +var filledBy = require( '@stdlib/array/base/filled-by' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var bernoulli = require( '@stdlib/random/base/bernoulli' ); +var linspace = require( '@stdlib/array/base/linspace' ); +var mskput = require( '@stdlib/array/base/mskput' ); + +// Generate a linearly spaced array: +var x = linspace( 0, 100, 11 ); +console.log( x ); + +// Generate a random mask array: +var N = discreteUniform( 5, 15 ); +var mask = filledBy( N, bernoulli.factory( 0.3 ) ); +console.log( mask ); + +// 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 = mskput( x, mask, values, 'throw' ); +console.log( out ); +``` + +
+ + + + + + + + + + + + + + diff --git a/base/mskput/benchmark/benchmark.js b/base/mskput/benchmark/benchmark.js new file mode 100644 index 00000000..0b6019a9 --- /dev/null +++ b/base/mskput/benchmark/benchmark.js @@ -0,0 +1,79 @@ +/** +* @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 zeros = require( './../../../base/zeros' ); +var pkg = require( './../package.json' ).name; +var mskput = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::no_broadcasting:len=100', function benchmark( b ) { + var mask; + var x; + var i; + var v; + + x = zeroTo( 100 ); + mask = zeros( 100 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = mskput( x, mask, x, 'throw' ); + 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 mask; + var x; + var i; + var v; + + x = zeroTo( 100 ); + mask = zeros( 100 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = mskput( x, mask, [ i ], 'repeat' ); + 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/base/mskput/benchmark/benchmark.length.js b/base/mskput/benchmark/benchmark.length.js new file mode 100644 index 00000000..e9260933 --- /dev/null +++ b/base/mskput/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 zeros = require( './../../../base/zeros' ); +var isArray = require( '@stdlib/assert/is-array' ); +var pkg = require( './../package.json' ).name; +var mskput = 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 mask; + var x; + + x = discreteUniform( len, 0, 10, opts ); + mask = zeros( 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 = mskput( x, mask, values[ i%values.length ], 'throw' ); + 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/base/mskput/docs/repl.txt b/base/mskput/docs/repl.txt new file mode 100644 index 00000000..c781773c --- /dev/null +++ b/base/mskput/docs/repl.txt @@ -0,0 +1,50 @@ + +{{alias}}( x, mask, values, mode ) + Replaces elements of an array with provided values according to a provided + mask array. + + When the `mode` is `'repeat'`, the function supports broadcasting a `values` + array containing a single element against the number of falsy values in the + `mask` array. + + The function mutates the input array. + + Parameters + ---------- + x: ArrayLikeObject + Input array. + + mask: ArrayLikeObject + Mask array. If a mask array element is falsy, the corresponding element + in `x` is *replaced*; otherwise, the corresponding element in `x` is + "masked" and thus left unchanged. + + values: ArrayLikeObject + Values to set. + + mode: string + String specifying whether to raise an exception when the number of + values to set is less than the number of falsy mask values. The function + supports the following modes: + + - 'throw': specifies that the function must raise an exception when the + function is provided insufficient values to satisfy the mask array. + - 'repeat': specifies that the function must reuse provided values when + replacing elements in `x` in order to satisfy the mask array. + + Returns + ------- + out: ArrayLikeObject + Input array. + + Examples + -------- + > var x = [ 1, 2, 3, 4 ]; + > var out = {{alias}}( x, [ 1, 0, 1, 0 ], [ 20, 40 ], 'throw' ) + [ 1, 20, 3, 40 ] + > var bool = ( out === x ) + true + + See Also + -------- + diff --git a/base/mskput/docs/types/index.d.ts b/base/mskput/docs/types/index.d.ts new file mode 100644 index 00000000..034d6c3e --- /dev/null +++ b/base/mskput/docs/types/index.d.ts @@ -0,0 +1,224 @@ +/* +* @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'; + +/** +* Mask array. +*/ +type MaskArray = Collection | AccessorArrayLike; + +/** +* Values array. +*/ +type ValuesArray = Collection | AccessorArrayLike; + +/** +* Mode specifying whether to raise an exception when the number of values to set is less than the number of falsy values in the mask array. +* +* ## Notes +* +* - The function supports the following modes: +* +* - `'throw'`: specifies that the function must raise an exception when the function is provided insufficient `values` to satisfy the `mask` array. +* - `'repeat'`: specifies that the function must reuse provided `values` when replacing elements in `x` in order to satisfy the `mask` array. +*/ +type Mode = 'throw' | 'repeat'; + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param x - input array +* @param mask - mask array +* @param values - values to set +* @param mode - string specifying whether to raise an exception when the number of values is less than the number of falsy values in the mask array +* @returns input array +* +* @example +* var Int32Array = require( '@stdlib/array/int32' ); +* +* var x = new Int32Array( [ 1, 2, 3, 4 ] ); +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* // 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 = mskput( x, [ 1, 0, 0, 1 ], [ 30 ], 'repeat' ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function mskput( x: T, mask: MaskArray, values: ValuesArray, mode: Mode ): T; + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param x - input array +* @param mask - mask array +* @param values - values to set +* @param mode - string specifying whether to raise an exception when the number of values is less than the number of falsy values in the mask array +* @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 mask = [ 1, 0, 0, 1 ]; +* var values = new Complex128Array( [ 20.0, 30.0, 40, 5.0 ] ); +* +* var out = mskput( x, mask, values, 'throw' ); +* // 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 mask = [ 1, 0, 0, 1 ]; +* var values = new Complex128Array( [ 20.0, 30.0 ] ); +* +* var out = mskput( x, mask, values, 'repeat' ); +* // returns +* +* var bool = ( out === x ); +* // returns true +*/ +declare function mskput( x: T, mask: MaskArray, values: ValuesArray, mode: Mode ): T; + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param x - input array +* @param mask - mask array +* @param values - values to set +* @param mode - string specifying whether to raise an exception when the number of values is less than the number of falsy values in the mask array +* @returns input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var out = mskput( x, [ 1, 0, 0, 1 ], [ 30 ], 'repeat' ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function mskput( x: Array, mask: MaskArray, values: ValuesArray, mode: Mode ): Array; + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param x - input array +* @param mask - mask array +* @param values - values to set +* @param mode - string specifying whether to raise an exception when the number of values is less than the number of falsy values in the mask array +* @returns input array +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* +* 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 = mskput( x, [ 1, 0, 0, 1 ], [ 30 ], 'repeat' ); +* +* var bool = ( out === x ); +* // returns true +*/ +declare function mskput( x: AccessorArrayLike, mask: MaskArray, values: ValuesArray, mode: Mode ): AccessorArrayLike; + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param x - input array +* @param mask - mask array +* @param values - values to set +* @param mode - string specifying whether to raise an exception when the number of values is less than the number of falsy values in the mask array +* @returns input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var out = mskput( x, [ 1, 0, 0, 1 ], [ 30 ], 'throw' ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +declare function mskput( x: Collection, mask: MaskArray, values: ValuesArray, mode: Mode ): Collection; + + +// EXPORTS // + +export = mskput; diff --git a/base/mskput/docs/types/test.ts b/base/mskput/docs/types/test.ts new file mode 100644 index 00000000..76bb350f --- /dev/null +++ b/base/mskput/docs/types/test.ts @@ -0,0 +1,89 @@ +/* +* @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 mskput = require( './index' ); + + +// TESTS // + +// The function returns an array... +{ + mskput( [ 1, 2, 3, 4 ], [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectType number[] + mskput( [ 1, 2, 3, 4 ], [ 1, 0, 0, 1 ], [ 20, 30 ], 'repeat' ); // $ExpectType number[] + + mskput( new Int32Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectType Int32Array + mskput( new Complex128Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ], 'throw' ); // $ExpectType Complex128Array + mskput( new Complex64Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ], 'throw' ); // $ExpectType Complex64Array + mskput( new AccessorArray( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], new AccessorArray( [ 20, 30 ] ), 'throw' ); // $ExpectType AccessorArrayLike +} + +// The compiler throws an error if the function is provided a first argument which is not an array-like object... +{ + mskput( 1, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError + mskput( true, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError + mskput( false, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError + mskput( null, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError + mskput( void 0, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError + mskput( {}, [ 1, 0, 0, 1 ], [ 20, 30 ], 'throw' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not an array-like object... +{ + mskput( [], 1, [ 20, 30 ], 'throw' ); // $ExpectError + mskput( [], true, [ 20, 30 ], 'throw' ); // $ExpectError + mskput( [], false, [ 20, 30 ], 'throw' ); // $ExpectError + mskput( [], null, [ 20, 30 ], 'throw' ); // $ExpectError + mskput( [], void 0, [ 20, 30 ], 'throw' ); // $ExpectError + mskput( [], {}, [ 20, 30 ], 'throw' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a third argument which is not an array-like object... +{ + mskput( [], [ 1, 0, 0, 1 ], 1, 'throw' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], true, 'throw' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], false, 'throw' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], null, 'throw' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], void 0, 'throw' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], {}, 'throw' ); // $ExpectError +} + +// The compiler throws an error if the function is provided a fourth argument which is not a valid mode... +{ + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], '1' ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], 1 ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], true ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], false ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], null ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], void 0 ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], {} ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], [] ); // $ExpectError + mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + mskput(); // $ExpectError + mskput( [] ); // $ExpectError + mskput( [], [] ); // $ExpectError + mskput( [], [], [], ); // $ExpectError + mskput( [], [], [], 'throw', {} ); // $ExpectError +} diff --git a/base/mskput/examples/index.js b/base/mskput/examples/index.js new file mode 100644 index 00000000..160aa516 --- /dev/null +++ b/base/mskput/examples/index.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'; + +var filledBy = require( './../../../base/filled-by' ); +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); +var bernoulli = require( '@stdlib/random/base/bernoulli' ); +var linspace = require( './../../../base/linspace' ); +var mskput = require( './../lib' ); + +// Generate a linearly spaced array: +var x = linspace( 0, 100, 11 ); +console.log( x ); + +// Generate a random mask array: +var N = discreteUniform( 5, 15 ); +var mask = filledBy( N, bernoulli.factory( 0.3 ) ); +console.log( mask ); + +// 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 = mskput( x, mask, values, 'throw' ); +console.log( out ); diff --git a/base/mskput/lib/index.js b/base/mskput/lib/index.js new file mode 100644 index 00000000..24415143 --- /dev/null +++ b/base/mskput/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 elements of an array with provided values according to a provided mask array. +* +* @module @stdlib/array/base/mskput +* +* @example +* var mskput = require( '@stdlib/array/base/mskput' ); +* +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/mskput/lib/main.js b/base/mskput/lib/main.js new file mode 100644 index 00000000..ef861812 --- /dev/null +++ b/base/mskput/lib/main.js @@ -0,0 +1,280 @@ +/** +* @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 isComplexDataType = require( './../../../base/assert/is-complex-floating-point-data-type' ); +var isBooleanDataType = require( './../../../base/assert/is-boolean-data-type' ); +var arraylike2object = require( './../../../base/arraylike2object' ); +var reinterpretComplex = require( '@stdlib/strided/base/reinterpret-complex' ); +var reinterpretBoolean = require( '@stdlib/strided/base/reinterpret-boolean' ); +var countFalsy = require( './../../../base/count-falsy' ); + + +// FUNCTIONS // + +/** +* Replaces elements in an indexed array with provided values. +* +* @private +* @param {Collection} x - input array +* @param {Collection} mask - mask array +* @param {Collection} values - values to set +* @returns {Collection} input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = indexed( x, mask, values ); +* // returns [ 1, 20, 30, 4 ] +*/ +function indexed( x, mask, values ) { + var iv; + var N; + var i; + + N = values.length; + iv = 0; + for ( i = 0; i < x.length; i++ ) { + if ( !mask[ i ] ) { + x[ i ] = values[ iv ]; + iv = ( iv+1 ) % N; + } + } + return x; +} + +/** +* Replaces elements of an accessor array with provided values. +* +* @private +* @param {Object} x - input array object +* @param {Object} mask - mask array object +* @param {Object} values - values object +* @returns {Collection} input array +* +* @example +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +* +* var x = toAccessorArray( [ 1, 2, 3, 4 ] ); +* +* var mask = toAccessorArray( [ 1, 0, 0, 1 ] ); +* var values = toAccessorArray( [ 20, 30 ] ); +* +* var out = accessors( arraylike2object( x ), arraylike2object( mask ), arraylike2object( values ) ); +* +* var v = x.get( 0 ); +* // returns 1 +* +* v = x.get( 1 ); +* // returns 20 +*/ +function accessors( x, mask, values ) { + var xdata; + var mdata; + var vdata; + var xset; + var mget; + var vget; + var iv; + var N; + var i; + + xdata = x.data; + mdata = mask.data; + vdata = values.data; + + xset = x.accessors[ 1 ]; + mget = mask.accessors[ 0 ]; + vget = values.accessors[ 0 ]; + + N = vdata.length; + iv = 0; + for ( i = 0; i < xdata.length; i++ ) { + if ( !mget( mdata, i ) ) { + xset( xdata, i, vget( vdata, iv ) ); + iv = ( iv+1 ) % N; + } + } + return xdata; +} + +/** +* Replaces elements in a complex array with provided values. +* +* @private +* @param {Collection} x - real-valued floating-point input array view +* @param {Object} mask - mask array object +* @param {Collection} values - real-valued floating-point values array view +* @returns {Collection} input array view +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +* +* var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* +* var mask = [ 0, 1, 0, 1 ]; +* var values = new Float64Array( [ 10.0, 20.0, 50.0, 60.0 ] ); +* +* var out = complex( x, arraylike2object( mask ), values ); +* // returns [ 10.0, 20.0, 3.0, 4.0, 50.0, 60.0, 7.0, 8.0 ] +*/ +function complex( x, mask, values ) { + var mdata; + var mget; + var iv; + var N; + var i; + + mdata = mask.data; + mget = mask.accessors[ 0 ]; + + N = values.length; + iv = 0; + for ( i = 0; i < x.length; i += 2 ) { + if ( !mget( mdata, i/2 ) ) { + x[ i ] = values[ iv ]; + x[ i+1 ] = values[ iv+1 ]; + iv = ( iv+2 ) % N; + } + } + return x; +} + +/** +* Replaces elements in a boolean array with provided values. +* +* @private +* @param {Uint8Array} x - input array +* @param {Object} mask - mask array object +* @param {Uint8Array} values - values to set +* @returns {Uint8Array} input array +* +* @example +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +* var Uint8Array = require( '@stdlib/array/uint8' ); +* +* var x = new Uint8Array( [ 1, 0, 0, 1 ] ); +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = new Uint8Array( [ 1, 1 ] ); +* +* var out = boolean( x, arraylike2object( mask ), values ); +* // returns [ 1, 1, 1, 1 ] +*/ +function boolean( x, mask, values ) { + var mdata; + var mget; + var iv; + var N; + var i; + + mdata = mask.data; + mget = mask.accessors[ 0 ]; + + N = values.length; + iv = 0; + for ( i = 0; i < x.length; i++ ) { + if ( !mget( mdata, i ) ) { + x[ i ] = values[ iv ]; + iv = ( i+1 ) % N; + } + } + return x; +} + + +// MAIN // + +/** +* Replaces elements of an array with provided values according to a provided mask array. +* +* @param {Collection} x - input array +* @param {Collection} mask - mask array +* @param {Collection} values - values to set +* @param {string} mode - string specifying whether to raise an exception when the number of values is less than the number of falsy mask values +* @throws {Error} insufficient values to satisfy mask array +* @returns {Collection} input array +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 20, 30 ]; +* +* var out = mskput( x, mask, values, 'throw' ); +* // returns [ 1, 20, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +* +* @example +* var x = [ 1, 2, 3, 4 ]; +* +* var mask = [ 1, 0, 0, 1 ]; +* var values = [ 30 ]; +* +* var out = mskput( x, mask, values, 'repeat' ); +* // returns [ 1, 30, 30, 4 ] +* +* var bool = ( out === x ); +* // returns true +*/ +function mskput( x, mask, values, mode ) { + var xo; + var mo; + var vo; + + if ( mode === 'throw' && countFalsy( mask ) > values.length ) { + throw new Error( 'invalid arguments. Insufficient values to satisfy mask array.' ); + } + xo = arraylike2object( x ); + mo = arraylike2object( mask ); + vo = arraylike2object( values ); + if ( + xo.accessorProtocol || + mo.accessorProtocol || + vo.accessorProtocol + ) { + // Note: we only explicitly support select dtype pairs, as this function should not be concerned with casting rules, etc. That is left to userland... + if ( isComplexDataType( xo.dtype ) && isComplexDataType( vo.dtype ) ) { + complex( reinterpretComplex( x, 0 ), mo, reinterpretComplex( values, 0 ) ); // eslint-disable-line max-len + return x; + } + if ( isBooleanDataType( xo.dtype ) && isBooleanDataType( vo.dtype ) ) { + boolean( reinterpretBoolean( x, 0 ), mo, reinterpretBoolean( values, 0 ) ); // eslint-disable-line max-len + return x; + } + accessors( xo, mo, vo ); + return x; + } + indexed( x, mask, values ); + return x; +} + + +// EXPORTS // + +module.exports = mskput; diff --git a/base/mskput/package.json b/base/mskput/package.json new file mode 100644 index 00000000..884f3707 --- /dev/null +++ b/base/mskput/package.json @@ -0,0 +1,65 @@ +{ + "name": "@stdlib/array/base/mskput", + "version": "0.0.0", + "description": "Replace elements of an array with provided values according to a provided mask array.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "utilities", + "utils", + "generic", + "array", + "set", + "replace", + "put", + "update", + "mask", + "missing", + "na" + ] +} diff --git a/base/mskput/test/test.js b/base/mskput/test/test.js new file mode 100644 index 00000000..e325427e --- /dev/null +++ b/base/mskput/test/test.js @@ -0,0 +1,361 @@ +/** +* @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 Complex64Array = require( './../../../complex64' ); +var Int32Array = require( './../../../int32' ); +var BooleanArray = require( './../../../bool' ); +var toAccessorArray = require( './../../../base/to-accessor-array' ); +var Complex64 = require( '@stdlib/complex/float32' ); +var realf = require( '@stdlib/complex/realf' ); +var imagf = require( '@stdlib/complex/imagf' ); +var isComplex64 = require( '@stdlib/assert/is-complex64' ); +var mskput = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof mskput, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function replaces elements in an array (generic)', function test( t ) { + var expected; + var actual; + var mask; + var x; + + x = [ 1, 2, 3, 4 ]; + mask = [ 1, 0, 1, 0 ]; + actual = mskput( x, mask, [ 20, 40 ], 'throw' ); + expected = [ 1, 20, 3, 40 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, [ 20, 30, 40, 50 ], 'throw' ); + expected = [ 20, 30, 40, 50 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + mask = [ 1, 1, 1, 1 ]; + actual = mskput( x, mask, [ 20, 30, 40, 50 ], 'throw' ); + expected = [ 1, 2, 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 actual; + var mask; + var x; + + x = [ 1, 2, 3, 4 ]; + mask = [ 1, 0, 1, 0 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + expected = [ 1, 20, 3, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + expected = [ 20, 20, 20, 20 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + mask = [ 1, 1, 1, 1 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + expected = [ 1, 2, 3, 4 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = [ 1, 2, 3, 4 ]; + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, [ 100, 200 ], 'repeat' ); + expected = [ 100, 200, 100, 200 ]; + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function replaces elements in an array (typed)', function test( t ) { + var expected; + var actual; + var mask; + var x; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + mask = [ 1, 0, 1, 0 ]; + actual = mskput( x, mask, new Int32Array( [ 20, 40 ] ), 'throw' ); + 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 ] ); + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, new Int32Array( [ 20, 30, 40, 50 ] ), 'throw' ); + expected = new Int32Array( [ 20, 30, 40, 50 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + mask = [ 1, 1, 1, 1 ]; + actual = mskput( x, mask, new Int32Array( [ 20, 30, 40, 50 ] ), 'throw' ); + expected = new Int32Array( [ 1, 2, 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 (typed, broadcasting)', function test( t ) { + var expected; + var actual; + var mask; + var x; + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + mask = [ 1, 0, 1, 0 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + 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 ] ); + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + expected = new Int32Array( [ 20, 20, 20, 20 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + mask = [ 1, 1, 1, 1 ]; + actual = mskput( x, mask, [ 20 ], 'repeat' ); + expected = new Int32Array( [ 1, 2, 3, 4 ] ); + t.strictEqual( actual, x, 'returns expected value' ); + t.deepEqual( actual, expected, 'returns expected value' ); + + x = new Int32Array( [ 1, 2, 3, 4 ] ); + mask = [ 0, 0, 0, 0 ]; + actual = mskput( x, mask, [ 100, 200 ], 'repeat' ); + expected = new Int32Array( [ 100, 200, 100, 200 ] ); + 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)', function test( t ) { + var expected; + var actual; + var values; + var mask; + var x; + var v; + var i; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + mask = toAccessorArray( [ 1, 0, 1, 0 ] ); + values = [ + new Complex64( 30.0, 40.0 ), + new Complex64( 70.0, 80.0 ) + ]; + expected = [ + new Complex64( 1.0, 2.0 ), + new Complex64( 30.0, 40.0 ), + new Complex64( 5.0, 6.0 ), + new Complex64( 70.0, 80.0 ) + ]; + actual = mskput( x, mask, values, 'throw' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.length; i++ ) { + v = actual.get( i ); + t.strictEqual( isComplex64( v ), true, 'returns expected value' ); + t.strictEqual( realf( v ), realf( expected[ i ] ), 'returns expected value' ); + t.strictEqual( imagf( v ), imagf( expected[ i ] ), 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, broadcasting)', function test( t ) { + var expected; + var actual; + var values; + var mask; + var x; + var v; + var i; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + mask = toAccessorArray( [ 1, 0, 1, 0 ] ); + values = [ + new Complex64( 100.0, 200.0 ) + ]; + expected = [ + new Complex64( 1.0, 2.0 ), + new Complex64( 100.0, 200.0 ), + new Complex64( 5.0, 6.0 ), + new Complex64( 100.0, 200.0 ) + ]; + actual = mskput( x, mask, values, 'repeat' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.length; i++ ) { + v = actual.get( i ); + t.strictEqual( isComplex64( v ), true, 'returns expected value' ); + t.strictEqual( realf( v ), realf( expected[ i ] ), 'returns expected value' ); + t.strictEqual( imagf( v ), imagf( expected[ i ] ), 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, complex)', function test( t ) { + var expected; + var actual; + var values; + var mask; + var x; + var v; + var i; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + mask = toAccessorArray( [ 1, 0, 1, 0 ] ); + values = new Complex64Array( [ 30.0, 40.0, 70.0, 80.0 ] ); + expected = [ + new Complex64( 1.0, 2.0 ), + new Complex64( 30.0, 40.0 ), + new Complex64( 5.0, 6.0 ), + new Complex64( 70.0, 80.0 ) + ]; + actual = mskput( x, mask, values, 'throw' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.length; i++ ) { + v = actual.get( i ); + t.strictEqual( isComplex64( v ), true, 'returns expected value' ); + t.strictEqual( realf( v ), realf( expected[ i ] ), 'returns expected value' ); + t.strictEqual( imagf( v ), imagf( expected[ i ] ), 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, complex, broadcasting)', function test( t ) { + var expected; + var actual; + var values; + var mask; + var x; + var v; + var i; + + x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); + mask = toAccessorArray( [ 1, 0, 1, 0 ] ); + values = new Complex64Array( [ 100.0, 200.0 ] ); + expected = [ + new Complex64( 1.0, 2.0 ), + new Complex64( 100.0, 200.0 ), + new Complex64( 5.0, 6.0 ), + new Complex64( 100.0, 200.0 ) + ]; + actual = mskput( x, mask, values, 'repeat' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.length; i++ ) { + v = actual.get( i ); + t.strictEqual( isComplex64( v ), true, 'returns expected value' ); + t.strictEqual( realf( v ), realf( expected[ i ] ), 'returns expected value' ); + t.strictEqual( imagf( v ), imagf( expected[ i ] ), 'returns expected value' ); + } + t.end(); +}); + +tape( 'the function replaces elements in an array (accessors, boolean)', function test( t ) { + var expected; + var actual; + var values; + var mask; + var x; + var v; + var i; + + x = new BooleanArray( [ true, false, false, true ] ); + mask = toAccessorArray( [ 1, 0, 1, 0 ] ); + values = new BooleanArray( [ true, false ] ); + expected = [ true, true, false, true ]; + actual = mskput( x, mask, values, 'throw' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.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 actual; + var values; + var mask; + var x; + var v; + var i; + + x = new BooleanArray( [ true, false, false, true ] ); + mask = toAccessorArray( [ 1, 0, 0, 1 ] ); + values = [ true ]; + expected = [ true, true, true, true ]; + actual = mskput( x, mask, values, 'repeat' ); + + t.strictEqual( actual, x, 'returns expected value' ); + for ( i = 0; i < mask.length; i++ ) { + v = actual.get( i ); + t.strictEqual( v, expected[ i ], 'returns expected value' ); + } + t.end(); +}); + +tape( 'when the "mode" is "throw", the function throws an error if provided insufficient values to satisfy the mask array', function test( t ) { + var mask; + var x; + + x = [ 1, 2, 3, 4 ]; + mask = [ 0, 0, 0, 0 ]; + + t.throws( badValue, Error, 'throws an error' ); + t.end(); + + function badValue() { + mskput( x, mask, [ 200 ], 'throw' ); + } +}); diff --git a/base/put/lib/main.js b/base/put/lib/main.js index 368eb3dc..9b30c183 100644 --- a/base/put/lib/main.js +++ b/base/put/lib/main.js @@ -256,9 +256,9 @@ function boolean( x, indices, values, stride, getIndex, maxIndex ) { * var x = [ 1, 2, 3, 4 ]; * * var indices = [ 1, 2 ]; -* var values = [ 20, 30 ]; +* var values = [ 30 ]; * -* var out = put( x, indices, [ 30 ], 'throw' ); +* var out = put( x, indices, values, 'throw' ); * // returns [ 1, 30, 30, 4 ] * * var bool = ( out === x ); diff --git a/put/lib/main.js b/put/lib/main.js index b817e005..ca1bd4d6 100644 --- a/put/lib/main.js +++ b/put/lib/main.js @@ -67,9 +67,9 @@ var validate = require( './validate.js' ); * var x = [ 1, 2, 3, 4 ]; * * var indices = [ 1, 2 ]; -* var values = [ 20, 30 ]; +* var values = [ 30 ]; * -* var out = put( x, indices, [ 30 ] ); +* var out = put( x, indices, values ); * // returns [ 1, 30, 30, 4 ] * * var bool = ( out === x );