diff --git a/CHANGELOG.md b/CHANGELOG.md
index 594e3fe1..8895c295 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
##### Features
+- [`0b727a5`](https://github.com/stdlib-js/stdlib/commit/0b727a5d922225d23693e456b5f7b5b82f63750a) - add `mskput` to namespace
- [`82a217c`](https://github.com/stdlib-js/stdlib/commit/82a217c79f7c10d4aca129fbaba753ce5055115a) - add `place` to namespace
- [`cd14ed3`](https://github.com/stdlib-js/stdlib/commit/cd14ed3f1bbc7f0cc7dc55d155e6fa86c90adb23) - update namespace TypeScript declarations [(#2402)](https://github.com/stdlib-js/stdlib/pull/2402)
- [`e1993a6`](https://github.com/stdlib-js/stdlib/commit/e1993a6ee84bd212b5a00210e360b14e2a979f3a) - add `put` to namespace
@@ -1612,6 +1613,28 @@ This release closes the following issue:
+
+
+#### [@stdlib/array/mskput](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/mskput)
+
+
+
+
+
+##### Features
+
+- [`201ce11`](https://github.com/stdlib-js/stdlib/commit/201ce11a0985502cfc82891fda3fe3b2d656afef) - add `array/mskput`
+
+
+
+
+
+
+
+
+
+
+
#### [@stdlib/array/mskreject](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/mskreject)
@@ -2139,6 +2162,8 @@ A total of 13 people contributed to this release. Thank you to the following con
+- [`0b727a5`](https://github.com/stdlib-js/stdlib/commit/0b727a5d922225d23693e456b5f7b5b82f63750a) - **feat:** add `mskput` to namespace _(by Athan Reines)_
+- [`201ce11`](https://github.com/stdlib-js/stdlib/commit/201ce11a0985502cfc82891fda3fe3b2d656afef) - **feat:** add `array/mskput` _(by Athan Reines)_
- [`82a217c`](https://github.com/stdlib-js/stdlib/commit/82a217c79f7c10d4aca129fbaba753ce5055115a) - **feat:** add `place` to namespace _(by Athan Reines)_
- [`7b97e18`](https://github.com/stdlib-js/stdlib/commit/7b97e18463ee395851cb173559793a9d2a7c37e3) - **feat:** add `array/place` _(by Athan Reines)_
- [`00fd68d`](https://github.com/stdlib-js/stdlib/commit/00fd68ddf80a71b08e5353c63c297fca4daaf873) - **feat:** update namespace TypeScript declarations [(#2415)](https://github.com/stdlib-js/stdlib/pull/2415) _(by stdlib-bot, Athan Reines)_
diff --git a/lib/index.js b/lib/index.js
index 8547623d..596b73c6 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -364,6 +364,15 @@ setReadOnly( ns, 'mostlySafeCasts', require( './../mostly-safe-casts' ) );
*/
setReadOnly( ns, 'mskfilter', require( './../mskfilter' ) );
+/**
+* @name mskput
+* @memberof ns
+* @readonly
+* @constructor
+* @see {@link module:@stdlib/array/mskput}
+*/
+setReadOnly( ns, 'mskput', require( './../mskput' ) );
+
/**
* @name mskreject
* @memberof ns
diff --git a/mskput/README.md b/mskput/README.md
new file mode 100644
index 00000000..511d3e2b
--- /dev/null
+++ b/mskput/README.md
@@ -0,0 +1,165 @@
+
+
+# mskput
+
+> Replace elements of an array with provided values according to a provided mask array.
+
+
+
+## Usage
+
+```javascript
+var mskput = require( '@stdlib/array/mskput' );
+```
+
+#### mskput( x, mask, values\[, options] )
+
+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 ] );
+// 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.
+- **options**: function options.
+
+The function supports the following options:
+
+- **mode**: string specifying behavior when the number of `values` does not equal the number of falsy `mask` values. Default: `'repeat'`.
+
+The function supports the following modes:
+
+- `'strict'`: specifies that the function must raise an exception when the number of `values` does not **exactly** equal the number of falsy `mask` values.
+- `'non_strict'`: specifies that the function must raise an exception when the function is provided insufficient `values` to satisfy the `mask` array.
+- `'strict_broadcast'`: specifies that the function must broadcast a single-element `values` array and otherwise raise an exception when the number of `values` does not **exactly** equal the number of falsy `mask` values.
+- `'broadcast'`: specifies that the function must broadcast a single-element `values` array and otherwise 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.
+
+In broadcasting modes, 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 ], {
+ 'mode': 'strict_broadcast'
+});
+// returns [ 1, 20, 3, 20 ]
+
+var bool = ( out === x );
+// returns true
+```
+
+In repeat mode, the function supports recycling elements in a `values` array to satisfy the number of falsy values in the `mask` array.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var out = mskput( x, [ 0, 0, 1, 0 ], [ 20, 40 ], {
+ 'mode': 'repeat'
+});
+// returns [ 20, 40, 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.
+- 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 bernoulli = require( '@stdlib/random/base/bernoulli' );
+var linspace = require( '@stdlib/array/base/linspace' );
+var mskput = require( '@stdlib/array/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 );
+console.log( out );
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[@stdlib/array/dtypes]: https://github.com/stdlib-js/array/tree/main/dtypes
+
+[@stdlib/array/safe-casts]: https://github.com/stdlib-js/array/tree/main/safe-casts
+
+[@stdlib/array/same-kind-casts]: https://github.com/stdlib-js/array/tree/main/same-kind-casts
+
+
+
+
diff --git a/mskput/benchmark/benchmark.js b/mskput/benchmark/benchmark.js
new file mode 100644
index 00000000..f276a341
--- /dev/null
+++ b/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 );
+ 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 ] );
+ 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/mskput/benchmark/benchmark.length.js b/mskput/benchmark/benchmark.length.js
new file mode 100644
index 00000000..860c9d22
--- /dev/null
+++ b/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 ] );
+ 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/mskput/docs/repl.txt b/mskput/docs/repl.txt
new file mode 100644
index 00000000..ddeb6756
--- /dev/null
+++ b/mskput/docs/repl.txt
@@ -0,0 +1,68 @@
+
+{{alias}}( x, mask, values[, options] )
+ Replaces elements of an array with provided values according to a provided
+ mask array.
+
+ In broadcasting modes, the function supports broadcasting a values array
+ containing a single element against the number of falsy values in the mask
+ array.
+
+ In repeat mode, the function supports recycling elements in a values array
+ to satisfy 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.
+
+ options: Object (optional)
+ Function options.
+
+ options.mode: string (optional)
+ String specifying behavior when the number of values to set does not
+ equal the number of falsy mask values. The function supports the
+ following modes:
+
+ - 'strict': specifies that the function must raise an exception when the
+ number of values does not *exactly* equal the number of falsy mask
+ values.
+ - 'non_strict': specifies that the function must raise an exception when
+ the function is provided insufficient values to satisfy the mask array.
+ - 'strict_broadcast': specifies that the function must broadcast a
+ single-element values array and otherwise raise an exception when the
+ number of values does not **exactly** equal the number of falsy mask
+ values.
+ - 'broadcast': specifies that the function must broadcast a single-
+ element values array and otherwise 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.
+
+ Default: 'repeat'.
+
+ Returns
+ -------
+ out: ArrayLikeObject
+ Input array.
+
+ Examples
+ --------
+ > var x = [ 1, 2, 3, 4 ];
+ > var out = {{alias}}( x, [ 1, 0, 1, 0 ], [ 20, 40 ] )
+ [ 1, 20, 3, 40 ]
+ > var bool = ( out === x )
+ true
+
+ See Also
+ --------
+
diff --git a/mskput/docs/types/index.d.ts b/mskput/docs/types/index.d.ts
new file mode 100644
index 00000000..105a9874
--- /dev/null
+++ b/mskput/docs/types/index.d.ts
@@ -0,0 +1,232 @@
+/*
+* @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;
+
+/**
+* Interface describing function options.
+*/
+interface Options {
+ /**
+ * Mode specifying behavior when the number of values to set does not equal the number of falsy values in the mask array.
+ *
+ * ## Notes
+ *
+ * - The function supports the following modes:
+ *
+ * - `'strict'`: specifies that the function must raise an exception when the number of `values` does not **exactly** equal the number of falsy `mask` values.
+ * - `'non_strict'`: specifies that the function must raise an exception when the function is provided insufficient `values` to satisfy the `mask` array.
+ * - `'strict_broadcast'`: specifies that the function must broadcast a single-element `values` array and otherwise raise an exception when the number of `values` does not **exactly** equal the number of falsy `mask` values.
+ * - `'broadcast'`: specifies that the function must broadcast a single-element `values` array and otherwise 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.
+ */
+ mode?: 'strict' | 'non_strict' | 'strict_broadcast' | 'broadcast' | '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 options - function options
+* @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 );
+* // 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 ] );
+* // returns [ 1, 30, 30, 4 ]
+*
+* var bool = ( out === x );
+* // returns true
+*/
+declare function mskput( x: T, mask: MaskArray, values: ValuesArray, options?: Options ): 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 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 mask = [ 1, 0, 0, 1 ];
+* var values = new Complex128Array( [ 20.0, 30.0, 40, 5.0 ] );
+*
+* var out = mskput( x, mask, 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 mask = [ 1, 0, 0, 1 ];
+* var values = new Complex128Array( [ 20.0, 30.0 ] );
+*
+* var out = mskput( x, mask, values );
+* // returns
+*
+* var bool = ( out === x );
+* // returns true
+*/
+declare function mskput( x: T, mask: MaskArray, values: ValuesArray, options?: Options ): 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 options - function options
+* @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 );
+* // 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 ] );
+* // returns [ 1, 30, 30, 4 ]
+*
+* var bool = ( out === x );
+* // returns true
+*/
+declare function mskput( x: Array, mask: MaskArray, values: ValuesArray, options?: Options ): 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 options - function options
+* @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 );
+*
+* 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 ] );
+*
+* var bool = ( out === x );
+* // returns true
+*/
+declare function mskput( x: AccessorArrayLike, mask: MaskArray, values: ValuesArray, options?: Options ): 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 options - function options
+* @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 );
+* // 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 ] );
+* // returns [ 1, 30, 30, 4 ]
+*
+* var bool = ( out === x );
+* // returns true
+*/
+declare function mskput( x: Collection, mask: MaskArray, values: ValuesArray, options?: Options ): Collection;
+
+
+// EXPORTS //
+
+export = mskput;
diff --git a/mskput/docs/types/test.ts b/mskput/docs/types/test.ts
new file mode 100644
index 00000000..00ca07b3
--- /dev/null
+++ b/mskput/docs/types/test.ts
@@ -0,0 +1,96 @@
+/*
+* @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 ] ); // $ExpectType number[]
+ mskput( new Int32Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectType Int32Array
+ mskput( new Complex128Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ] ); // $ExpectType Complex128Array
+ mskput( new Complex64Array( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], [ new Complex128( 20, 30 ), [ 40, 50 ] ] ); // $ExpectType Complex64Array
+ mskput( new AccessorArray( [ 1, 2, 3, 4 ] ), [ 1, 0, 0, 1 ], 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...
+{
+ mskput( 1, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectError
+ mskput( true, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectError
+ mskput( false, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectError
+ mskput( null, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectError
+ mskput( void 0, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $ExpectError
+ mskput( {}, [ 1, 0, 0, 1 ], [ 20, 30 ] ); // $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 ] ); // $ExpectError
+ mskput( [], true, [ 20, 30 ] ); // $ExpectError
+ mskput( [], false, [ 20, 30 ] ); // $ExpectError
+ mskput( [], null, [ 20, 30 ] ); // $ExpectError
+ mskput( [], void 0, [ 20, 30 ] ); // $ExpectError
+ mskput( [], {}, [ 20, 30 ] ); // $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 ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], true ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], false ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], null ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], void 0 ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], {} ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a fourth argument which is not an object...
+{
+ 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 ], [] ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 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 mode...
+{
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': '1' } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': 1 } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': true } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': false } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': null } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': {} } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': [] } ); // $ExpectError
+ mskput( [], [ 1, 0, 0, 1 ], [ 20, 30 ], { 'mode': ( 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
+}
diff --git a/mskput/examples/index.js b/mskput/examples/index.js
new file mode 100644
index 00000000..78c40faf
--- /dev/null
+++ b/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 );
+console.log( out );
diff --git a/mskput/lib/defaults.js b/mskput/lib/defaults.js
new file mode 100644
index 00000000..ae985155
--- /dev/null
+++ b/mskput/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': 'repeat'
+ };
+}
+
+
+// EXPORTS //
+
+module.exports = defaults;
diff --git a/mskput/lib/index.js b/mskput/lib/index.js
new file mode 100644
index 00000000..d0d90b4a
--- /dev/null
+++ b/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/mskput
+*
+* @example
+* var mskput = require( '@stdlib/array/mskput' );
+*
+* var x = [ 1, 2, 3, 4 ];
+*
+* var mask = [ 1, 0, 0, 1 ];
+* var values = [ 20, 30 ];
+*
+* var out = mskput( x, mask, 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/mskput/lib/main.js b/mskput/lib/main.js
new file mode 100644
index 00000000..aaf80b55
--- /dev/null
+++ b/mskput/lib/main.js
@@ -0,0 +1,130 @@
+/**
+* @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/mskput' );
+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 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 {Options} [options] - function options
+* @param {string} [options.mode='repeat'] - string specifying behavior when the number of values does not equal the number of falsy mask values
+* @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} insufficient values to satisfy mask array
+* @throws {Error} number of values does not equal the number of falsy mask values
+* @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 mask = [ 1, 0, 0, 1 ];
+* var values = [ 20, 30 ];
+*
+* var out = mskput( x, mask, values );
+* // 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 );
+* // returns [ 1, 30, 30, 4 ]
+*
+* var bool = ( out === x );
+* // returns true
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+*
+* var mask = [ 0, 0, 1, 0 ];
+* var values = [ 20, 30 ];
+*
+* var out = mskput( x, mask, values );
+* // returns [ 20, 30, 3, 20 ]
+*
+* var bool = ( out === x );
+* // returns true
+*/
+function mskput( x, mask, 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( mask ) ) {
+ throw new TypeError( format( 'invalid argument. Second argument must be an array-like object. Value: `%s`.', mask ) );
+ }
+ 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, mask, values, opts.mode );
+}
+
+
+// EXPORTS //
+
+module.exports = mskput;
diff --git a/mskput/lib/validate.js b/mskput/lib/validate.js
new file mode 100644
index 00000000..acb45951
--- /dev/null
+++ b/mskput/lib/validate.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 isObject = require( '@stdlib/assert/is-plain-object' );
+var hasOwnProp = require( '@stdlib/assert/has-own-property' );
+var contains = require( './../../base/assert/contains' ).factory;
+var format = require( '@stdlib/string/format' );
+
+
+// VARIABLES //
+
+var MODES = [
+ 'strict',
+ 'non_strict',
+ 'strict_broadcast',
+ 'broadcast',
+ 'repeat'
+];
+var isMode = contains( MODES );
+
+
+// MAIN //
+
+/**
+* Validates function options.
+*
+* @private
+* @param {Object} opts - destination object
+* @param {Options} options - function options
+* @param {string} [options.mode] - mode option
+* @returns {(Error|null)} null or an error object
+*
+* @example
+* var opts = {};
+* var options = {
+* 'mode': 'strict'
+* };
+* 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 ( !isMode( 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/mskput/package.json b/mskput/package.json
new file mode 100644
index 00000000..a3730c38
--- /dev/null
+++ b/mskput/package.json
@@ -0,0 +1,65 @@
+{
+ "name": "@stdlib/array/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/mskput/test/test.js b/mskput/test/test.js
new file mode 100644
index 00000000..c6135a73
--- /dev/null
+++ b/mskput/test/test.js
@@ -0,0 +1,696 @@
+/**
+* @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 zeros = require( './../../zeros' );
+var toAccessorArray = require( './../../base/to-accessor-array' );
+var isAccessorArray = require( '@stdlib/assert/is-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 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() {
+ mskput( 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() {
+ mskput( 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() {
+ mskput( [], 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() {
+ mskput( [], 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() {
+ mskput( [], [], 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() {
+ mskput( [], [], 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() {
+ mskput( [], [], [], value );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided a `mode` option which is not a valid 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() {
+ mskput( [], [], [], {
+ 'mode': 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() {
+ mskput( value, zeros( 5, 'generic' ), values );
+ };
+ }
+});
+
+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 ] );
+ 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 ] );
+ 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 ] );
+ 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 ] );
+ 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 ] );
+ 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 ] );
+ 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 ] );
+ 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 ] ) );
+ 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 ] ) );
+ 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 ] ) );
+ 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, 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 ] );
+ mask = [ 0, 0, 0, 0 ];
+ actual = mskput( x, mask, new Int32Array( [ 20 ] ) );
+ 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, new Int32Array( [ 20 ] ) );
+ 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, new Int32Array( [ 100, 200 ] ) );
+ 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 mask;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ mask = toAccessorArray( [ 1, 0, 1, 0 ] );
+ actual = mskput( toAccessorArray( x ), mask, toAccessorArray( [ 20, 40 ] ) ); // eslint-disable-line max-len
+ 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 ];
+ mask = toAccessorArray( [ 0, 0, 0, 0 ] );
+ actual = mskput( toAccessorArray( x ), mask, toAccessorArray( [ 20, 30, 40, 50 ] ) ); // eslint-disable-line max-len
+ expected = [ 20, 30, 40, 50 ];
+ t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' );
+ t.deepEqual( x, expected, 'returns expected value' );
+
+ x = [ 1, 2, 3, 4 ];
+ mask = toAccessorArray( [ 1, 1, 1, 1 ] );
+ actual = mskput( toAccessorArray( x ), mask, [ 20, 30, 40, 50 ] );
+ expected = [ 1, 2, 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, broadcasting)', function test( t ) {
+ var expected;
+ var actual;
+ var mask;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ mask = toAccessorArray( [ 1, 0, 1, 0 ] );
+ actual = mskput( toAccessorArray( x ), mask, 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 ];
+ mask = toAccessorArray( [ 0, 0, 0, 0 ] );
+ actual = mskput( toAccessorArray( x ), mask, 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 ];
+ mask = toAccessorArray( [ 1, 1, 1, 1 ] );
+ actual = mskput( toAccessorArray( x ), mask, toAccessorArray( [ 20 ] ) );
+ expected = [ 1, 2, 3, 4 ];
+ t.strictEqual( isAccessorArray( actual ), true, 'returns expected value' );
+ t.deepEqual( x, expected, 'returns expected value' );
+
+ x = [ 1, 2, 3, 4 ];
+ mask = toAccessorArray( [ 0, 0, 0, 0 ] );
+ actual = mskput( toAccessorArray( x ), mask, toAccessorArray( [ 100, 200 ] ) ); // eslint-disable-line max-len
+ expected = [ 100, 200, 100, 200 ];
+ 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, 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 );
+
+ 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 );
+
+ 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 );
+
+ 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 = new BooleanArray( [ true ] );
+ expected = [ true, true, true, true ];
+ actual = mskput( x, mask, values );
+
+ 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 "strict", 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 ], {
+ 'mode': 'strict'
+ });
+ }
+});
+
+tape( 'when the "mode" is "strict", the function throws an error if provided too many 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, 300, 400, 500, 600 ], {
+ 'mode': 'strict'
+ });
+ }
+});
+
+tape( 'when the "mode" is "non_strict", 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 ], {
+ 'mode': 'non_strict'
+ });
+ }
+});
+
+tape( 'when the "mode" is "strict_broadcast", the function throws an error if provided a values array which is broadcast incompatible with the number of falsy values in a mask array (insufficient)', 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, 400 ], {
+ 'mode': 'strict_broadcast'
+ });
+ }
+});
+
+tape( 'when the "mode" is "strict_broadcast", the function throws an error if provided a values array which is broadcast incompatible with the number of falsy values in a mask array (too many)', 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, 400, 500, 600, 700 ], {
+ 'mode': 'strict_broadcast'
+ });
+ }
+});
+
+tape( 'when the "mode" is "broadcast", the function throws an error if provided a values array which is broadcast incompatible with the number of falsy values in a 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, 400 ], {
+ 'mode': 'broadcast'
+ });
+ }
+});
diff --git a/mskput/test/test.validate.js b/mskput/test/test.validate.js
new file mode 100644
index 00000000..50239210
--- /dev/null
+++ b/mskput/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': 'strict'
+ };
+ opts = {};
+
+ expected = {
+ 'mode': 'strict'
+ };
+
+ 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();
+});