diff --git a/base/bifurcate-entries-by/README.md b/base/bifurcate-entries-by/README.md
index ef650f9b..fd538b90 100644
--- a/base/bifurcate-entries-by/README.md
+++ b/base/bifurcate-entries-by/README.md
@@ -103,7 +103,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateEntriesBy = require( '@stdlib/array/base/bifurcate-entries-by' );
function predicate( v ) {
diff --git a/base/bifurcate-entries-by/examples/index.js b/base/bifurcate-entries-by/examples/index.js
index 29171fdc..5d8648ce 100644
--- a/base/bifurcate-entries-by/examples/index.js
+++ b/base/bifurcate-entries-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateEntriesBy = require( './../lib' );
function predicate( v ) {
diff --git a/base/bifurcate-entries/README.md b/base/bifurcate-entries/README.md
index 94c2b16f..a97d93dc 100644
--- a/base/bifurcate-entries/README.md
+++ b/base/bifurcate-entries/README.md
@@ -78,7 +78,7 @@ var out = bifurcateEntries( x, filter );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateEntries = require( '@stdlib/array/base/bifurcate-entries' );
// Define an initial array of values:
diff --git a/base/bifurcate-entries/examples/index.js b/base/bifurcate-entries/examples/index.js
index d0fc5610..05a08df1 100644
--- a/base/bifurcate-entries/examples/index.js
+++ b/base/bifurcate-entries/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateEntries = require( './../lib' );
// Define an initial array of values:
diff --git a/base/bifurcate-indices-by/README.md b/base/bifurcate-indices-by/README.md
index 09951f88..e4433eef 100644
--- a/base/bifurcate-indices-by/README.md
+++ b/base/bifurcate-indices-by/README.md
@@ -103,7 +103,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateIndicesBy = require( '@stdlib/array/base/bifurcate-indices-by' );
function predicate( v ) {
diff --git a/base/bifurcate-indices-by/examples/index.js b/base/bifurcate-indices-by/examples/index.js
index 32fee448..41db341b 100644
--- a/base/bifurcate-indices-by/examples/index.js
+++ b/base/bifurcate-indices-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateIndicesBy = require( './../lib' );
function predicate( v ) {
diff --git a/base/bifurcate-indices/README.md b/base/bifurcate-indices/README.md
index 512034d4..e1f85ad2 100644
--- a/base/bifurcate-indices/README.md
+++ b/base/bifurcate-indices/README.md
@@ -78,7 +78,7 @@ var out = bifurcateIndices( x, filter );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateIndices = require( '@stdlib/array/base/bifurcate-indices' );
// Define an initial array of values:
diff --git a/base/bifurcate-indices/examples/index.js b/base/bifurcate-indices/examples/index.js
index f6d58973..acc01b9c 100644
--- a/base/bifurcate-indices/examples/index.js
+++ b/base/bifurcate-indices/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateIndices = require( './../lib' );
// Define an initial array of values:
diff --git a/base/bifurcate-values-by/README.md b/base/bifurcate-values-by/README.md
index f8761152..86ed195c 100644
--- a/base/bifurcate-values-by/README.md
+++ b/base/bifurcate-values-by/README.md
@@ -103,7 +103,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateValuesBy = require( '@stdlib/array/base/bifurcate-values-by' );
function predicate( v ) {
diff --git a/base/bifurcate-values-by/examples/index.js b/base/bifurcate-values-by/examples/index.js
index 756cd64a..00eefb73 100644
--- a/base/bifurcate-values-by/examples/index.js
+++ b/base/bifurcate-values-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateValuesBy = require( './../lib' );
function predicate( v ) {
diff --git a/base/bifurcate-values/README.md b/base/bifurcate-values/README.md
index 04537763..c56c4f01 100644
--- a/base/bifurcate-values/README.md
+++ b/base/bifurcate-values/README.md
@@ -78,7 +78,7 @@ var out = bifurcateValues( x, filter );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var bifurcateValues = require( '@stdlib/array/base/bifurcate-values' );
// Define an initial array of values:
diff --git a/base/bifurcate-values/examples/index.js b/base/bifurcate-values/examples/index.js
index 5530fffc..5bcfddf1 100644
--- a/base/bifurcate-values/examples/index.js
+++ b/base/bifurcate-values/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var bifurcateValues = require( './../lib' );
// Define an initial array of values:
diff --git a/base/fancy-slice-assign/lib/main.js b/base/fancy-slice-assign/lib/main.js
index 2eb0d0d7..96a4709a 100644
--- a/base/fancy-slice-assign/lib/main.js
+++ b/base/fancy-slice-assign/lib/main.js
@@ -21,9 +21,12 @@
// 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 normalizeSlice = require( '@stdlib/slice/base/normalize-slice' );
var sliceLength = require( '@stdlib/slice/base/length' );
var dtype = require( './../../../dtype' );
+var convert = require( './../../../convert' );
var gcopy = require( '@stdlib/blas/base/gcopy' ).ndarray;
var format = require( '@stdlib/string/format' );
@@ -92,6 +95,10 @@ function sliceAssign( x, y, s, strict ) {
if ( !isMostlySafeCast( xdt, ydt ) ) {
throw new TypeError( format( 'invalid argument. Input array values cannot be safely cast to the output array data type. Data types: [%s, %s].', xdt, ydt ) );
}
+ // 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( ydt ) && isRealDataType( xdt ) ) {
+ x = convert( x, ydt );
+ }
// Normalize the slice object base on the output array length:
ns = normalizeSlice( s, ylen, true );
diff --git a/base/fancy-slice-assign/test/test.js b/base/fancy-slice-assign/test/test.js
index a7c0b3b1..e3c1fc29 100644
--- a/base/fancy-slice-assign/test/test.js
+++ b/base/fancy-slice-assign/test/test.js
@@ -21,8 +21,13 @@
// MODULES //
var tape = require( 'tape' );
+var isSameComplex128Array = require( '@stdlib/assert/is-same-complex128array' );
+var isSameComplex64Array = require( '@stdlib/assert/is-same-complex64array' );
var AccessorArray = require( './../../../base/accessor' );
var Float64Array = require( './../../../float64' );
+var Float32Array = require( './../../../float32' );
+var Complex128Array = require( './../../../complex128' );
+var Complex64Array = require( './../../../complex64' );
var Int32Array = require( './../../../int32' );
var zeros = require( './../../../zeros' );
var Slice = require( '@stdlib/slice/ctor' );
@@ -261,15 +266,15 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.deepEqual( actual, expected, 'returns expected value' );
x = new Float64Array( [ 1.0, 2.0, 3.0 ] );
- y = zeros( 3, 'float64' );
+ y = zeros( 3, 'float32' ); // downcast
- expected = new Float64Array( [ 3.0, 2.0, 1.0 ] );
+ expected = new Float32Array( [ 3.0, 2.0, 1.0 ] );
actual = sliceAssign( x, y, new Slice( null, null, -1 ), false );
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 1, 3 ] );
+ x = new Float64Array( [ 1.0, 3.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 3.0, 0.0, 1.0 ] );
@@ -278,16 +283,16 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 1, 3 ] );
- y = zeros( 3, 'float64' );
+ x = new Float64Array( [ 1.0, 3.0 ] );
+ y = zeros( 3, 'float32' ); // downcast
- expected = new Float64Array( [ 1.0, 0.0, 3.0 ] );
+ expected = new Float32Array( [ 1.0, 0.0, 3.0 ] );
actual = sliceAssign( x, y, new Slice( null, null, 2 ), false );
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 2, 3 ] );
+ x = new Float64Array( [ 2.0, 3.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 0.0, 2.0, 3.0 ] );
@@ -296,7 +301,7 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 2 ] );
+ x = new Float64Array( [ 2.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 0.0, 2.0, 0.0 ] );
@@ -305,7 +310,7 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 1 ] );
+ x = new Float64Array( [ 1.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 0.0, 0.0, 0.0 ] );
@@ -315,7 +320,7 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.deepEqual( actual, expected, 'returns expected value' );
// Broadcasting:
- x = new Float64Array( [ 1 ] );
+ x = new Float64Array( [ 1.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 1.0, 1.0, 1.0 ] );
@@ -324,7 +329,7 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
- x = new Float64Array( [ 3 ] );
+ x = new Float64Array( [ 3.0 ] );
y = zeros( 3, 'float64' );
expected = new Float64Array( [ 3.0, 0.0, 3.0 ] );
@@ -333,6 +338,107 @@ tape( 'the function performs slice assignment with support for broadcasting (flo
t.strictEqual( actual, y, 'returns expected value' );
t.deepEqual( actual, expected, 'returns expected value' );
+ // Upcasting:
+ x = new Float64Array( [ 1.0, 2.0, 3.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 1.0, 0.0, 2.0, 0.0, 3.0, 0.0 ] );
+ actual = sliceAssign( x, y, new Slice(), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function performs slice assignment with support for broadcasting (complex128)', function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+ actual = sliceAssign( x, y, new Slice(), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 5.0, 6.0, 3.0, 4.0, 1.0, 2.0 ] );
+ actual = sliceAssign( x, y, new Slice( null, null, -1 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ y = zeros( 3, 'complex64' ); // downcast
+
+ expected = new Complex64Array( [ 3.0, 4.0, 0.0, 0.0, 1.0, 2.0 ] );
+ actual = sliceAssign( x, y, new Slice( null, null, -2 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 1.0, 2.0, 0.0, 0.0, 3.0, 4.0 ] );
+ actual = sliceAssign( x, y, new Slice( null, null, 2 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 0.0, 0.0, 1.0, 2.0, 3.0, 4.0 ] );
+ actual = sliceAssign( x, y, new Slice( 1, null ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0 ] );
+ y = zeros( 3, 'complex64' ); // downcast
+
+ expected = new Complex64Array( [ 0.0, 0.0, 1.0, 2.0, 0.0, 0.0 ] );
+ actual = sliceAssign( x, y, new Slice( 1, y.length-1 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] );
+ actual = sliceAssign( x, y, new Slice( 1, 1 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ // Broadcasting:
+ x = new Complex128Array( [ 1.0, 2.0 ] );
+ y = zeros( 3, 'complex128' );
+
+ expected = new Complex128Array( [ 1.0, 2.0, 1.0, 2.0, 1.0, 2.0 ] );
+ actual = sliceAssign( x, y, new Slice(), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex128Array( [ 3.0, 4.0 ] );
+ y = zeros( 3, 'complex64' ); // downcast
+
+ expected = new Complex64Array( [ 3.0, 4.0, 0.0, 0.0, 3.0, 4.0 ] );
+ actual = sliceAssign( x, y, new Slice( null, null, 2 ), false );
+
+ t.strictEqual( actual, y, 'returns expected value' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
t.end();
});
diff --git a/base/group-entries-by/README.md b/base/group-entries-by/README.md
index 32762748..3ea2b7e1 100644
--- a/base/group-entries-by/README.md
+++ b/base/group-entries-by/README.md
@@ -119,7 +119,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupEntriesBy = require( '@stdlib/array/base/group-entries-by' );
function indicator( v ) {
diff --git a/base/group-entries-by/examples/index.js b/base/group-entries-by/examples/index.js
index c60ec912..a81cfeca 100644
--- a/base/group-entries-by/examples/index.js
+++ b/base/group-entries-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupEntriesBy = require( './../lib' );
function indicator( v ) {
diff --git a/base/group-entries/README.md b/base/group-entries/README.md
index 79c45b83..a96910f4 100644
--- a/base/group-entries/README.md
+++ b/base/group-entries/README.md
@@ -88,7 +88,7 @@ var out = groupEntries( x, groups );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupEntries = require( '@stdlib/array/base/group-entries' );
// Define an initial array of values:
diff --git a/base/group-entries/examples/index.js b/base/group-entries/examples/index.js
index 8aa03bd0..652ab459 100644
--- a/base/group-entries/examples/index.js
+++ b/base/group-entries/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupEntries = require( './../lib' );
// Define an initial array of values:
diff --git a/base/group-indices-by/README.md b/base/group-indices-by/README.md
index 0ae6809b..2cbad4ce 100644
--- a/base/group-indices-by/README.md
+++ b/base/group-indices-by/README.md
@@ -119,7 +119,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupIndicesBy = require( '@stdlib/array/base/group-indices-by' );
function indicator( v ) {
diff --git a/base/group-indices-by/examples/index.js b/base/group-indices-by/examples/index.js
index e5d405b8..ab07de39 100644
--- a/base/group-indices-by/examples/index.js
+++ b/base/group-indices-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupIndicesBy = require( './../lib' );
function indicator( v ) {
diff --git a/base/group-indices/README.md b/base/group-indices/README.md
index 992dcbad..18703746 100644
--- a/base/group-indices/README.md
+++ b/base/group-indices/README.md
@@ -88,7 +88,7 @@ var out = groupIndices( x, groups );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupIndices = require( '@stdlib/array/base/group-indices' );
// Define an initial array of values:
diff --git a/base/group-indices/examples/index.js b/base/group-indices/examples/index.js
index 95cf3f18..37217361 100644
--- a/base/group-indices/examples/index.js
+++ b/base/group-indices/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupIndices = require( './../lib' );
// Define an initial array of values:
diff --git a/base/group-values-by/README.md b/base/group-values-by/README.md
index 124428bb..ee14a57b 100644
--- a/base/group-values-by/README.md
+++ b/base/group-values-by/README.md
@@ -119,7 +119,7 @@ var cnt = context.count;
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupValuesBy = require( '@stdlib/array/base/group-values-by' );
function indicator( v ) {
diff --git a/base/group-values-by/examples/index.js b/base/group-values-by/examples/index.js
index 8a0af9c0..56ec38e7 100644
--- a/base/group-values-by/examples/index.js
+++ b/base/group-values-by/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupValuesBy = require( './../lib' );
function indicator( v ) {
diff --git a/base/group-values/README.md b/base/group-values/README.md
index 7d250335..bd228e1a 100644
--- a/base/group-values/README.md
+++ b/base/group-values/README.md
@@ -88,7 +88,7 @@ var out = groupValues( x, groups );
```javascript
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( '@stdlib/array/base/take' );
+var take = require( '@stdlib/array/base/take-indexed' );
var groupValues = require( '@stdlib/array/base/group-values' );
// Define an initial array of values:
diff --git a/base/group-values/examples/index.js b/base/group-values/examples/index.js
index 4e97ac48..2775b3e1 100644
--- a/base/group-values/examples/index.js
+++ b/base/group-values/examples/index.js
@@ -19,7 +19,7 @@
'use strict';
var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
-var take = require( './../../../base/take' );
+var take = require( './../../../base/take-indexed' );
var groupValues = require( './../lib' );
// Define an initial array of values:
diff --git a/base/take/README.md b/base/take/README.md
index 525fb8e5..89394087 100644
--- a/base/take/README.md
+++ b/base/take/README.md
@@ -30,36 +30,64 @@ limitations under the License.
var take = require( '@stdlib/array/base/take' );
```
-#### take( x, indices )
+#### take( x, indices, mode )
Takes elements from an array.
```javascript
var x = [ 1, 2, 3, 4 ];
-var y = take( x, [ 1, 3 ] );
+var y = take( x, [ 1, 3 ], 'throw' );
// returns [ 2, 4 ]
```
+The function supports the following parameters:
+
+- **x**: input array.
+- **indices**: list of indices.
+- **mode**: index [mode][@stdlib/ndarray/base/ind].
+
If `indices` is an empty array, the function returns an empty array.
```javascript
var x = [ 1, 2, 3, 4 ];
-var y = take( x, [] );
+var y = take( x, [], 'throw' );
// returns []
```
+#### take.assign( x, indices, mode, out, stride, offset )
+
+Takes elements from an array and assigns the values to elements in a provided output array.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var out = [ 0, 0, 0, 0, 0, 0 ];
+var indices = [ 0, 0, 1, 1, 3, 3 ];
+
+var arr = take.assign( x, indices, 'throw', out, -1, out.length-1 );
+// returns [ 4, 4, 2, 2, 1, 1 ]
+
+var bool = ( arr === out );
+// returns true
+```
+
+The function supports the following parameters:
+
+- **x**: input array.
+- **indices**: list of indices.
+- **mode**: index [mode][@stdlib/ndarray/base/ind].
+- **out**: output array.
+- **stride**: output array stride.
+- **offset**: output array offset.
+
-## Notes
-
-- The function does **not** perform bounds checking. If an index is less than zero or greater than the maximum index of `x`, the value of the corresponding element in the output array is undefined.
-
@@ -84,7 +112,7 @@ var N = discreteUniform( 5, 15 );
var indices = filledBy( N, discreteUniform.factory( 0, x.length-1 ) );
// Take a random sample of elements from `x`:
-var y = take( x, indices );
+var y = take( x, indices, 'throw' );
console.log( x );
console.log( indices );
@@ -107,6 +135,8 @@ console.log( y );
+[@stdlib/ndarray/base/ind]: https://github.com/stdlib-js/ndarray-base-ind
+
diff --git a/base/take/benchmark/benchmark.assign.length.js b/base/take/benchmark/benchmark.assign.length.js
new file mode 100644
index 00000000..330c1c46
--- /dev/null
+++ b/base/take/benchmark/benchmark.assign.length.js
@@ -0,0 +1,106 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2022 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( './../../../zeros' );
+var isArray = require( '@stdlib/assert/is-array' );
+var pkg = require( './../package.json' ).name;
+var take = require( './../lib' );
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} len - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( len ) {
+ var out;
+ var idx;
+
+ idx = discreteUniform( len, 0, 3, {
+ 'dtype': 'generic'
+ });
+ out = zeros( len, 'generic' );
+
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var x;
+ var v;
+ var i;
+
+ x = [ 1, 2, 3, 4 ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = take.assign( x, idx, 'throw', out, 1, 0 );
+ 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+':assign:len='+len, f );
+ }
+}
+
+main();
diff --git a/base/take/benchmark/benchmark.js b/base/take/benchmark/benchmark.js
index 51ae6f5e..fdd872ce 100644
--- a/base/take/benchmark/benchmark.js
+++ b/base/take/benchmark/benchmark.js
@@ -38,7 +38,7 @@ bench( pkg+'::copy:len=100', function benchmark( b ) {
b.tic();
for ( i = 0; i < b.iterations; i++ ) {
- v = take( x, x );
+ v = take( x, x, 'throw' );
if ( typeof v !== 'object' ) {
b.fail( 'should return an array' );
}
diff --git a/base/take/benchmark/benchmark.length.js b/base/take/benchmark/benchmark.length.js
index 01697bdc..1ac63bf0 100644
--- a/base/take/benchmark/benchmark.length.js
+++ b/base/take/benchmark/benchmark.length.js
@@ -22,8 +22,7 @@
var bench = require( '@stdlib/bench' );
var pow = require( '@stdlib/math/base/special/pow' );
-var filledBy = require( './../../../base/filled-by' );
-var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ).factory;
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
var isArray = require( '@stdlib/assert/is-array' );
var pkg = require( './../package.json' ).name;
var take = require( './../lib' );
@@ -39,7 +38,7 @@ var take = require( './../lib' );
* @returns {Function} benchmark function
*/
function createBenchmark( len ) {
- var idx = filledBy( len, discreteUniform( 0, 3 ) );
+ var idx = discreteUniform( len, 0, 3 );
return benchmark;
/**
@@ -57,7 +56,7 @@ function createBenchmark( len ) {
b.tic();
for ( i = 0; i < b.iterations; i++ ) {
- v = take( x, idx );
+ v = take( x, idx, 'throw' );
if ( typeof v !== 'object' ) {
b.fail( 'should return an array' );
}
diff --git a/base/take/docs/repl.txt b/base/take/docs/repl.txt
index bedbcf02..429279ba 100644
--- a/base/take/docs/repl.txt
+++ b/base/take/docs/repl.txt
@@ -1,13 +1,9 @@
-{{alias}}( x, indices )
+{{alias}}( x, indices, mode )
Takes elements from an array.
If `indices` is an empty array, the function returns an empty array.
- The function does *not* perform bounds checking. If an index is less than
- zero or greater than the maximum index of `x`, the value of the
- corresponding element in the output array is undefined.
-
Parameters
----------
x: ArrayLikeObject
@@ -16,6 +12,15 @@
indices: ArrayLikeObject
List of element indices.
+ mode: string
+ Specifies how to handle an index outside the interval [0, max], where
+ `max` is the maximum possible array index. If equal to 'throw', the
+ function throws an error. If equal to 'normalize', the function throws
+ an error if provided an out-of-bounds normalized index. If equal to
+ 'wrap', the function wraps around an index using modulo arithmetic. If
+ equal to 'clamp', the function sets an index to either 0 (minimum index)
+ or the maximum index.
+
Returns
-------
out: Array
@@ -24,9 +29,54 @@
Examples
--------
> var x = [ 1, 2, 3, 4 ];
- > var y = {{alias}}( x, [ 1, 3 ] )
+ > var y = {{alias}}( x, [ 1, 3 ], 'throw' )
[ 2, 4 ]
+
+{{alias}}.assign( x, indices, mode, out, stride, offset )
+ Takes elements from an array and assigns the values to elements in a
+ provided output array.
+
+ Parameters
+ ----------
+ x: ArrayLikeObject
+ Input array.
+
+ indices: ArrayLikeObject
+ List of element indices.
+
+ mode: string
+ Specifies how to handle an index outside the interval [0, max], where
+ `max` is the maximum possible array index. If equal to 'throw', the
+ function throws an error. If equal to 'normalize', the function throws
+ an error if provided an out-of-bounds normalized index. If equal to
+ 'wrap', the function wraps around an index using modulo arithmetic. If
+ equal to 'clamp', the function sets an index to either 0 (minimum index)
+ or the maximum index.
+
+ out: ArrayLikeObject
+ Output array.
+
+ stride: integer
+ Output array stride.
+
+ offset: integer
+ Output array offset.
+
+ Returns
+ -------
+ out: ArrayLikeObject
+ Output array.
+
+ Examples
+ --------
+ > var x = [ 1, 2, 3, 4 ];
+ > var out = [ 0, 0, 0, 0 ];
+ > var arr = {{alias}}.assign( x, [ 1, 3 ], 'throw', out, 2, 0 )
+ [ 2, 0, 4, 0 ]
+ > var bool = ( arr === out )
+ true
+
See Also
--------
diff --git a/base/take/docs/types/index.d.ts b/base/take/docs/types/index.d.ts
index 04c74e02..06d7720b 100644
--- a/base/take/docs/types/index.d.ts
+++ b/base/take/docs/types/index.d.ts
@@ -20,26 +20,408 @@
///
-import { Collection } from '@stdlib/types/array';
+import { Collection, AccessorArrayLike, Complex128Array, Complex64Array } from '@stdlib/types/array';
+import { Mode } from '@stdlib/types/ndarray';
/**
-* Takes element from an array.
-*
-* ## Notes
-*
-* - The function does **not** perform bounds checking. If an index is less than zero or greater than the maximum index of `x`, the value of the corresponding element in the output array is undefined.
+* Index array.
+*/
+type IndexArray = Collection | AccessorArrayLike;
+
+/**
+* Interface describing `take`.
+*/
+interface Take {
+ /**
+ * Takes elements from an array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @returns output array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var y = take( x, [ 1, 3 ], 'throw' );
+ * // returns [ 2, 4 ]
+ */
+ ( x: Collection, indices: IndexArray, mode: Mode ): Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Float64Array = require( './../../../../float64' );
+ *
+ * var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ * var out = new Float64Array( [ 0.0, 0.0, 0.0, 0.0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2.0, 0.0, 4.0, 0.0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Float64Array, stride: number, offset: number ): Float64Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Float32Array = require( './../../../../float32' );
+ *
+ * var x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ * var out = new Float32Array( [ 0.0, 0.0, 0.0, 0.0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2.0, 0.0, 4.0, 0.0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Float32Array, stride: number, offset: number ): Float32Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Complex128Array = require( './../../../../float64' );
+ *
+ * var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+ * var out = new Complex128Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 3.0, 4.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Complex128Array, stride: number, offset: number ): Complex128Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Complex64Array = require( './../../../../float64' );
+ *
+ * var x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+ * var out = new Complex64Array( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 3.0, 4.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Complex64Array, stride: number, offset: number ): Complex64Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Int32Array = require( './../../../../int32' );
+ *
+ * var x = new Int32Array( [ 1, 2, 3, 4 ] );
+ * var out = new Int32Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Int32Array, stride: number, offset: number ): Int32Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Int16Array = require( './../../../../int16' );
+ *
+ * var x = new Int16Array( [ 1, 2, 3, 4 ] );
+ * var out = new Int16Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Int16Array, stride: number, offset: number ): Int16Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Int8Array = require( './../../../../int8' );
+ *
+ * var x = new Int8Array( [ 1, 2, 3, 4 ] );
+ * var out = new Int8Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Int8Array, stride: number, offset: number ): Int8Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Uint32Array = require( './../../../../uint32' );
+ *
+ * var x = new Uint32Array( [ 1, 2, 3, 4 ] );
+ * var out = new Uint32Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Uint32Array, stride: number, offset: number ): Uint32Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Uint16Array = require( './../../../../uint16' );
+ *
+ * var x = new Uint16Array( [ 1, 2, 3, 4 ] );
+ * var out = new Uint16Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Uint16Array, stride: number, offset: number ): Uint16Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Uint8Array = require( './../../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 2, 3, 4 ] );
+ * var out = new Uint8Array( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Uint8Array, stride: number, offset: number ): Uint8Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var Uint8ClampedArray = require( './../../../../uint8c' );
+ *
+ * var x = new Uint8ClampedArray( [ 1, 2, 3, 4 ] );
+ * var out = new Uint8ClampedArray( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Uint8ClampedArray, stride: number, offset: number ): Uint8ClampedArray;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ * var out = [ 0, 0, 0, 0 ];
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Array, stride: number, offset: number ): Array;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var toAccessorArray = require( './../../../../base/to-accessor-array' );
+ *
+ * var x = [ 1, 2, 3, 4 ];
+ * var out = toAccessorArray( [ 0, 0, 0, 0 ] );
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ *
+ * var v = arr.get( 0 );
+ * // returns 2
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: AccessorArrayLike, stride: number, offset: number ): AccessorArrayLike;
+
+ /**
+ * Takes elements from an array and assigns the value to elements in a provided output array.
+ *
+ * @param x - input array
+ * @param indices - list of element indices
+ * @param mode - index mode
+ * @param out - output array
+ * @param stride - output array stride
+ * @param offset - output array offset
+ * @returns output array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ * var out = [ 0, 0, 0, 0 ];
+ *
+ * var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+ * // returns [ 2, 0, 4, 0 ]
+ *
+ * var bool = ( arr === out );
+ * // returns true
+ */
+ assign( x: Collection | AccessorArrayLike, indices: IndexArray, mode: Mode, out: Collection, stride: number, offset: number ): Collection;
+}
+
+/**
+* Takes elements from an array.
*
* @param x - input array
* @param indices - list of element indices
+* @param mode - index mode
* @returns output array
*
* @example
* var x = [ 1, 2, 3, 4 ];
*
-* var y = take( x, [ 1, 3 ] );
+* var y = take( x, [ 1, 3 ], 'throw' );
* // returns [ 2, 4 ]
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+* var out = [ 0, 0, 0, 0 ];
+*
+* var arr = take.assign( x, [ 1, 3 ], 'throw', out, 2, 0 );
+* // returns [ 2, 0, 4, 0 ]
+*
+* var bool = ( arr === out );
+* // returns true
*/
-declare function take( x: Collection, indices: Collection ): Array;
+declare var take: Take;
// EXPORTS //
diff --git a/base/take/docs/types/test.ts b/base/take/docs/types/test.ts
index f9a84493..5ff071ae 100644
--- a/base/take/docs/types/test.ts
+++ b/base/take/docs/types/test.ts
@@ -16,6 +16,8 @@
* limitations under the License.
*/
+import Complex128Array = require( './../../../../complex128' );
+import Complex64Array = require( './../../../../complex64' );
import take = require( './index' );
@@ -23,35 +25,156 @@ import take = require( './index' );
// The function returns an array...
{
- take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType number[]
- take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType any[]
- take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType number[]
- take( [ '1', '2', '3', '4' ], [ 1, 3 ] ); // $ExpectType string[]
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ], 'throw' ); // $ExpectType number[]
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ], 'normalize' ); // $ExpectType any[]
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ], 'clamp' ); // $ExpectType number[]
+ take( [ '1', '2', '3', '4' ], [ 1, 3 ], 'wrap' ); // $ExpectType string[]
}
// The compiler throws an error if the function is provided a first argument which is not an array-like object...
{
- take( 1, [ 1, 3 ] ); // $ExpectError
- take( true, [ 1, 3 ] ); // $ExpectError
- take( false, [ 1, 3 ] ); // $ExpectError
- take( null, [ 1, 3 ] ); // $ExpectError
- take( void 0, [ 1, 3 ] ); // $ExpectError
- take( {}, [ 1, 3 ] ); // $ExpectError
+ take( 1, [ 1, 3 ], 'throw' ); // $ExpectError
+ take( true, [ 1, 3 ], 'throw' ); // $ExpectError
+ take( false, [ 1, 3 ], 'throw' ); // $ExpectError
+ take( null, [ 1, 3 ], 'throw' ); // $ExpectError
+ take( void 0, [ 1, 3 ], 'throw' ); // $ExpectError
+ take( {}, [ 1, 3 ], 'throw' ); // $ExpectError
}
// The compiler throws an error if the function is provided a second argument which is not an array-like object containing numbers...
{
- take( [], 1 ); // $ExpectError
- take( [], true ); // $ExpectError
- take( [], false ); // $ExpectError
- take( [], null ); // $ExpectError
- take( [], void 0 ); // $ExpectError
- take( [], {} ); // $ExpectError
+ take( [], 1, 'throw' ); // $ExpectError
+ take( [], true, 'throw' ); // $ExpectError
+ take( [], false, 'throw' ); // $ExpectError
+ take( [], null, 'throw' ); // $ExpectError
+ take( [], void 0, 'throw' ); // $ExpectError
+ take( [], {}, 'throw' ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a third argument which is not a valid index mode...
+{
+ take( [], [ 1, 3 ], '1' ); // $ExpectError
+ take( [], [ 1, 3 ], 1 ); // $ExpectError
+ take( [], [ 1, 3 ], true ); // $ExpectError
+ take( [], [ 1, 3 ], false ); // $ExpectError
+ take( [], [ 1, 3 ], null ); // $ExpectError
+ take( [], [ 1, 3 ], void 0 ); // $ExpectError
+ take( [], [ 1, 3 ], {} ); // $ExpectError
+ take( [], [ 1, 3 ], [] ); // $ExpectError
+ take( [], [ 1, 3 ], ( x: number ): number => x ); // $ExpectError
}
// The compiler throws an error if the function is provided an unsupported number of arguments...
{
take(); // $ExpectError
take( [] ); // $ExpectError
- take( [], [], [] ); // $ExpectError
+ take( [], [] ); // $ExpectError
+ take( [], [], 'throw', {} ); // $ExpectError
+}
+
+// Attached to the main export is an `assign` method which returns a collection...
+{
+ const x = [ 1, 2, 3, 4 ];
+ const y = new Complex128Array( 4 );
+
+ take.assign( x, [ 1, 3 ], 'throw', [ 0, 0, 0, 0 ], 1, 0 ); // $ExpectType number[]
+ take.assign( x, [ 1, 3 ], 'throw', new Float64Array( 4 ), 1, 0 ); // $ExpectType Float64Array
+ take.assign( x, [ 1, 3 ], 'throw', new Float32Array( 4 ), 1, 0 ); // $ExpectType Float32Array
+ take.assign( x, [ 1, 3 ], 'throw', new Int32Array( 4 ), 1, 0 ); // $ExpectType Int32Array
+ take.assign( x, [ 1, 3 ], 'throw', new Int16Array( 4 ), 1, 0 ); // $ExpectType Int16Array
+ take.assign( x, [ 1, 3 ], 'throw', new Int8Array( 4 ), 1, 0 ); // $ExpectType Int8Array
+ take.assign( x, [ 1, 3 ], 'throw', new Uint32Array( 4 ), 1, 0 ); // $ExpectType Uint32Array
+ take.assign( x, [ 1, 3 ], 'throw', new Uint16Array( 4 ), 1, 0 ); // $ExpectType Uint16Array
+ take.assign( x, [ 1, 3 ], 'throw', new Uint8Array( 4 ), 1, 0 ); // $ExpectType Uint8Array
+ take.assign( x, [ 1, 3 ], 'throw', new Uint8ClampedArray( 4 ), 1, 0 ); // $ExpectType Uint8ClampedArray
+ take.assign( y, [ 1, 3 ], 'throw', new Complex128Array( 4 ), 1, 0 ); // $ExpectType Complex128Array
+ take.assign( y, [ 1, 3 ], 'throw', new Complex64Array( 4 ), 1, 0 ); // $ExpectType Complex64Array
+}
+
+// The compiler throws an error if the `assign` method is provided a first argument which is not an array-like object...
+{
+ const out = [ 0, 0, 0, 0 ];
+
+ take.assign( 1, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( true, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( false, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( null, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( void 0, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( {}, [ 1, 3 ], 'throw', out, 1, 0 ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided a second argument which is not an array-like object containing numbers...
+{
+ const out = [ 0, 0, 0, 0 ];
+
+ take.assign( [], 1, 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( [], true, 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( [], false, 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( [], null, 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( [], void 0, 'throw', out, 1, 0 ); // $ExpectError
+ take.assign( [], {}, 'throw', out, 1, 0 ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided a third argument which is not a valid index mode...
+{
+ const out = [ 0, 0, 0, 0 ];
+
+ take.assign( [], [ 1, 3 ], '1', out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 1, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], true, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], false, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], null, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], void 0, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], {}, out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], [], out, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], ( x: number ): number => x, out, 1, 0 ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided a fourth argument which is not an array-like object...
+{
+ take.assign( [], [ 1, 3 ], 'throw', 1, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', true, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', false, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', null, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', void 0, 1, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', {}, 1, 0 ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided a fifth argument which is not a number...
+{
+ const out = [ 0, 0, 0, 0 ];
+
+ take.assign( [], [ 1, 3 ], 'throw', out, '1', 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, true, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, false, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, null, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, void 0, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, {}, 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, [], 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, ( x: number ): number => x, 0 ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided a sixth argument which is not a number...
+{
+ const out = [ 0, 0, 0, 0 ];
+
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, '1' ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, true ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, false ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, null ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, void 0 ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, {} ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, [] ); // $ExpectError
+ take.assign( [], [ 1, 3 ], 'throw', out, 1, ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the `assign` method is provided an unsupported number of arguments...
+{
+ take.assign(); // $ExpectError
+ take.assign( [] ); // $ExpectError
+ take.assign( [], [] ); // $ExpectError
+ take.assign( [], [], 'throw' ); // $ExpectError
+ take.assign( [], [], 'throw', [] ); // $ExpectError
+ take.assign( [], [], 'throw', [], 1 ); // $ExpectError
+ take.assign( [], [], 'throw', [], 1, 0, {} ); // $ExpectError
}
diff --git a/base/take/examples/index.js b/base/take/examples/index.js
index 08d52623..bf4e5302 100644
--- a/base/take/examples/index.js
+++ b/base/take/examples/index.js
@@ -31,7 +31,7 @@ var N = discreteUniform( 5, 15 );
var indices = filledBy( N, discreteUniform.factory( 0, x.length-1 ) );
// Take a random sample of elements from `x`:
-var y = take( x, indices );
+var y = take( x, indices, 'throw' );
console.log( x );
console.log( indices );
diff --git a/base/take/lib/assign.js b/base/take/lib/assign.js
new file mode 100644
index 00000000..3163ee44
--- /dev/null
+++ b/base/take/lib/assign.js
@@ -0,0 +1,250 @@
+/**
+* @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 arraylike2object = require( './../../../base/arraylike2object' );
+var reinterpret = require( '@stdlib/strided/base/reinterpret-complex' );
+var ind = require( '@stdlib/ndarray/base/ind' ).factory;
+
+
+// FUNCTIONS //
+
+/**
+* Takes elements from an indexed array and assigns the values to elements in an indexed output array.
+*
+* @private
+* @param {Collection} x - input array
+* @param {IntegerArray} indices - list of indices
+* @param {string} mode - index mode
+* @param {Collection} out - output array
+* @param {integer} stride - output array stride
+* @param {NonNegativeInteger} offset - output array offset
+* @returns {Collection} output array
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+* var indices = [ 3, 1, 2, 0 ];
+*
+* var out = [ 0, 0, 0, 0 ];
+*
+* var arr = indexed( x, indices, 'throw', out, 1, 0 );
+* // returns [ 4, 2, 3, 1 ]
+*/
+function indexed( x, indices, mode, out, stride, offset ) {
+ var getIndex;
+ var max;
+ var io;
+ var i;
+ var j;
+
+ // Resolve a function for returning an index according to the specified index mode:
+ getIndex = ind( mode );
+
+ // Resolve the maximum index:
+ max = x.length - 1;
+
+ // Extract each desired element from the provided array...
+ io = offset;
+ for ( i = 0; i < indices.length; i++ ) {
+ j = getIndex( indices[ i ], max );
+ out[ io ] = x[ j ];
+ io += stride;
+ }
+ return out;
+}
+
+/**
+* Takes elements from an accessor array and assigns the values to elements in an accessor output array.
+*
+* @private
+* @param {Object} x - input array object
+* @param {IntegerArray} indices - index array object
+* @param {string} mode - index mode
+* @param {Object} out - output array object
+* @param {integer} stride - output array stride
+* @param {NonNegativeInteger} offset - output array offset
+* @returns {Collection} output 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 indices = toAccessorArray( [ 3, 1, 2, 0 ] );
+*
+* var out = toAccessorArray( [ 0, 0, 0, 0 ] );
+* var arr = accessors( arraylike2object( x ), arraylike2object( indices ), 'throw', arraylike2object( out ), 1, 0 );
+*
+* var v = arr.get( 0 );
+* // returns 4
+*/
+function accessors( x, indices, mode, out, stride, offset ) {
+ var getIndex;
+ var xdata;
+ var idata;
+ var odata;
+ var xget;
+ var iget;
+ var oset;
+ var max;
+ var io;
+ var i;
+ var j;
+
+ xdata = x.data;
+ idata = indices.data;
+ odata = out.data;
+
+ xget = x.accessors[ 0 ];
+ iget = indices.accessors[ 0 ];
+ oset = out.accessors[ 1 ];
+
+ // Resolve a function for returning an index according to the specified index mode:
+ getIndex = ind( mode );
+
+ // Resolve the maximum index:
+ max = xdata.length - 1;
+
+ // Extract each desired element from the provided array...
+ io = offset;
+ for ( i = 0; i < idata.length; i++ ) {
+ j = getIndex( iget( idata, i ), max );
+ oset( odata, io, xget( xdata, j ) );
+ io += stride;
+ }
+ return odata;
+}
+
+/**
+* Takes elements from a complex array and assigns the values to elements in a complex output array.
+*
+* @private
+* @param {Collection} x - real-valued floating-point input array view
+* @param {Object} indices - index array object
+* @param {string} mode - index mode
+* @param {Collection} out - real-valued floating-point output array view
+* @param {integer} stride - output array stride
+* @param {NonNegativeInteger} offset - output array offset
+* @returns {Collection} output 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 ] );
+* var indices = [ 0, 0, 1, 1 ];
+*
+* var out = new Float64Array( 8 );
+*
+* var arr = complex( x, arraylike2object( indices ), 'throw', out, 1, 0 );
+* // returns [ 1.0, 2.0, 1.0, 2.0, 3.0, 4.0, 3.0, 4.0 ]
+*/
+function complex( x, indices, mode, out, stride, offset ) {
+ var getIndex;
+ var idata;
+ var iget;
+ var max;
+ var io;
+ var so;
+ var i;
+ var j;
+ var k;
+
+ idata = indices.data;
+ iget = indices.accessors[ 0 ];
+
+ // Resolve a function for returning an index according to the specified index mode:
+ getIndex = ind( mode );
+
+ // Resolve the maximum index:
+ max = ( x.length/2 ) - 1; // resolve the length of the original complex array
+
+ // Extract each desired element from the provided array...
+ so = stride * 2; // note: multiply by 2, as real-valued array consists of interleaved real and imaginary components
+ io = offset * 2;
+ for ( i = 0; i < idata.length; i++ ) {
+ j = getIndex( iget( idata, i ), max );
+ k = j * 2;
+ out[ io ] = x[ k ];
+ out[ io+1 ] = x[ k+1 ];
+ io += so;
+ }
+ return out;
+}
+
+
+// MAIN //
+
+/**
+* Takes elements from an array and assigns the values to elements in a provided output array.
+*
+* @param {Collection} x - input array
+* @param {IntegerArray} indices - list of indices
+* @param {string} mode - index mode
+* @param {Collection} out - output array
+* @param {integer} stride - output array stride
+* @param {NonNegativeInteger} offset - output array offset
+* @returns {Collection} output array
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+* var indices = [ 3, 1, 2, 0 ];
+*
+* var out = [ 0, 0, 0, 0 ];
+* var arr = assign( x, indices, 'throw', out, 1, 0 );
+* // returns [ 4, 2, 3, 1 ]
+*
+* var bool = ( arr === out );
+* // returns true
+*/
+function assign( x, indices, mode, out, stride, offset ) {
+ var xo;
+ var io;
+ var oo;
+
+ xo = arraylike2object( x );
+ io = arraylike2object( indices );
+ oo = arraylike2object( out );
+ if (
+ xo.accessorProtocol ||
+ io.accessorProtocol ||
+ oo.accessorProtocol
+ ) {
+ // Note: we only explicitly support complex-to-complex, as this function should not be concerned with casting rules, etc. That is left to userland...
+ if (
+ isComplexDataType( xo.dtype ) &&
+ isComplexDataType( oo.dtype )
+ ) {
+ complex( reinterpret( x, 0 ), io, mode, reinterpret( out, 0 ), stride, offset ); // eslint-disable-line max-len
+ return out;
+ }
+ accessors( xo, io, mode, oo, stride, offset );
+ return out;
+ }
+ indexed( x, indices, mode, out, stride, offset );
+ return out;
+}
+
+
+// EXPORTS //
+
+module.exports = assign;
diff --git a/base/take/lib/index.js b/base/take/lib/index.js
index 2ba2c826..6709f4b7 100644
--- a/base/take/lib/index.js
+++ b/base/take/lib/index.js
@@ -29,13 +29,34 @@
* var x = [ 1, 2, 3, 4 ];
*
* var indices = [ 0, 0, 1, 1, 3, 3 ];
-* var y = take( x, indices );
+* var y = take( x, indices, 'throw' );
* // returns [ 1, 1, 2, 2, 4, 4 ]
+*
+* @example
+* var take = require( '@stdlib/array/base/take' );
+*
+* var x = [ 1, 2, 3, 4 ];
+*
+* var out = [ 0, 0, 0, 0, 0, 0 ];
+* var indices = [ 0, 0, 1, 1, 3, 3 ];
+*
+* var arr = take.assign( x, indices, 'throw', out, 1, 0 );
+* // returns [ 1, 1, 2, 2, 4, 4 ]
+*
+* var bool = ( arr === out );
+* // returns true
*/
// MODULES //
+var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
var main = require( './main.js' );
+var assign = require( './assign.js' );
+
+
+// MAIN //
+
+setReadOnly( main, 'assign', assign );
// EXPORTS //
diff --git a/base/take/lib/main.js b/base/take/lib/main.js
index 1d442727..33d0762a 100644
--- a/base/take/lib/main.js
+++ b/base/take/lib/main.js
@@ -21,6 +21,7 @@
// MODULES //
var resolveGetter = require( './../../../base/resolve-getter' );
+var ind = require( '@stdlib/ndarray/base/ind' ).factory;
// MAIN //
@@ -29,28 +30,41 @@ var resolveGetter = require( './../../../base/resolve-getter' );
* Takes elements from an array.
*
* @param {Collection} x - input array
-* @param {NonNegativeIntegerArray} indices - list of indices
+* @param {IntegerArray} indices - list of indices
+* @param {string} mode - index mode
* @returns {Array} output array
*
* @example
* var x = [ 1, 2, 3, 4 ];
* var indices = [ 3, 1, 2, 0 ];
*
-* var y = take( x, indices );
+* var y = take( x, indices, 'throw' );
* // returns [ 4, 2, 3, 1 ]
*/
-function take( x, indices ) {
- var get;
+function take( x, indices, mode ) {
+ var getIndex;
+ var xget;
+ var iget;
var out;
+ var max;
var i;
+ var j;
- // Resolve an accessor for retrieving input array elements:
- get = resolveGetter( x );
+ // Resolve an accessor for retrieving array elements:
+ xget = resolveGetter( x );
+ iget = resolveGetter( indices );
+
+ // Resolve a function for returning an index according to the specified index mode:
+ getIndex = ind( mode );
+
+ // Resolve the maximum index:
+ max = x.length - 1;
// Extract each desired element from the provided array...
out = [];
for ( i = 0; i < indices.length; i++ ) {
- out.push( get( x, indices[ i ] ) ); // use `Array#push` to ensure "fast" elements
+ j = getIndex( iget( indices, i ), max );
+ out.push( xget( x, j ) ); // use `Array#push` to ensure "fast" elements
}
return out;
}
diff --git a/base/take/test/test.assign.js b/base/take/test/test.assign.js
new file mode 100644
index 00000000..dca85fbb
--- /dev/null
+++ b/base/take/test/test.assign.js
@@ -0,0 +1,607 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2022 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 Complex128Array = require( './../../../complex128' );
+var Complex64Array = require( './../../../complex64' );
+var Float64Array = require( './../../../float64' );
+var toAccessorArray = require( './../../../base/to-accessor-array' );
+var isSameComplex128Array = require( '@stdlib/assert/is-same-complex128array' );
+var isSameComplex64Array = require( '@stdlib/assert/is-same-complex64array' );
+var zeros = require( './../../../zeros' );
+var take = require( './../lib/assign.js' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof take, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function takes elements from an array (generic)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ 1, 3 ];
+ out = zeros( indices.length, 'generic' );
+ actual = take( x, indices, 'throw', out, 1, 0 );
+ expected = [ 2, 4 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 3, 3 ];
+ out = zeros( indices.length*2, 'generic' );
+ actual = take( x, indices, 'throw', out, 2, 0 );
+ expected = [ 2, 0, 2, 0, 4, 0, 4, 0 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 3, 2, 1, 0 ];
+ out = zeros( indices.length, 'generic' );
+ actual = take( x, indices, 'throw', out, -1, out.length-1 );
+ expected = [ 1, 2, 3, 4 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ];
+ out = zeros( indices.length+1, 'generic' );
+ actual = take( x, indices, 'throw', out, 1, 1 );
+ expected = [ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function takes elements from an array (real typed array)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+
+ indices = [ 1, 3 ];
+ out = zeros( indices.length, 'float64' );
+ actual = take( x, indices, 'throw', out, 1, 0 );
+ expected = new Float64Array( [ 2.0, 4.0 ] );
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 3, 3 ];
+ out = zeros( indices.length*2, 'float64' );
+ actual = take( x, indices, 'throw', out, 2, 0 );
+ expected = new Float64Array( [ 2.0, 0.0, 2.0, 0.0, 4.0, 0.0, 4.0, 0.0 ] );
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 3, 2, 1, 0 ];
+ out = zeros( indices.length, 'float64' );
+ actual = take( x, indices, 'throw', out, -1, out.length-1 );
+ expected = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ];
+ out = zeros( indices.length+1, 'float64' );
+ actual = take( x, indices, 'throw', out, 1, 1 );
+ expected = new Float64Array( [ 0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0 ] ); // eslint-disable-line max-len
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function takes elements from an array (complex typed array)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+
+ indices = [ 1, 3 ];
+ out = zeros( indices.length, 'complex128' );
+ actual = take( x, indices, 'throw', out, 1, 0 );
+ expected = new Complex128Array( [ 3.0, 4.0, 7.0, 8.0 ] );
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ indices = [ 1, 1, 3, 3 ];
+ out = zeros( indices.length*2, 'complex64' );
+ actual = take( x, indices, 'throw', out, 2, 0 );
+ expected = new Complex64Array( [ 3.0, 4.0, 0.0, 0.0, 3.0, 4.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0, 7.0, 8.0, 0.0, 0.0 ] ); // eslint-disable-line max-len
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
+ x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+
+ indices = [ 3, 2, 1, 0 ];
+ out = zeros( indices.length, 'complex128' );
+ actual = take( x, indices, 'throw', out, -1, out.length-1 );
+ expected = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); // eslint-disable-line max-len
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ indices = [ 1, 1, 1, 1 ];
+ out = zeros( indices.length+1, 'complex64' );
+ actual = take( x, indices, 'throw', out, 1, 1 );
+ expected = new Complex64Array( [ 0.0, 0.0, 3.0, 4.0, 3.0, 4.0, 3.0, 4.0, 3.0, 4.0 ] ); // eslint-disable-line max-len
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function takes elements from an array (accessors)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+
+ indices = toAccessorArray( [ 1, 3 ] );
+ out = toAccessorArray( zeros( indices.length, 'generic' ) );
+ actual = take( x, indices, 'throw', out, 1, 0 );
+ expected = [ 2, 4 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ isEqual( actual, expected );
+
+ indices = toAccessorArray( [ 1, 1, 3, 3 ] );
+ out = toAccessorArray( zeros( indices.length*2, 'generic' ) );
+ actual = take( x, indices, 'throw', out, 2, 0 );
+ expected = [ 2, 0, 2, 0, 4, 0, 4, 0 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ isEqual( actual, expected );
+
+ indices = toAccessorArray( [ 3, 2, 1, 0 ] );
+ out = toAccessorArray( zeros( indices.length, 'generic' ) );
+ actual = take( x, indices, 'throw', out, -1, out.length-1 );
+ expected = [ 1, 2, 3, 4 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ isEqual( actual, expected );
+
+ indices = toAccessorArray( [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] );
+ out = toAccessorArray( zeros( indices.length+1, 'generic' ) );
+ actual = take( x, indices, 'throw', out, 1, 1 );
+ expected = [ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ];
+
+ t.strictEqual( actual, out, 'returns expected value' );
+ isEqual( actual, expected );
+
+ t.end();
+
+ function isEqual( actual, expected ) {
+ var i;
+ for ( i = 0; i < expected.length; i++ ) {
+ t.strictEqual( actual.get( i ), expected[ i ], 'returns expected value' );
+ }
+ }
+});
+
+tape( 'the function returns leaves an output array unchanged if provided a second argument which is empty', function test( t ) {
+ var expected;
+ var actual;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ out = [ 0, 0, 0, 0 ];
+ expected = [ 0, 0, 0, 0 ];
+ actual = take( x, [], 'throw', out, 1, 0 );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ out = [ 0, 0, 0, 0 ];
+ expected = [ 0, 0, 0, 0 ];
+ actual = take( x, [], 'throw', out, 1, 0 );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ out = [ 0, 0, 0, 0 ];
+ expected = [ 0, 0, 0, 0 ];
+ actual = take( x, [], 'throw', out, 1, 0 );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ out = new Complex128Array( [ 0.0, 0.0, 0.0, 0.0 ] );
+ expected = new Complex128Array( [ 0.0, 0.0, 0.0, 0.0 ] );
+ actual = take( x, [], 'throw', out, 1, 0 );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index (generic)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'generic' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'throw', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index (accessors)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ indices = toAccessorArray( [ 4, 5, 1, 2 ] );
+ out = toAccessorArray( zeros( x.length, 'generic' ) );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'throw', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index (real typed)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'float64' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'throw', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index (complex typed)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'complex128' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'throw', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices (generic)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ -1, -2, -3, -4 ];
+ out = zeros( x.length, 'generic' );
+
+ actual = take( x, indices, 'normalize', out, 1, 0 );
+ expected = [ 4, 3, 2, 1 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices (accessors)', function test( t ) {
+ var expected;
+ var indices;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ indices = toAccessorArray( [ -1, -2, -3, -4 ] );
+ out = zeros( x.length, 'generic' );
+
+ take( x, indices, 'normalize', toAccessorArray( out ), 1, 0 );
+ expected = [ 4, 3, 2, 1 ];
+ t.deepEqual( out, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices (real typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ -1, -2, -3, -4 ];
+ out = zeros( x.length, 'float64' );
+
+ actual = take( x, indices, 'normalize', out, 1, 0 );
+ expected = new Float64Array( [ 4.0, 3.0, 2.0, 1.0 ] );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices (complex typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ -1, -2 ];
+ out = zeros( x.length, 'complex128' );
+
+ actual = take( x, indices, 'normalize', out, 1, 0 );
+ expected = new Complex128Array( [ 3.0, 4.0, 1.0, 2.0 ] );
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index (generic)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'generic' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'normalize', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index (accessors)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ indices = toAccessorArray( [ 4, 5, 1, 2 ] );
+ out = toAccessorArray( zeros( x.length, 'generic' ) );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'normalize', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index (real typed)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'float64' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'normalize', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index (complex typed)', function test( t ) {
+ var indices;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ 4, 5, 1, 2 ];
+ out = zeros( x.length, 'complex128' );
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'normalize', out, 1, 0 );
+ }
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices (generic)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'generic' );
+
+ actual = take( x, indices, 'clamp', out, 1, 0 );
+ expected = [ 1, 4, 1, 4 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices (accessors)', function test( t ) {
+ var expected;
+ var indices;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ indices = toAccessorArray( [ -10, 10, -5, 5 ] );
+ out = zeros( x.length, 'generic' );
+
+ take( x, indices, 'clamp', toAccessorArray( out ), 1, 0 );
+ expected = [ 1, 4, 1, 4 ];
+ t.deepEqual( out, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices (real typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'float64' );
+
+ actual = take( x, indices, 'clamp', out, 1, 0 );
+ expected = new Float64Array( [ 1.0, 4.0, 1.0, 4.0 ] );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices (complex typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'complex128' );
+
+ actual = take( x, indices, 'clamp', out, 1, 0 );
+ expected = new Complex128Array( [ 1.0, 2.0, 7.0, 8.0, 1.0, 2.0, 7.0, 8.0 ] ); // eslint-disable-line max-len
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices (generic)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'generic' );
+
+ actual = take( x, indices, 'wrap', out, 1, 0 );
+ expected = [ 3, 3, 4, 2 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices (accessors)', function test( t ) {
+ var expected;
+ var indices;
+ var out;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ indices = toAccessorArray( [ -10, 10, -5, 5 ] );
+ out = zeros( x.length, 'generic' );
+
+ take( x, indices, 'wrap', toAccessorArray( out ), 1, 0 );
+ expected = [ 3, 3, 4, 2 ];
+ t.deepEqual( out, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices (real typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'float64' );
+
+ actual = take( x, indices, 'wrap', out, 1, 0 );
+ expected = new Float64Array( [ 3.0, 3.0, 4.0, 2.0 ] );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices (complex typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var out;
+ var x;
+
+ x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+ indices = [ -10, 10, -5, 5 ];
+ out = zeros( x.length, 'complex128' );
+
+ actual = take( x, indices, 'wrap', out, 1, 0 );
+ expected = new Complex128Array( [ 5.0, 6.0, 5.0, 6.0, 7.0, 8.0, 3.0, 4.0 ] ); // eslint-disable-line max-len
+ t.strictEqual( isSameComplex128Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
diff --git a/base/take/test/test.js b/base/take/test/test.js
index 13a65fcc..47d782ac 100644
--- a/base/take/test/test.js
+++ b/base/take/test/test.js
@@ -22,6 +22,7 @@
var tape = require( 'tape' );
var Complex64Array = require( './../../../complex64' );
+var toAccessorArray = require( './../../../base/to-accessor-array' );
var realf = require( '@stdlib/complex/realf' );
var imagf = require( '@stdlib/complex/imagf' );
var isComplex64 = require( '@stdlib/assert/is-complex64' );
@@ -45,22 +46,22 @@ tape( 'the function takes elements from an array', function test( t ) {
x = [ 1, 2, 3, 4 ];
indices = [ 1, 3 ];
- actual = take( x, indices );
+ actual = take( x, indices, 'throw' );
expected = [ 2, 4 ];
t.deepEqual( actual, expected, 'returns expected value' );
indices = [ 1, 1, 3, 3 ];
- actual = take( x, indices );
+ actual = take( x, indices, 'throw' );
expected = [ 2, 2, 4, 4 ];
t.deepEqual( actual, expected, 'returns expected value' );
indices = [ 3, 2, 1, 0 ];
- actual = take( x, indices );
+ actual = take( x, indices, 'throw' );
expected = [ 4, 3, 2, 1 ];
t.deepEqual( actual, expected, 'returns expected value' );
indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ];
- actual = take( x, indices );
+ actual = take( x, indices, 'throw' );
expected = [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ];
t.deepEqual( actual, expected, 'returns expected value' );
@@ -76,13 +77,13 @@ tape( 'the function takes elements from an array (accessors)', function test( t
var i;
x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
- indices = [ 1, 1, 3, 3 ];
- actual = take( x, indices );
+ indices = toAccessorArray( [ 1, 1, 3, 3 ] );
+ actual = take( x, indices, 'throw' );
t.notEqual( actual, x, 'returns different reference' );
for ( i = 0; i < indices.length; i++ ) {
v = actual[ i ];
- expected = x.get( indices[ i ] );
+ expected = x.get( indices.get( i ) );
t.strictEqual( isComplex64( v ), true, 'returns expected value' );
t.strictEqual( realf( v ), realf( expected ), 'returns expected value' );
t.strictEqual( imagf( v ), imagf( expected ), 'returns expected value' );
@@ -90,7 +91,28 @@ tape( 'the function takes elements from an array (accessors)', function test( t
t.end();
});
-tape( 'the function does not perform bounds checking', function test( t ) {
+tape( 'the function returns an empty array if provided a second argument which is empty', function test( t ) {
+ var x = [ 1, 2, 3, 4 ];
+ t.deepEqual( take( x, [], 'throw' ), [], 'returns expected value' );
+ t.end();
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index', function test( t ) {
+ var indices;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 4, 5, 1, 2 ];
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'throw' );
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices', function test( t ) {
var expected;
var indices;
var actual;
@@ -98,16 +120,57 @@ tape( 'the function does not perform bounds checking', function test( t ) {
x = [ 1, 2, 3, 4 ];
- indices = [ 4, 5, 1, 2 ];
- actual = take( x, indices );
- expected = [ void 0, void 0, 2, 3 ];
+ indices = [ -1, -2, -3, -4 ];
+ actual = take( x, indices, 'normalize' );
+ expected = [ 4, 3, 2, 1 ];
t.deepEqual( actual, expected, 'returns expected value' );
t.end();
});
-tape( 'the function returns an empty array if provided a second argument which is empty', function test( t ) {
- var x = [ 1, 2, 3, 4 ];
- t.deepEqual( take( x, [] ), [], 'returns expected value' );
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index', function test( t ) {
+ var indices;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 2, 50, 1, 2 ];
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, 'normalize' );
+ }
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -10, 10, -5, 5 ];
+ actual = take( x, indices, 'clamp' );
+ expected = [ 1, 4, 1, 4 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -10, 10, -5, 5 ];
+ actual = take( x, indices, 'wrap' );
+ expected = [ 3, 3, 4, 2 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
t.end();
});
diff --git a/base/zero-to/lib/assign.js b/base/zero-to/lib/assign.js
index f33e39c9..30b48f74 100644
--- a/base/zero-to/lib/assign.js
+++ b/base/zero-to/lib/assign.js
@@ -20,8 +20,6 @@
// MODULES //
-var isComplex128Array = require( './../../../base/assert/is-complex128array' );
-var isComplex64Array = require( './../../../base/assert/is-complex64array' );
var arraylike2object = require( './../../../base/arraylike2object' );
var reinterpret128 = require( '@stdlib/strided/base/reinterpret-complex128' );
var reinterpret64 = require( '@stdlib/strided/base/reinterpret-complex64' );
@@ -181,10 +179,10 @@ function assign( out, stride, offset ) {
var obj = arraylike2object( out );
if ( obj.accessorProtocol ) {
// If provided a complex number array, reinterpret as a real typed array and only set the real components...
- if ( isComplex128Array( out ) ) {
+ if ( obj.dtype === 'complex128' ) {
return complex( out, reinterpret128( out, 0 ), stride, offset );
}
- if ( isComplex64Array( out ) ) {
+ if ( obj.dtype === 'complex64' ) {
return complex( out, reinterpret64( out, 0 ), stride, offset );
}
return accessors( obj, stride, offset );
diff --git a/index/README.md b/index/README.md
new file mode 100644
index 00000000..7eaaafa1
--- /dev/null
+++ b/index/README.md
@@ -0,0 +1,471 @@
+
+
+# ArrayIndex
+
+> Array index constructor.
+
+
+
+
+
+In JavaScript, only strings and symbols are valid property names. When providing values for property names which are not string or symbols, the values are serialized to strings **prior to** attempting to access property values. For example, the following
+
+```javascript
+// Create an array:
+var x = [ 1, 2, 3, 4 ];
+
+// Define a list of indices for elements we want to retrieve from `x`:
+var y = [ 0, 2 ];
+
+// Attempt to retrieve the desired elements:
+var v = x[ y ]; // => desired: [ 1, 3 ]
+// returns undefined
+```
+
+is equivalent to
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+var y = [ 0, 2 ];
+
+var v = x[ y.toString() ];
+// returns undefined
+
+// ...which is equivalent to:
+v = x[ '0,2' ];
+// returns undefined
+```
+
+Accordingly, in order to circumvent built-in property access behavior and support non-traditional access patterns, one can leverage [`Proxy`][@stdlib/proxy/ctor] objects which allow one to intercept property access and to perform transformations before attempting to access elements in a target object.
+
+To support the access pattern shown in the example above, one can leverage built-in string serialization behavior to reconstruct the original property value provided prior to serialization. The `ArrayIndex` constructor described below provides one such mechanism.
+
+Specifically, instantiated `ArrayIndex` objects are assigned a unique identifier and stored in a local cache. When provided as property values to `ArrayIndex` consumers, instantiated objects serialize to a string containing their unique identifier. `ArrayIndex` consumers can then parse the serialized string to obtain the unique identifier and subsequently recover the original array from the local cache.
+
+
+
+
+
+
+
+
+
+## Usage
+
+```javascript
+var ArrayIndex = require( '@stdlib/array/index' );
+```
+
+
+
+#### ArrayIndex( x\[, options] )
+
+Wraps a provided array as an array index object.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var idx = new ArrayIndex( x );
+// returns
+```
+
+The constructor accepts the following arguments:
+
+- **x**: input array.
+- **options**: function options.
+
+The constructor accepts the following options:
+
+- **persist**: boolean indicating whether to continue persisting an index object after first usage. Default: `false`.
+
+By default, an `ArrayIndex` is invalidated and removed from an internal cache immediately after a consumer resolves the underlying data associated with an `ArrayIndex` instance using the [`ArrayIndex.get()`](#static-method-get) static method. Immediate invalidation and cache removal ensures that references to the underlying array are not the source of memory leaks.
+
+One may, however, want to reuse an `ArrayIndex` instance to avoid additional memory allocation. In order to persist an `ArrayIndex` and prevent automatic cache invalidation, set the `persist` option to `true`.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var idx = new ArrayIndex( x, {
+ 'persist': true
+});
+// returns
+
+// ...
+
+var o = ArrayIndex.get( idx.id );
+// returns {...}
+
+// ...
+
+o = ArrayIndex.get( idx.id );
+// returns {...}
+
+// ...
+
+// Explicitly free the array index:
+ArrayIndex.free( idx.id );
+```
+
+In order to **prevent** memory leaks when working with persisted `ArrayIndex` instances, one **must** remember to manually free persisted instances using the [`ArrayIndex.free()`](#static-method-free) method.
+
+* * *
+
+### Properties
+
+
+
+#### ArrayIndex.name
+
+String value of the `ArrayIndex` constructor name.
+
+```javascript
+var str = ArrayIndex.name;
+// returns 'ArrayIndex'
+```
+
+
+
+#### ArrayIndex.prototype.data
+
+**Read-only** property returning the underlying array associated with an `ArrayIndex` instance.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var v = idx.data;
+// returns [ 1, 0, 1, 0 ]
+```
+
+
+
+#### ArrayIndex.prototype.dtype
+
+**Read-only** property returning the data type of the underlying array associated with an `ArrayIndex` instance.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var dt = idx.dtype;
+// returns 'uint8'
+```
+
+
+
+#### ArrayIndex.prototype.id
+
+**Read-only** property returning the unique identifier associated with an `ArrayIndex` instance.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var id = idx.id;
+// returns
+```
+
+The identifier should be used by `ArrayIndex` consumers to resolve the underlying data associated with an `ArrayIndex` instance.
+
+
+
+#### ArrayIndex.prototype.isCached
+
+**Read-only** property returning a boolean indicating whether an `ArrayIndex` instance is actively cached.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var out = idx.isCached;
+// returns true
+```
+
+
+
+#### ArrayIndex.prototype.type
+
+**Read-only** property returning the array index type.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var t = idx.type;
+// returns 'mask'
+```
+
+The following array index types are supported:
+
+- **mask**: mask array, in which a value of zero indicates to include a respective element and a value of one indicates to exclude a respective element. A mask array is the complement of a boolean array.
+- **bool**: boolean array, in which a value of `true` indicates to include a respective element and a value of `false` indicates to exclude a respective element. A boolean array is the complement of a mask array.
+- **int**: integer array, in which each element is an index indicating the position of an element to include. Elements are **not** required to be unique (i.e., more than element may resolve to the same position).
+
+* * *
+
+### Methods
+
+
+
+#### ArrayIndex.free( id )
+
+Frees the `ArrayIndex` associated with a provided identifier.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+ 'persist': true
+});
+// returns
+
+// ...
+
+var out = ArrayIndex.free( idx.id );
+// returns true
+```
+
+Once an `ArrayIndex` is freed, the instance is invalid and can no longer be used. Any subsequent `ArrayIndex` operations (i.e., property and method access) will raise an exception.
+
+
+
+#### ArrayIndex.get( id )
+
+Returns the array associated with the `ArrayIndex` having a provided identifier.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+ 'persist': true
+});
+// returns
+
+// ...
+
+var o = ArrayIndex.get( idx.id );
+// returns {...}
+
+var d = o.data;
+// returns [ 1, 0, 1, 0 ]
+
+var t = o.type;
+// returns 'mask'
+
+var dt = o.dtype;
+// returns 'uint8'
+```
+
+The returned object has the following properties:
+
+- **data**: the underlying array associated with the `ArrayIndex` identified by the provided `id`.
+- **type**: the type of array index. One of the following: `'int'`, `'bool'`, or `'mask'`.
+- **dtype**: the data type of the underlying array.
+
+If the `ArrayIndex` associated with a provided identifier was not explicitly persisted, calling this method will cause the `ArrayIndex` to be invalidated and removed from an internal cache. Any subsequent instance operations (i.e., property and method access) will raise an exception.
+
+
+
+#### ArrayIndex.prototype.toString()
+
+Serializes an `ArrayIndex` as a string.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var str = idx.toString();
+// e.g., 'ArrayIndex<0>'
+```
+
+An `ArrayIndex` is intended to be an opaque object used by objects supporting "fancy" indexing (e.g., [fancy arrays][@stdlib/array/to-fancy]). As such, when serialized as a string, a serialized `ArrayIndex` includes only the unique identifier associated with the respective instance.
+
+
+
+#### ArrayIndex.prototype.toJSON()
+
+Serializes an `ArrayIndex` as a [JSON][json] object.
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+
+var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+// returns
+
+var o = idx.toJSON();
+// returns { 'type': 'ArrayIndex', 'data': { 'type': 'Uint8Array', 'data': [ 1, 0, 1, 0 ] } }
+```
+
+`JSON.stringify()` implicitly calls this method when stringifying an `ArrayIndex` instance.
+
+
+
+
+
+
+
+* * *
+
+
+
+## Notes
+
+- `ArrayIndex` instances have no explicit functionality; however, they are used by ["fancy" arrays][@stdlib/array/to-fancy] and other packages for element retrieval and assignment.
+
+- Because `ArrayIndex` instances leverage an internal cache implementing the **Singleton pattern**, one **must** be sure to use the same `ArrayIndex` constructor as `ArrayIndex` consumers. If one uses a different `ArrayIndex` constructor, the consumer will **not** be able to resolve the original wrapped array, as the consumer will attempt to resolve an `ArrayIndex` instance in the wrong internal cache.
+
+- Because non-persisted `ArrayIndex` instances are freed after first use, in order to avoid holding onto memory and to allow garbage collection, one should avoid scenarios in which an `ArrayIndex` is never used. For example,
+
+ ```javascript
+ var Uint8Array = require( '@stdlib/array/uint8' );
+
+ var data = new Uint8Array( [ 1, 0, 0, 0 ] );
+ var idx = new ArrayIndex( data );
+
+ var o;
+ if ( data[ 0 ] === 0 ) {
+ // Do something with `idx`...
+ o = ArrayIndex.get( idx.id );
+
+ // ...
+ }
+ ```
+
+ will leak memory as `idx` is only consumed within an `if` block which never evaluates. In such scenarios, one should either refactor to avoid inadvertently holding onto memory or explicitly free the `ArrayIndex`.
+
+ ```javascript
+ var Uint8Array = require( '@stdlib/array/uint8' );
+
+ var data = new Uint8Array( [ 1, 0, 0, 0 ] );
+ var idx = new ArrayIndex( data );
+
+ var o;
+ if ( data[ 0 ] === 0 ) {
+ // Do something with `idx`...
+ o = ArrayIndex.get( idx.id );
+
+ // ...
+ } else {
+ ArrayIndex.free( idx.id );
+ }
+ ```
+
+
+
+
+
+
+
+* * *
+
+
+
+## Examples
+
+
+
+```javascript
+var Uint8Array = require( '@stdlib/array/uint8' );
+var Int32Array = require( '@stdlib/array/int32' );
+var ArrayIndex = require( '@stdlib/array/index' );
+
+var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+var i = new ArrayIndex( x );
+// returns
+
+var o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = [ true, false, true, false ];
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = new Int32Array( [ 1, 3, 4, 7 ] );
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = [ 1, 3, 4, 7 ];
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[json]: http://www.json.org/
+
+[@stdlib/array/to-fancy]: https://github.com/stdlib-js/array/tree/main/to-fancy
+
+[@stdlib/proxy/ctor]: https://github.com/stdlib-js/proxy-ctor
+
+
+
+
diff --git a/index/benchmark/benchmark.data.js b/index/benchmark/benchmark.data.js
new file mode 100644
index 00000000..b1ff8301
--- /dev/null
+++ b/index/benchmark/benchmark.data.js
@@ -0,0 +1,60 @@
+/**
+* @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 isCollection = require( '@stdlib/assert/is-collection' );
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':data', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].data;
+ if ( typeof v !== 'object' ) {
+ b.fail( 'should return an object' );
+ }
+ }
+ b.toc();
+ if ( !isCollection( v ) ) {
+ b.fail( 'should return a collection' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.dtype.js b/index/benchmark/benchmark.dtype.js
new file mode 100644
index 00000000..5a9eea9f
--- /dev/null
+++ b/index/benchmark/benchmark.dtype.js
@@ -0,0 +1,60 @@
+/**
+* @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 isString = require( '@stdlib/assert/is-string' ).isPrimitive;
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':dtype', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].dtype;
+ if ( typeof v !== 'string' ) {
+ b.fail( 'should return a string' );
+ }
+ }
+ b.toc();
+ if ( !isString( v ) ) {
+ b.fail( 'should return a string' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.get.js b/index/benchmark/benchmark.get.js
new file mode 100644
index 00000000..0bdb0bde
--- /dev/null
+++ b/index/benchmark/benchmark.get.js
@@ -0,0 +1,60 @@
+/**
+* @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 isPlainObject = require( '@stdlib/assert/is-plain-object' );
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':get', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ ( new ArrayIndex( [ 1, 2, 3 ], opts ) ).id,
+ ( new ArrayIndex( [ 5, 6, 7 ], opts ) ).id,
+ ( new ArrayIndex( [ true, false, true ], opts ) ).id
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = ArrayIndex.get( values[ i%values.length ] );
+ if ( typeof v !== 'object' ) {
+ b.fail( 'should return an object' );
+ }
+ }
+ b.toc();
+ if ( !isPlainObject( v ) ) {
+ b.fail( 'should return an object' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.id.js b/index/benchmark/benchmark.id.js
new file mode 100644
index 00000000..010e132e
--- /dev/null
+++ b/index/benchmark/benchmark.id.js
@@ -0,0 +1,60 @@
+/**
+* @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 isString = require( '@stdlib/assert/is-string' ).isPrimitive;
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':id', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].id;
+ if ( typeof v !== 'string' ) {
+ b.fail( 'should return a string' );
+ }
+ }
+ b.toc();
+ if ( !isString( v ) ) {
+ b.fail( 'should return a string' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.is_cached.js b/index/benchmark/benchmark.is_cached.js
new file mode 100644
index 00000000..c4bccf03
--- /dev/null
+++ b/index/benchmark/benchmark.is_cached.js
@@ -0,0 +1,60 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var bench = require( '@stdlib/bench' );
+var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':isCached', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].isCached;
+ if ( typeof v !== 'boolean' ) {
+ b.fail( 'should return a boolean' );
+ }
+ }
+ b.toc();
+ if ( !isBoolean( v ) ) {
+ b.fail( 'should return a boolean' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.js b/index/benchmark/benchmark.js
new file mode 100644
index 00000000..14c89bce
--- /dev/null
+++ b/index/benchmark/benchmark.js
@@ -0,0 +1,84 @@
+/**
+* @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 instanceOf = require( '@stdlib/assert/instance-of' );
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+'::instantiation,new', function benchmark( b ) {
+ var values;
+ var v;
+ var i;
+
+ values = [
+ [ 1, 2, 3 ],
+ [ 5, 6, 7 ],
+ [ true, false, true ]
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = new ArrayIndex( values[ i%values.length ] );
+ if ( typeof v !== 'object' ) {
+ b.fail( 'should return an object' );
+ }
+ }
+ b.toc();
+ if ( !instanceOf( v, ArrayIndex ) ) {
+ b.fail( 'should return an instance' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
+
+bench( pkg+'::instantiation,no_new', function benchmark( b ) {
+ var values;
+ var idx;
+ var v;
+ var i;
+
+ idx = ArrayIndex;
+
+ values = [
+ [ 1, 2, 3 ],
+ [ 5, 6, 7 ],
+ [ true, false, true ]
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = idx( values[ i%values.length ] );
+ if ( typeof v !== 'object' ) {
+ b.fail( 'should return an object' );
+ }
+ }
+ b.toc();
+ if ( !instanceOf( v, ArrayIndex ) ) {
+ b.fail( 'should return an instance' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.to_json.js b/index/benchmark/benchmark.to_json.js
new file mode 100644
index 00000000..3c99ab76
--- /dev/null
+++ b/index/benchmark/benchmark.to_json.js
@@ -0,0 +1,60 @@
+/**
+* @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 isPlainObject = require( '@stdlib/assert/is-plain-object' );
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':toJSON:len=3', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].toJSON();
+ if ( typeof v !== 'object' ) {
+ b.fail( 'should return an object' );
+ }
+ }
+ b.toc();
+ if ( !isPlainObject( v ) ) {
+ b.fail( 'should return an object' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.to_string.js b/index/benchmark/benchmark.to_string.js
new file mode 100644
index 00000000..e973acb3
--- /dev/null
+++ b/index/benchmark/benchmark.to_string.js
@@ -0,0 +1,60 @@
+/**
+* @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 isString = require( '@stdlib/assert/is-string' ).isPrimitive;
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':toString:len=3', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].toString();
+ if ( typeof v !== 'string' ) {
+ b.fail( 'should return a string' );
+ }
+ }
+ b.toc();
+ if ( !isString( v ) ) {
+ b.fail( 'should return a string' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/benchmark/benchmark.type.js b/index/benchmark/benchmark.type.js
new file mode 100644
index 00000000..fa3f11e4
--- /dev/null
+++ b/index/benchmark/benchmark.type.js
@@ -0,0 +1,60 @@
+/**
+* @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 isString = require( '@stdlib/assert/is-string' ).isPrimitive;
+var pkg = require( './../package.json' ).name;
+var ArrayIndex = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':type', function benchmark( b ) {
+ var values;
+ var opts;
+ var v;
+ var i;
+
+ opts = {
+ 'persist': true
+ };
+
+ values = [
+ new ArrayIndex( [ 1, 2, 3 ], opts ),
+ new ArrayIndex( [ 5, 6, 7 ], opts ),
+ new ArrayIndex( [ true, false, true ], opts )
+ ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = values[ i%values.length ].type;
+ if ( typeof v !== 'string' ) {
+ b.fail( 'should return a string' );
+ }
+ }
+ b.toc();
+ if ( !isString( v ) ) {
+ b.fail( 'should return a string' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/index/docs/repl.txt b/index/docs/repl.txt
new file mode 100644
index 00000000..d2e4cd7a
--- /dev/null
+++ b/index/docs/repl.txt
@@ -0,0 +1,202 @@
+
+{{alias}}( x[, options] )
+ Wraps a provided array as an array index object.
+
+ Array index instances have no explicit functionality; however, they are used
+ by "fancy" arrays for element retrieval and assignment.
+
+ By default, an instance is invalidated and removed from an internal cache
+ immediately after a consumer resolves the underlying data associated with an
+ instance using the `get` static method. Immediate invalidation and cache
+ removal ensures that references to the underlying array are not the source
+ of memory leaks.
+
+ Because instances leverage an internal cache implementing the Singleton
+ pattern, one must be sure to use the same constructor as consumers. If one
+ uses a different constructor, the consumer will *not* be able to resolve the
+ original wrapped array, as the consumer will attempt to resolve an instance
+ in the wrong internal cache.
+
+ Because non-persisted instances are freed after first use, in order to avoid
+ holding onto memory and to allow garbage collection, one should avoid
+ scenarios in which an instance is never used.
+
+ Parameters
+ ----------
+ x: Array|TypedArray|Object
+ Input array.
+
+ options: Object (optional)
+ Function options.
+
+ options.persist: boolean (optional)
+ Boolean indicating whether to continue persisting an index object after
+ first usage. Default: false.
+
+ Returns
+ -------
+ out: ArrayIndex
+ ArrayIndex instance.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+
+
+{{alias}}.free( id )
+ Frees the instance associated with a provided identifier.
+
+ Parameters
+ ----------
+ id: string
+ Instance identifier.
+
+ Returns
+ -------
+ out: boolean
+ Boolean indicating whether an instance was successfully freed.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > // ...
+ > {{alias}}.free( idx.id )
+
+
+{{alias}}.get( id )
+ Returns the array associated with the instance having a provided identifier.
+
+ Parameters
+ ----------
+ id: string
+ Instance identifier.
+
+ Returns
+ -------
+ out: Object
+ Object containing array data.
+
+ out.data: Array|TypedArray|Object
+ The underlying array associated with the provided identifier.
+
+ out.type: string
+ The type of array index.
+
+ out.dtype: string
+ The data type of the underlying array.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > {{alias}}.get( idx.id )
+ {...}
+
+
+{{alias}}.prototype.data
+ Read-only property returning the underlying index array.
+
+ Returns
+ -------
+ out: Array|TypedArray|Object
+ Array data type.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.data
+ [ 1, 2, 3, 4 ]
+
+
+{{alias}}.prototype.dtype
+ Read-only property returning the underlying data type of the index array.
+
+ Returns
+ -------
+ out: string
+ Array data type.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.dtype
+ 'generic'
+
+
+{{alias}}.prototype.id
+ Read-only property returning the unique identifier associated with an
+ instance.
+
+ Returns
+ -------
+ out: string
+ String identifier.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.id
+
+
+
+{{alias}}.prototype.isCached
+ Read-only property returning a boolean indicating whether an array index is
+ actively cached.
+
+ Returns
+ -------
+ out: boolean
+ Boolean indicating whether an array index is actively cached.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.isCached
+ true
+
+
+{{alias}}.prototype.type
+ Read-only property returning the array index type.
+
+ Returns
+ -------
+ out: string
+ Array index type.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.type
+
+
+
+{{alias}}.prototype.toString()
+ Serializes an instance as a string.
+
+ Returns
+ -------
+ str: string
+ Serialized string.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.toString()
+
+
+{{alias}}.prototype.toJSON()
+ Serializes an instance as a JSON object.
+
+ Returns
+ -------
+ obj: Object
+ JSON object.
+
+ Examples
+ --------
+ > var idx = new {{alias}}( [ 1, 2, 3, 4 ] );
+ > idx.toJSON()
+ { 'type': 'ArrayIndex', 'data': [ 1, 2, 3, 4 ] }
+
+ See Also
+ --------
+
diff --git a/index/docs/types/index.d.ts b/index/docs/types/index.d.ts
new file mode 100644
index 00000000..11fa91bb
--- /dev/null
+++ b/index/docs/types/index.d.ts
@@ -0,0 +1,539 @@
+/*
+* @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, DataType } from '@stdlib/types/array';
+
+/**
+* Boolean index array.
+*/
+type BooleanIndexArray = Collection | AccessorArrayLike;
+
+/**
+* Integer index array.
+*/
+type IntegerIndexArray = Collection | AccessorArrayLike;
+
+/**
+* Index array.
+*/
+type IndexArray = BooleanIndexArray | IntegerIndexArray;
+
+/**
+* Interface describing function options.
+*/
+interface Options {
+ /**
+ * Boolean indicating whether to continue persisting an index object after first usage (default: `false`).
+ */
+ persist?: boolean;
+}
+
+/**
+* Interface describing an object containing array index data.
+*/
+interface BaseArrayObject {
+ /**
+ * The underlying array associated with an array index.
+ */
+ data: IndexArray;
+
+ /**
+ * The type of array index.
+ */
+ type: 'int' | 'bool' | 'mask';
+
+ /**
+ * The data type of the underlying array.
+ */
+ dtype: DataType;
+}
+
+/**
+* Interface describing an object containing mask array data.
+*/
+interface MaskArrayObject extends BaseArrayObject {
+ /**
+ * The underlying array associated with an array index.
+ */
+ data: Uint8Array;
+
+ /**
+ * The type of array index.
+ */
+ type: 'mask';
+
+ /**
+ * The data type of the underlying array.
+ */
+ dtype: 'uint8';
+}
+
+/**
+* Interface describing an object containing integer array data.
+*/
+interface Int32ArrayObject extends BaseArrayObject {
+ /**
+ * The underlying array associated with an array index.
+ */
+ data: Int32Array;
+
+ /**
+ * The type of array index.
+ */
+ type: 'int';
+
+ /**
+ * The data type of the underlying array.
+ */
+ dtype: 'int32';
+}
+
+/**
+* Interface describing an object containing integer array data.
+*/
+interface IntegerArrayObject extends BaseArrayObject {
+ /**
+ * The underlying array associated with an array index.
+ */
+ data: IntegerIndexArray;
+
+ /**
+ * The type of array index.
+ */
+ type: 'int';
+
+ /**
+ * The data type of the underlying array.
+ */
+ dtype: 'generic';
+}
+
+/**
+* Interface describing an object containing boolean array data.
+*/
+interface BooleanArrayObject extends BaseArrayObject {
+ /**
+ * The underlying array associated with an array index.
+ */
+ data: BooleanIndexArray;
+
+ /**
+ * The type of array index.
+ */
+ type: 'bool';
+
+ /**
+ * The data type of the underlying array.
+ */
+ dtype: 'generic';
+}
+
+/**
+* Array object data.
+*/
+type ArrayObject = MaskArrayObject | Int32ArrayObject | BooleanArrayObject | IntegerArrayObject | null;
+
+/**
+* Interface describing an array index object.
+*/
+interface BaseArrayIndex {
+ /**
+ * Read-only property returning the data associated with an `ArrayIndex` instance.
+ */
+ data: IndexArray;
+
+ /**
+ * Read-only property returning the underlying array index data type.
+ */
+ dtype: DataType;
+
+ /**
+ * Read-only property returning the unique identifier associated with an `ArrayIndex` instance.
+ */
+ id: string;
+
+ /**
+ * Boolean indicating if an `ArrayIndex` instance is actively cached.
+ */
+ isCached: boolean;
+
+ /**
+ * Read-only property returning the array index type.
+ */
+ type: 'int' | 'bool' | 'mask';
+
+ /**
+ * Serializes an `ArrayIndex` to a string.
+ *
+ * @returns serialized string
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+ * // returns
+ *
+ * var str = idx.toString();
+ * // e.g., 'ArrayIndex<0>'
+ */
+ toString(): string;
+}
+
+/**
+* Interface describing a mask array index object.
+*/
+interface MaskArrayIndex extends BaseArrayIndex {
+ /**
+ * Read-only property returning the array index type.
+ */
+ type: 'mask';
+
+ /**
+ * Read-only property returning the underlying array index data type.
+ */
+ dtype: 'uint8';
+
+ /**
+ * Read-only property returning the underlying array data.
+ */
+ data: Uint8Array;
+}
+
+/**
+* Interface describing an integer array index object.
+*/
+interface Int32ArrayIndex extends BaseArrayIndex {
+ /**
+ * Read-only property returning the array index type.
+ */
+ type: 'int';
+
+ /**
+ * Read-only property returning the underlying array index data type.
+ */
+ dtype: 'int32';
+
+ /**
+ * Read-only property returning the underlying array data.
+ */
+ data: Int32Array;
+}
+
+/**
+* Interface describing a boolean array index object.
+*/
+interface BooleanArrayIndex extends BaseArrayIndex {
+ /**
+ * Read-only property returning the array index type.
+ */
+ type: 'bool';
+
+ /**
+ * Read-only property returning the underlying array index data type.
+ */
+ dtype: 'generic';
+
+ /**
+ * Read-only property returning the underlying array data.
+ */
+ data: BooleanIndexArray;
+}
+
+/**
+* Interface describing an integer array index object.
+*/
+interface IntegerArrayIndex extends BaseArrayIndex {
+ /**
+ * Read-only property returning the array index type.
+ */
+ type: 'int';
+
+ /**
+ * Read-only property returning the underlying array index data type.
+ */
+ dtype: 'generic';
+
+ /**
+ * Read-only property returning the underlying array data.
+ */
+ data: IntegerIndexArray;
+}
+
+/**
+* Array index object.
+*/
+type ArrayIndex = MaskArrayIndex | Int32ArrayIndex | BooleanArrayIndex | IntegerArrayIndex;
+
+/**
+* Interface defining an `ArrayIndex` constructor which is both "newable" and "callable".
+*/
+interface Constructor {
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = new ArrayIndex( x );
+ * // returns
+ */
+ new( x: Uint8Array, options?: Options ): MaskArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Int32Array = require( './../../../int32' );
+ *
+ * var x = new Int32Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = new ArrayIndex( x );
+ * // returns
+ */
+ new( x: Int32Array, options?: Options ): Int32ArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var idx = new ArrayIndex( x );
+ * // returns
+ */
+ new( x: IntegerIndexArray, options?: Options ): IntegerArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var x = [ true, false, true, false ];
+ *
+ * var idx = new ArrayIndex( x );
+ * // returns
+ */
+ new( x: BooleanIndexArray, options?: Options ): BooleanArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = new ArrayIndex( x );
+ * // returns
+ */
+ new( x: IndexArray, options?: Options ): ArrayIndex;
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = ArrayIndex( x );
+ * // returns
+ */
+ ( x: Uint8Array, options?: Options ): MaskArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Int32Array = require( './../../../int32' );
+ *
+ * var x = new Int32Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = ArrayIndex( x );
+ * // returns
+ */
+ ( x: Int32Array, options?: Options ): Int32ArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var idx = ArrayIndex( x );
+ * // returns
+ */
+ ( x: IntegerIndexArray, options?: Options ): IntegerArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var x = [ true, false, true, false ];
+ *
+ * var idx = ArrayIndex( x );
+ * // returns
+ */
+ ( x: BooleanIndexArray, options?: Options ): BooleanArrayIndex;
+
+ /**
+ * Array index constructor.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+ * @returns ArrayIndex instance
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+ *
+ * var idx = ArrayIndex( x );
+ * // returns
+ */
+ ( x: IndexArray, options?: Options ): ArrayIndex;
+
+ /**
+ * String value of the constructor name.
+ */
+ name: 'ArrayIndex';
+
+ /**
+ * Frees the `ArrayIndex` associated with a provided identifier.
+ *
+ * @param id - identifier
+ * @returns boolean indicating whether an `ArrayIndex` was successfully freed
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+ * 'persist': true
+ * });
+ * // returns
+ *
+ * // ...
+ *
+ * var out = ArrayIndex.free( idx.id );
+ * // returns true
+ */
+ free( id: string ): boolean;
+
+ /**
+ * Returns the array associated with a provided identifier.
+ *
+ * @param id - identifier
+ * @returns object containing array index data
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+ * 'persist': true
+ * });
+ * // returns
+ *
+ * // ...
+ *
+ * var o = ArrayIndex.get( idx.id );
+ * // returns {...}
+ *
+ * var d = o.data;
+ * // returns [ 1, 0, 1, 0 ]
+ *
+ * var t = o.type;
+ * // returns 'mask'
+ *
+ * var dt = o.dtype;
+ * // returns 'uint8'
+ */
+ get( id: string ): ArrayObject;
+}
+
+/**
+* Array index constructor.
+*
+* @param x - input array
+* @param options - function options
+* @param options.persist - boolean indicating whether to continue persisting an index object after first usage
+* @returns ArrayIndex instance
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+*
+* var idx = new ArrayIndex( x );
+* // returns
+*/
+declare var ctor: Constructor;
+
+
+// EXPORTS //
+
+export = ctor;
diff --git a/index/docs/types/test.ts b/index/docs/types/test.ts
new file mode 100644
index 00000000..d330d1fb
--- /dev/null
+++ b/index/docs/types/test.ts
@@ -0,0 +1,189 @@
+/*
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/* eslint-disable @typescript-eslint/no-unused-expressions */
+
+import ArrayIndex = require( './index' );
+
+
+// TESTS //
+
+// The function returns an array index...
+{
+ const x = [ 1, 2, 3, 4 ];
+ const y = [ true, false, true, false ];
+ const z = new Uint8Array( [ 1, 0, 1, 0 ] );
+ const w = new Int32Array( [ 1, 2, 3, 4 ] );
+
+ new ArrayIndex( x ); // $ExpectType IntegerArrayIndex
+ new ArrayIndex( y ); // $ExpectType BooleanArrayIndex
+ new ArrayIndex( z ); // $ExpectType MaskArrayIndex
+ new ArrayIndex( w ); // $ExpectType Int32ArrayIndex
+
+ new ArrayIndex( x, { 'persist': true } ); // $ExpectType IntegerArrayIndex
+ new ArrayIndex( y, { 'persist': true } ); // $ExpectType BooleanArrayIndex
+ new ArrayIndex( z, { 'persist': true } ); // $ExpectType MaskArrayIndex
+ new ArrayIndex( w, { 'persist': true } ); // $ExpectType Int32ArrayIndex
+
+ ArrayIndex( x ); // $ExpectType IntegerArrayIndex
+ ArrayIndex( y ); // $ExpectType BooleanArrayIndex
+ ArrayIndex( z ); // $ExpectType MaskArrayIndex
+ ArrayIndex( w ); // $ExpectType Int32ArrayIndex
+
+ ArrayIndex( x, { 'persist': true } ); // $ExpectType IntegerArrayIndex
+ ArrayIndex( y, { 'persist': true } ); // $ExpectType BooleanArrayIndex
+ ArrayIndex( z, { 'persist': true } ); // $ExpectType MaskArrayIndex
+ ArrayIndex( w, { 'persist': true } ); // $ExpectType Int32ArrayIndex
+}
+
+// The compiler throws an error if the function is provided first argument which is not a valid collection...
+{
+ ArrayIndex( 'abc' ); // $ExpectError
+ ArrayIndex( 1 ); // $ExpectError
+ ArrayIndex( null ); // $ExpectError
+ ArrayIndex( void 0 ); // $ExpectError
+ ArrayIndex( true ); // $ExpectError
+ ArrayIndex( false ); // $ExpectError
+ ArrayIndex( {} ); // $ExpectError
+ ArrayIndex( [ {} ] ); // $ExpectError
+ ArrayIndex( ( x: number ): number => x ); // $ExpectError
+
+ ArrayIndex( 'abc', {} ); // $ExpectError
+ ArrayIndex( 1, {} ); // $ExpectError
+ ArrayIndex( null, {} ); // $ExpectError
+ ArrayIndex( void 0, {} ); // $ExpectError
+ ArrayIndex( true, {} ); // $ExpectError
+ ArrayIndex( false, {} ); // $ExpectError
+ ArrayIndex( {}, {} ); // $ExpectError
+ ArrayIndex( [ {} ], {} ); // $ExpectError
+ ArrayIndex( ( x: number ): number => x, {} ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided second argument which is not an object...
+{
+ const x = [ 1, 2, 3, 4 ];
+
+ ArrayIndex( x, 'abc' ); // $ExpectError
+ ArrayIndex( x, 1 ); // $ExpectError
+ ArrayIndex( x, null ); // $ExpectError
+ ArrayIndex( x, true ); // $ExpectError
+ ArrayIndex( x, false ); // $ExpectError
+ ArrayIndex( x, [ {} ] ); // $ExpectError
+ ArrayIndex( x, ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided `persist` option which is not a boolean...
+{
+ const x = [ 1, 2, 3, 4 ];
+
+ ArrayIndex( x, { 'persist': 'abc' } ); // $ExpectError
+ ArrayIndex( x, { 'persist': 1 } ); // $ExpectError
+ ArrayIndex( x, { 'persist': null } ); // $ExpectError
+ ArrayIndex( x, { 'persist': {} } ); // $ExpectError
+ ArrayIndex( x, { 'persist': [] } ); // $ExpectError
+ ArrayIndex( x, { 'persist': ( x: number ): number => x } ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an unsupported number of arguments...
+{
+ const x = [ 1, 2, 3, 4 ];
+
+ ArrayIndex(); // $ExpectError
+ ArrayIndex( x, {}, {} ); // $ExpectError
+}
+
+// Attached to the main export is a `free` function which returns a boolean...
+{
+ ArrayIndex.free( '0' ); // $ExpectType boolean
+}
+
+// The compiler throws an error if the `free` method is provided first argument which is not a string...
+{
+ ArrayIndex.free( 1 ); // $ExpectError
+ ArrayIndex.free( null ); // $ExpectError
+ ArrayIndex.free( void 0 ); // $ExpectError
+ ArrayIndex.free( true ); // $ExpectError
+ ArrayIndex.free( false ); // $ExpectError
+ ArrayIndex.free( {} ); // $ExpectError
+ ArrayIndex.free( [] ); // $ExpectError
+ ArrayIndex.free( ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the `free` method is provided an unsupported number of arguments...
+{
+ ArrayIndex.free(); // $ExpectError
+ ArrayIndex.free( '0', {} ); // $ExpectError
+}
+
+// Attached to the main export is a `get` function which returns array object data...
+{
+ ArrayIndex.get( '0' ); // $ExpectType ArrayObject
+}
+
+// The compiler throws an error if the `get` method is provided first argument which is not a string...
+{
+ ArrayIndex.get( 1 ); // $ExpectError
+ ArrayIndex.get( null ); // $ExpectError
+ ArrayIndex.get( void 0 ); // $ExpectError
+ ArrayIndex.get( true ); // $ExpectError
+ ArrayIndex.get( false ); // $ExpectError
+ ArrayIndex.get( {} ); // $ExpectError
+ ArrayIndex.get( [] ); // $ExpectError
+ ArrayIndex.get( ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the `get` method is provided an unsupported number of arguments...
+{
+ ArrayIndex.get(); // $ExpectError
+ ArrayIndex.get( '0', {} ); // $ExpectError
+}
+
+// An array index has a `dtype` property which returns a string...
+{
+ const x = new ArrayIndex( [ 1, 2, 3, 4 ] );
+
+ x.dtype; // $ExpectType "generic"
+}
+
+// An array index has an `id` property which returns a string...
+{
+ const x = new ArrayIndex( [ 1, 2, 3, 4 ] );
+
+ x.id; // $ExpectType string
+}
+
+// An array index has a `type` property which returns a string...
+{
+ const x = new ArrayIndex( [ 1, 2, 3, 4 ] );
+
+ x.type; // $ExpectType "int"
+}
+
+// An array index has a `data` property which returns a collection...
+{
+ const x = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+
+ x.data; // $ExpectType Uint8Array
+}
+
+// An array index has an `isCached` property which returns a boolean...
+{
+ const x = new ArrayIndex( [ 1, 2, 3, 4 ] );
+
+ x.isCached; // $ExpectType boolean
+}
diff --git a/index/examples/index.js b/index/examples/index.js
new file mode 100644
index 00000000..f64908f4
--- /dev/null
+++ b/index/examples/index.js
@@ -0,0 +1,59 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+var Uint8Array = require( './../../uint8' );
+var Int32Array = require( './../../int32' );
+var ArrayIndex = require( './../lib' );
+
+var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+var i = new ArrayIndex( x );
+// returns
+
+var o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = [ true, false, true, false ];
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = new Int32Array( [ 1, 3, 4, 7 ] );
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
+
+x = [ 1, 3, 4, 7 ];
+i = new ArrayIndex( x );
+// returns
+
+o = ArrayIndex.get( i.id );
+// returns {...}
+
+console.log( 'Type: %s. Data type: %s.', o.type, o.dtype );
diff --git a/index/lib/cache.js b/index/lib/cache.js
new file mode 100644
index 00000000..ff74dc49
--- /dev/null
+++ b/index/lib/cache.js
@@ -0,0 +1,40 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var LinkedList = require( '@stdlib/utils/linked-list' );
+
+
+// MAIN //
+
+/**
+* Cache for storing index arrays.
+*
+* @private
+* @name cache
+* @type {LinkedList}
+*/
+var cache = new LinkedList(); // note: created as a linked list to allow for more efficient removal of expired index arrays
+
+
+// EXPORTS //
+
+module.exports = cache;
diff --git a/index/lib/cache_gc.js b/index/lib/cache_gc.js
new file mode 100644
index 00000000..b3160110
--- /dev/null
+++ b/index/lib/cache_gc.js
@@ -0,0 +1,59 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var cache = require( './cache.js' );
+
+
+// MAIN //
+
+/**
+* Performs garbage collection on the index cache.
+*
+* @private
+* @returns {Object} garbage collection results
+*/
+function gc() {
+ var node;
+ var N;
+ var M;
+ var v;
+
+ node = cache.first();
+ N = cache.length;
+ while ( node ) {
+ v = node.value;
+ if ( !v.persist ) {
+ cache.remove( node );
+ }
+ node = node.next;
+ }
+ M = cache.length;
+ return {
+ 'size': M,
+ 'removed': N - M
+ };
+}
+
+
+// EXPORTS //
+
+module.exports = gc;
diff --git a/index/lib/defaults.js b/index/lib/defaults.js
new file mode 100644
index 00000000..44fa8dc1
--- /dev/null
+++ b/index/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} defaults
+*
+* @example
+* var o = defaults();
+* // returns {...}
+*/
+function defaults() {
+ return {
+ 'persist': false
+ };
+}
+
+
+// EXPORTS //
+
+module.exports = defaults;
diff --git a/index/lib/find.js b/index/lib/find.js
new file mode 100644
index 00000000..3e14813f
--- /dev/null
+++ b/index/lib/find.js
@@ -0,0 +1,49 @@
+/**
+* @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 cache = require( './cache.js' );
+
+
+// MAIN //
+
+/**
+* Returns an array index object associated with a specified identifier.
+*
+* @private
+* @param {*} id - identifier
+* @returns {(Node|null)} array index object
+*/
+function find( id ) { // eslint-disable-line stdlib/no-redeclare
+ var node = cache.first();
+ while ( node ) {
+ if ( node.value.id === id ) {
+ return node;
+ }
+ node = node.next;
+ }
+ return null;
+}
+
+
+// EXPORTS //
+
+module.exports = find;
diff --git a/index/lib/id.js b/index/lib/id.js
new file mode 100644
index 00000000..64b99b46
--- /dev/null
+++ b/index/lib/id.js
@@ -0,0 +1,46 @@
+/**
+* @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';
+
+// VARIABLES //
+
+var COUNTER = -1; // TODO: consider another approach for unique identifier generation. For most cases, this should suffice; however, it is possible that two different libraries, both relying on separate copies of this package, may trigger id collisions in the event that instantiated instances were to interact (e.g., a consumer attempting to free an instance instantiated by another copy of the package, etc).
+
+
+// MAIN //
+
+/**
+* Generates a new identifier.
+*
+* @private
+* @returns {string} identifier
+*
+* @example
+* var v = id();
+* // returns
+*/
+function id() {
+ COUNTER += 1;
+ return COUNTER.toString();
+}
+
+
+// EXPORTS //
+
+module.exports = id;
diff --git a/index/lib/index.js b/index/lib/index.js
new file mode 100644
index 00000000..6c5586d8
--- /dev/null
+++ b/index/lib/index.js
@@ -0,0 +1,43 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+/**
+* Array index constructor.
+*
+* @module @stdlib/array/index
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+* var ArrayIndex = require( '@stdlib/array/index' );
+*
+* var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+*
+* var idx = new ArrayIndex( x );
+* // returns
+*/
+
+// MODULES //
+
+var main = require( './main.js' );
+
+
+// EXPORTS //
+
+module.exports = main;
diff --git a/index/lib/main.js b/index/lib/main.js
new file mode 100644
index 00000000..73544516
--- /dev/null
+++ b/index/lib/main.js
@@ -0,0 +1,443 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+/* eslint-disable no-restricted-syntax, no-invalid-this */
+
+'use strict';
+
+// MODULES //
+
+var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' );
+var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
+var setNonEnumerable = require( '@stdlib/utils/define-nonenumerable-property' );
+var isCollection = require( '@stdlib/assert/is-collection' );
+var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
+var isInteger = require( '@stdlib/assert/is-integer' ).isPrimitive;
+var isAccessorArray = require( './../../base/assert/is-accessor-array' );
+var array2json = require( './../../to-json' );
+var dtype = require( './../../dtype' );
+var copy = require( './../../base/copy' );
+var resolveGetter = require( './../../base/resolve-getter' );
+var format = require( '@stdlib/string/format' );
+var defaults = require( './defaults.js' );
+var validate = require( './validate.js' );
+var cache = require( './cache.js' );
+var findArrayIndex = require( './find.js' );
+var generateId = require( './id.js' );
+
+
+// MAIN //
+
+/**
+* Array index constructor.
+*
+* @param {Collection} x - input array
+* @param {Options} [options] - function options
+* @param {boolean} [options.persist=false] - boolean indicating whether to continue persisting an index object after first usage
+* @throws {TypeError} first argument must be an array-like object
+* @throws {TypeError} first argument must be a valid index array
+* @throws {TypeError} options argument must be an object
+* @throws {TypeError} must provide valid options
+* @returns {ArrayIndex} ArrayIndex instance
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var x = new Uint8Array( [ 1, 0, 1, 0 ] );
+*
+* var idx = new ArrayIndex( x );
+* // returns
+*/
+function ArrayIndex( x ) {
+ var opts;
+ var err;
+ var get;
+ var dt;
+ var t;
+ var v;
+ if ( !(this instanceof ArrayIndex) ) {
+ if ( arguments.length > 1 ) {
+ return new ArrayIndex( x, arguments[ 1 ] );
+ }
+ return new ArrayIndex( x );
+ }
+ if ( !isCollection( x ) ) {
+ throw new TypeError( format( 'invalid argument. First argument must be an array-like object. Value: `%s`.', x ) );
+ }
+ dt = dtype( x );
+
+ // When provided a "generic" array or an array of an unknown data type, attempt to infer the type of index array...
+ if ( dt === 'generic' || dt === null ) {
+ get = resolveGetter( x );
+ v = get( x, 0 );
+
+ // Infer the "type" of index array from the first element...
+ if ( isBoolean( v ) ) {
+ t = 'bool';
+ } else if ( isInteger( v ) ) {
+ t = 'int';
+ } else {
+ throw new TypeError( 'invalid argument. First argument must be a valid index array.' );
+ }
+ } else if ( dt === 'int32' ) {
+ t = 'int';
+ } else if ( dt === 'uint8' ) {
+ t = 'mask';
+ } else {
+ throw new TypeError( 'invalid argument. First argument must be a valid index array.' );
+ }
+ // Resolve index options:
+ opts = defaults();
+ if ( arguments.length > 1 ) {
+ err = validate( opts, arguments[ 1 ] );
+ if ( err ) {
+ throw err;
+ }
+ }
+ // Add the array index to the index cache:
+ cache.push({
+ 'id': generateId(),
+ 'ref': this,
+ 'data': x,
+ 'type': t,
+ 'dtype': dt,
+ 'persist': opts.persist
+ });
+
+ // Store a reference to the cache node:
+ setReadOnly( this, '_node', cache.last() );
+
+ // Initialize a boolean flag indicating whether an array index object has been invalidated (i.e., freed):
+ setNonEnumerable( this, '_invalidated', false );
+
+ return this;
+}
+
+/**
+* Constructor name.
+*
+* @name name
+* @memberof ArrayIndex
+* @readonly
+* @type {string}
+* @default 'ArrayIndex'
+*
+* @example
+* var str = ArrayIndex.name;
+* // returns 'ArrayIndex'
+*/
+setReadOnly( ArrayIndex, 'name', 'ArrayIndex' );
+
+/**
+* Frees an array index object associated with a provided identifier.
+*
+* @name free
+* @memberof ArrayIndex
+* @type {Function}
+* @param {string} id - identifier
+* @returns {boolean} boolean indicating whether an array index object was successfully freed
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+* 'persist': true
+* });
+* // returns
+*
+* // ...
+*
+* var out = ArrayIndex.free( idx.id );
+* // returns true
+*/
+setReadOnly( ArrayIndex, 'free', function free( id ) {
+ var node;
+ var v;
+
+ // Retrieve the array index object with the specified identifier:
+ node = findArrayIndex( id );
+ if ( node === null ) {
+ return false;
+ }
+ v = node.value;
+
+ // Invalidate the array instance object:
+ setReadOnly( v.ref, '_invalidated', true );
+
+ // Remove the array instance from the cache:
+ cache.remove( node );
+
+ // Remove the reference to the original array:
+ v.data = null;
+
+ return true;
+});
+
+/**
+* Returns the array associated with a provided identifier.
+*
+* @name get
+* @memberof ArrayIndex
+* @type {Function}
+* @param {string} id - identifier
+* @returns {(Object|null)} object containing array index data
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ), {
+* 'persist': true
+* });
+* // returns
+*
+* // ...
+*
+* var o = ArrayIndex.get( idx.id );
+* // returns {...}
+*
+* var d = o.data;
+* // returns [ 1, 0, 1, 0 ]
+*
+* var t = o.type;
+* // returns 'mask'
+*
+* var dt = o.dtype;
+* // returns 'uint8'
+*/
+setReadOnly( ArrayIndex, 'get', function get( id ) {
+ var node;
+ var out;
+ var v;
+
+ // Retrieve the array index object with the specified identifier:
+ node = findArrayIndex( id );
+ if ( node === null ) {
+ return null;
+ }
+ v = node.value;
+
+ // Assemble the output object:
+ out = {
+ 'data': v.data,
+ 'type': v.type,
+ 'dtype': v.dtype
+ };
+
+ // If the array index object should not be persisted, go ahead and remove the object from the cache...
+ if ( !v.persist ) {
+ ArrayIndex.free( id ); // note: this should come last, after having retrieved all desired array index node data
+ }
+ return out;
+});
+
+/**
+* Returns the underlying array data of array index object.
+*
+* @name data
+* @memberof ArrayIndex.prototype
+* @readonly
+* @type {Collection}
+* @throws {Error} array index is no longer valid
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var v = idx.data;
+* // returns [ 1, 0, 1, 0 ]
+*/
+setReadOnlyAccessor( ArrayIndex.prototype, 'data', function get() {
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ return this._node.value.data;
+});
+
+/**
+* Returns the underlying array data type of array index object.
+*
+* @name dtype
+* @memberof ArrayIndex.prototype
+* @readonly
+* @type {string}
+* @throws {Error} array index is no longer valid
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var t = idx.dtype;
+* // returns 'uint8'
+*/
+setReadOnlyAccessor( ArrayIndex.prototype, 'dtype', function get() {
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ return this._node.value.dtype;
+});
+
+/**
+* Returns the identifier associated with an array index object.
+*
+* @name id
+* @memberof ArrayIndex.prototype
+* @readonly
+* @type {string}
+* @throws {Error} array index is no longer valid
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var id = idx.id;
+* // returns
+*/
+setReadOnlyAccessor( ArrayIndex.prototype, 'id', function get() {
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ return this._node.value.id;
+});
+
+/**
+* Returns a boolean indicating if an array index is actively cached.
+*
+* @name isCached
+* @memberof ArrayIndex.prototype
+* @readonly
+* @type {boolean}
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var out = idx.isCached;
+* // returns true
+*/
+setReadOnlyAccessor( ArrayIndex.prototype, 'isCached', function get() {
+ return !this._invalidated;
+});
+
+/**
+* Returns the type of array index object.
+*
+* @name type
+* @memberof ArrayIndex.prototype
+* @readonly
+* @type {string}
+* @throws {Error} array index is no longer valid
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var t = idx.type;
+* // returns 'mask'
+*/
+setReadOnlyAccessor( ArrayIndex.prototype, 'type', function get() {
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ return this._node.value.type;
+});
+
+/**
+* Serializes an array index object to a string.
+*
+* @name toString
+* @memberof ArrayIndex.prototype
+* @type {Function}
+* @throws {Error} array index is no longer valid
+* @returns {string} serialized array index object
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var str = idx.toString();
+* // e.g., 'ArrayIndex<0>'
+*/
+setReadOnly( ArrayIndex.prototype, 'toString', function toString() {
+ var v;
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ v = this._node.value;
+ return 'ArrayIndex<' + v.id + '>';
+});
+
+/**
+* Serializes an array index object as a JSON object.
+*
+* ## Notes
+*
+* - `JSON.stringify()` implicitly calls this method when stringifying an `ArrayIndex` instance.
+*
+* @name toJSON
+* @memberof ArrayIndex.prototype
+* @type {Function}
+* @throws {Error} array index is no longer valid
+* @returns {Object} serialized array index object
+*
+* @example
+* var Uint8Array = require( '@stdlib/array/uint8' );
+*
+* var idx = new ArrayIndex( new Uint8Array( [ 1, 0, 1, 0 ] ) );
+* // returns
+*
+* var o = idx.toJSON();
+* // returns { 'type': 'ArrayIndex', 'data': { 'type': 'Uint8Array', 'data': [ 1, 0, 1, 0 ] } }
+*/
+setReadOnly( ArrayIndex.prototype, 'toJSON', function toJSON() {
+ var v;
+ var o;
+ if ( this._invalidated ) {
+ throw new Error( 'invalid operation. This array index instance has already been freed and can no longer be used.' );
+ }
+ v = this._node.value;
+ if ( v.dtype === 'generic' || v.dtype === null ) {
+ if ( isAccessorArray( v.data ) ) {
+ o = copy( v.data );
+ } else {
+ o = v.data;
+ }
+ } else {
+ o = array2json( v.data );
+ }
+ return {
+ 'type': 'ArrayIndex',
+ 'data': o
+ };
+});
+
+
+// EXPORTS //
+
+module.exports = ArrayIndex;
diff --git a/index/lib/validate.js b/index/lib/validate.js
new file mode 100644
index 00000000..75d3a46a
--- /dev/null
+++ b/index/lib/validate.js
@@ -0,0 +1,66 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var isObject = require( '@stdlib/assert/is-plain-object' );
+var hasOwnProp = require( '@stdlib/assert/has-own-property' );
+var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
+var format = require( '@stdlib/string/format' );
+
+
+// MAIN //
+
+/**
+* Validates function options.
+*
+* @private
+* @param {Object} opts - destination object
+* @param {Options} options - function options
+* @param {boolean} [options.persist] - boolean indicating whether to continue persisting an index object after first usage
+* @returns {(Error|null)} null or an error object
+*
+* @example
+* var opts = {};
+* var options = {
+* 'persist': false
+* };
+* 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, 'persist' ) ) {
+ opts.persist = options.persist;
+ if ( !isBoolean( opts.persist ) ) {
+ return new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'persist', opts.persist ) );
+ }
+ }
+ return null;
+}
+
+
+// EXPORTS //
+
+module.exports = validate;
diff --git a/index/package.json b/index/package.json
new file mode 100644
index 00000000..e3241bb6
--- /dev/null
+++ b/index/package.json
@@ -0,0 +1,66 @@
+{
+ "name": "@stdlib/array/index",
+ "version": "0.0.0",
+ "description": "Array index constructor.",
+ "license": "Apache-2.0",
+ "author": {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ },
+ "contributors": [
+ {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ }
+ ],
+ "main": "./lib",
+ "directories": {
+ "benchmark": "./benchmark",
+ "doc": "./docs",
+ "example": "./examples",
+ "lib": "./lib",
+ "test": "./test"
+ },
+ "types": "./docs/types",
+ "scripts": {},
+ "homepage": "https://github.com/stdlib-js/stdlib",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/stdlib-js/stdlib.git"
+ },
+ "bugs": {
+ "url": "https://github.com/stdlib-js/stdlib/issues"
+ },
+ "dependencies": {},
+ "devDependencies": {},
+ "engines": {
+ "node": ">=0.10.0",
+ "npm": ">2.7.0"
+ },
+ "os": [
+ "aix",
+ "darwin",
+ "freebsd",
+ "linux",
+ "macos",
+ "openbsd",
+ "sunos",
+ "win32",
+ "windows"
+ ],
+ "keywords": [
+ "stdlib",
+ "stdtypes",
+ "types",
+ "data",
+ "structure",
+ "array",
+ "fancy",
+ "indexing",
+ "index",
+ "vector",
+ "slice",
+ "constructor",
+ "ctor"
+ ]
+}
diff --git a/index/test/test.js b/index/test/test.js
new file mode 100644
index 00000000..dd99b3dd
--- /dev/null
+++ b/index/test/test.js
@@ -0,0 +1,87 @@
+/**
+* @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 instanceOf = require( '@stdlib/assert/instance-of' );
+var Uint8Array = require( './../../uint8' );
+var Int32Array = require( './../../int32' );
+var toAccessorArray = require( './../../base/to-accessor-array' );
+var ArrayIndex = require( './../lib' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof ArrayIndex, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function is a constructor', function test( t ) {
+ var x;
+
+ x = new ArrayIndex( [ 1, 2, 3 ] );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = new ArrayIndex( [ true, false, true ] );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = new ArrayIndex( toAccessorArray( [ 1, 2, 3 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = new ArrayIndex( new Uint8Array( [ 1, 0, 1 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = new ArrayIndex( new Int32Array( [ 1, 0, 1 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function does not require the `new` keyword', function test( t ) {
+ var idx;
+ var x;
+
+ idx = ArrayIndex;
+
+ x = idx( [ 1, 2, 3 ] );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = idx( [ true, false, true ] );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = idx( toAccessorArray( [ 1, 2, 3 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = idx( new Uint8Array( [ 1, 0, 1 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ x = idx( new Int32Array( [ 1, 0, 1 ] ) );
+ t.strictEqual( instanceOf( x, ArrayIndex ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'attached to the constructor is a `name` property', function test( t ) {
+ t.strictEqual( ArrayIndex.name, 'ArrayIndex', 'returns expected value' );
+ t.end();
+});
diff --git a/lib/index.js b/lib/index.js
index a12c3393..03af8058 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -274,6 +274,15 @@ setReadOnly( ns, 'afullLike', require( './../full-like' ) );
*/
setReadOnly( ns, 'incrspace', require( './../incrspace' ) );
+/**
+* @name ArrayIndex
+* @memberof ns
+* @readonly
+* @constructor
+* @see {@link module:@stdlib/array/index}
+*/
+setReadOnly( ns, 'ArrayIndex', require( './../index' ) );
+
/**
* @name Int8Array
* @memberof ns
@@ -472,6 +481,15 @@ setReadOnly( ns, 'SharedArrayBuffer', require( './../shared-buffer' ) );
*/
setReadOnly( ns, 'aslice', require( './../slice' ) );
+/**
+* @name atake
+* @memberof ns
+* @readonly
+* @type {Function}
+* @see {@link module:@stdlib/array/take}
+*/
+setReadOnly( ns, 'atake', require( './../take' ) );
+
/**
* @name circarray2iterator
* @memberof ns
diff --git a/one-to/README.md b/one-to/README.md
index 0c995839..a767c284 100644
--- a/one-to/README.md
+++ b/one-to/README.md
@@ -142,6 +142,15 @@ console.log( y );
@@ -152,6 +161,18 @@ console.log( y );
[mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
+
+
+[@stdlib/array/full]: https://github.com/stdlib-js/array/tree/main/full
+
+[@stdlib/array/ones]: https://github.com/stdlib-js/array/tree/main/ones
+
+[@stdlib/array/one-to-like]: https://github.com/stdlib-js/array/tree/main/one-to-like
+
+[@stdlib/array/zero-to]: https://github.com/stdlib-js/array/tree/main/zero-to
+
+
+
diff --git a/package.json b/package.json
index 76fa77ec..4a191f53 100644
--- a/package.json
+++ b/package.json
@@ -44,6 +44,7 @@
"@stdlib/iter": "github:stdlib-js/iter#main",
"@stdlib/math": "github:stdlib-js/math#main",
"@stdlib/ndarray": "github:stdlib-js/ndarray#main",
+ "@stdlib/object": "github:stdlib-js/object#main",
"@stdlib/proxy": "github:stdlib-js/proxy#main",
"@stdlib/slice": "github:stdlib-js/slice#main",
"@stdlib/strided": "github:stdlib-js/strided#main",
diff --git a/take/README.md b/take/README.md
new file mode 100644
index 00000000..dcf22b2a
--- /dev/null
+++ b/take/README.md
@@ -0,0 +1,155 @@
+
+
+# take
+
+> Take elements from an array.
+
+
+
+## Usage
+
+```javascript
+var take = require( '@stdlib/array/take' );
+```
+
+#### take( x, indices\[, options] )
+
+Takes elements from an array.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var y = take( x, [ 1, 3 ] );
+// returns [ 2, 4 ]
+```
+
+The function supports the following parameters:
+
+- **x**: input array.
+- **indices**: list of indices.
+- **options**: function options.
+
+The function supports the following options:
+
+- **mode**: index [mode][@stdlib/ndarray/base/ind]. Default: `'normalize'`.
+
+By default, the function normalizes negative integer indices to positive integer index equivalents.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var y = take( x, [ -3, -1 ] );
+// returns [ 2, 4 ]
+```
+
+To specify an alternative index [mode][@stdlib/ndarray/base/ind], provide a `mode` option.
+
+```javascript
+var x = [ 1, 2, 3, 4 ];
+
+var y = take( x, [ -10, 10 ], {
+ 'mode': 'clamp'
+});
+// returns [ 1, 4 ]
+```
+
+
+
+
+
+
+
+## Notes
+
+- If `indices` is an empty array, the function returns an empty array.
+
+ ```javascript
+ var x = [ 1, 2, 3, 4 ];
+
+ var y = take( x, [] );
+ // returns []
+ ```
+
+- If provided an input array having a recognized [data type][@stdlib/array/dtypes], the function returns an array having the same [data type][@stdlib/array/dtypes] as the input array. Otherwise, the function **always** returns a "generic" array.
+
+
+
+
+
+
+
+## Examples
+
+
+
+```javascript
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var linspace = require( '@stdlib/array/linspace' );
+var take = require( '@stdlib/array/take' );
+
+// Generate a linearly spaced array:
+var x = linspace( 0, 100, 11 );
+console.log( x );
+
+// Generate an array of random indices:
+var indices = discreteUniform( 10, 0, x.length-1 );
+console.log( indices );
+
+// Take a random sample of elements from `x`:
+var y = take( x, indices );
+console.log( y );
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[@stdlib/ndarray/base/ind]: https://github.com/stdlib-js/ndarray-base-ind
+
+[@stdlib/array/dtypes]: https://github.com/stdlib-js/array/tree/main/dtypes
+
+
+
+[@stdlib/array/slice]: https://github.com/stdlib-js/array/tree/main/slice
+
+
+
+
+
+
diff --git a/take/benchmark/benchmark.js b/take/benchmark/benchmark.js
new file mode 100644
index 00000000..8975c75d
--- /dev/null
+++ b/take/benchmark/benchmark.js
@@ -0,0 +1,52 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var bench = require( '@stdlib/bench' );
+var isArray = require( '@stdlib/assert/is-array' );
+var zeroTo = require( './../../base/zero-to' );
+var pkg = require( './../package.json' ).name;
+var take = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+'::copy:len=100', function benchmark( b ) {
+ var x;
+ var i;
+ var v;
+
+ x = zeroTo( 100 );
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = take( x, 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();
+});
diff --git a/take/benchmark/benchmark.length.js b/take/benchmark/benchmark.length.js
new file mode 100644
index 00000000..f81872fd
--- /dev/null
+++ b/take/benchmark/benchmark.length.js
@@ -0,0 +1,98 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var bench = require( '@stdlib/bench' );
+var pow = require( '@stdlib/math/base/special/pow' );
+var discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var isArray = require( '@stdlib/assert/is-array' );
+var pkg = require( './../package.json' ).name;
+var take = require( './../lib' );
+
+
+// FUNCTIONS //
+
+/**
+* Creates a benchmark function.
+*
+* @private
+* @param {PositiveInteger} len - array length
+* @returns {Function} benchmark function
+*/
+function createBenchmark( len ) {
+ var idx = discreteUniform( len, 0, 3 );
+ return benchmark;
+
+ /**
+ * Benchmark function.
+ *
+ * @private
+ * @param {Benchmark} b - benchmark instance
+ */
+ function benchmark( b ) {
+ var x;
+ var v;
+ var i;
+
+ x = [ 1, 2, 3, 4 ];
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = take( x, idx );
+ 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/take/docs/repl.txt b/take/docs/repl.txt
new file mode 100644
index 00000000..eb4e87aa
--- /dev/null
+++ b/take/docs/repl.txt
@@ -0,0 +1,40 @@
+
+{{alias}}( x, indices[, options] )
+ Takes elements from an array.
+
+ If `indices` is an empty array, the function returns an empty array.
+
+ Parameters
+ ----------
+ x: Array|TypedArray|Object
+ Input array.
+
+ indices: ArrayLikeObject
+ List of element indices.
+
+ options: Object (optional)
+ Function options.
+
+ options.mode: string (optional)
+ Specifies how to handle an index outside the interval [0, max], where
+ `max` is the maximum possible array index. If equal to 'throw', the
+ function throws an error. If equal to 'normalize', the function throws
+ an error if provided an out-of-bounds normalized index. If equal to
+ 'wrap', the function wraps around an index using modulo arithmetic. If
+ equal to 'clamp', the function sets an index to either 0 (minimum index)
+ or the maximum index. Default: 'normalize'.
+
+ Returns
+ -------
+ out: Array|TypedArray
+ Output array.
+
+ Examples
+ --------
+ > var x = [ 1, 2, 3, 4 ];
+ > var y = {{alias}}( x, [ 1, 3 ] )
+ [ 2, 4 ]
+
+ See Also
+ --------
+
diff --git a/take/docs/types/index.d.ts b/take/docs/types/index.d.ts
new file mode 100644
index 00000000..fcf1547f
--- /dev/null
+++ b/take/docs/types/index.d.ts
@@ -0,0 +1,247 @@
+/*
+* @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, Complex128Array, Complex64Array } from '@stdlib/types/array';
+import { Mode } from '@stdlib/types/ndarray';
+
+/**
+* Index array.
+*/
+type IndexArray = Collection | AccessorArrayLike;
+
+/**
+* Interface describing function options.
+*/
+interface Options {
+ /**
+ * Index mode.
+ */
+ mode?: Mode;
+}
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'float64' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2.0, 4.0 ]
+*/
+declare function take( x: Float64Array, indices: IndexArray, options?: Options ): Float64Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'float32' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2.0, 4.0 ]
+*/
+declare function take( x: Float32Array, indices: IndexArray, options?: Options ): Float32Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'int32' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Int32Array, indices: IndexArray, options?: Options ): Int32Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'int16' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Int16Array, indices: IndexArray, options?: Options ): Int16Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'int8' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Int8Array, indices: IndexArray, options?: Options ): Int8Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'uint32' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Uint32Array, indices: IndexArray, options?: Options ): Uint32Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'uint16' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Uint16Array, indices: IndexArray, options?: Options ): Uint16Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'uint8' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Uint8Array, indices: IndexArray, options?: Options ): Uint8Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'uint8c' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Uint8ClampedArray, indices: IndexArray, options?: Options ): Uint8ClampedArray;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'complex128' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2.0, 0.0, 4.0, 0.0 ]
+*/
+declare function take( x: Complex128Array, indices: IndexArray, options?: Options ): Complex128Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var zeroTo = require( '@stdlib/array/zero-to' );
+*
+* var x = zeroTo( 4, 'complex64' );
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2.0, 0.0, 4.0, 0.0 ]
+*/
+declare function take( x: Complex64Array, indices: IndexArray, options?: Options ): Complex64Array;
+
+/**
+* Takes elements from an array.
+*
+* @param x - input array
+* @param indices - list of element indices
+* @param options - function options
+* @returns output array
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+*
+* var y = take( x, [ 1, 3 ] );
+* // returns [ 2, 4 ]
+*/
+declare function take( x: Collection | AccessorArrayLike, indices: IndexArray, options?: Options ): Array;
+
+
+// EXPORTS //
+
+export = take;
diff --git a/take/docs/types/test.ts b/take/docs/types/test.ts
new file mode 100644
index 00000000..0fe1ea80
--- /dev/null
+++ b/take/docs/types/test.ts
@@ -0,0 +1,94 @@
+/*
+* @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 take = require( './index' );
+
+
+// TESTS //
+
+// The function returns an array...
+{
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType number[]
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType any[]
+ take( [ 1, 2, 3, 4 ], [ 1, 3 ] ); // $ExpectType number[]
+ take( [ '1', '2', '3', '4' ], [ 1, 3 ] ); // $ExpectType string[]
+
+ take( new Float64Array( 10 ), [ 1, 3 ] ); // $ExpectType Float64Array
+ take( new Float32Array( 10 ), [ 1, 3 ] ); // $ExpectType Float32Array
+ take( new Int32Array( 10 ), [ 1, 3 ] ); // $ExpectType Int32Array
+ take( new Int16Array( 10 ), [ 1, 3 ] ); // $ExpectType Int16Array
+ take( new Int8Array( 10 ), [ 1, 3 ] ); // $ExpectType Int8Array
+ take( new Uint32Array( 10 ), [ 1, 3 ] ); // $ExpectType Uint32Array
+ take( new Uint16Array( 10 ), [ 1, 3 ] ); // $ExpectType Uint16Array
+ take( new Uint8Array( 10 ), [ 1, 3 ] ); // $ExpectType Uint8Array
+ take( new Uint8ClampedArray( 10 ), [ 1, 3 ] ); // $ExpectType Uint8ClampedArray
+ take( new Complex128Array( 10 ), [ 1, 3 ] ); // $ExpectType Complex128Array
+ take( new Complex64Array( 10 ), [ 1, 3 ] ); // $ExpectType Complex64Array
+}
+
+// The compiler throws an error if the function is provided a first argument which is not an array-like object...
+{
+ take( 1, [ 1, 3 ] ); // $ExpectError
+ take( true, [ 1, 3 ] ); // $ExpectError
+ take( false, [ 1, 3 ] ); // $ExpectError
+ take( null, [ 1, 3 ] ); // $ExpectError
+ take( void 0, [ 1, 3 ] ); // $ExpectError
+ take( {}, [ 1, 3 ] ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a second argument which is not an array-like object containing numbers...
+{
+ take( [], 1 ); // $ExpectError
+ take( [], true ); // $ExpectError
+ take( [], false ); // $ExpectError
+ take( [], null ); // $ExpectError
+ take( [], void 0 ); // $ExpectError
+ take( [], {} ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a third argument which is not an object...
+{
+ take( [], [ 1, 3 ], '1' ); // $ExpectError
+ take( [], [ 1, 3 ], 1 ); // $ExpectError
+ take( [], [ 1, 3 ], true ); // $ExpectError
+ take( [], [ 1, 3 ], false ); // $ExpectError
+ take( [], [ 1, 3 ], null ); // $ExpectError
+ take( [], [ 1, 3 ], [] ); // $ExpectError
+ take( [], [ 1, 3 ], ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided a `mode` option which is not a valid index mode...
+{
+ take( [], [ 1, 3 ], { 'mode': '1' } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': 1 } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': true } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': false } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': null } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': {} } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': [] } ); // $ExpectError
+ take( [], [ 1, 3 ], { 'mode': ( x: number ): number => x } ); // $ExpectError
+}
+
+// The compiler throws an error if the function is provided an unsupported number of arguments...
+{
+ take(); // $ExpectError
+ take( [] ); // $ExpectError
+ take( [], [], {}, {} ); // $ExpectError
+}
diff --git a/take/examples/index.js b/take/examples/index.js
new file mode 100644
index 00000000..49fd565a
--- /dev/null
+++ b/take/examples/index.js
@@ -0,0 +1,35 @@
+/**
+* @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 discreteUniform = require( '@stdlib/random/array/discrete-uniform' );
+var linspace = require( './../../linspace' );
+var take = require( './../lib' );
+
+// Generate a linearly spaced array:
+var x = linspace( 0, 100, 11 );
+console.log( x );
+
+// Generate an array of random indices:
+var indices = discreteUniform( 10, 0, x.length-1 );
+console.log( indices );
+
+// Take a random sample of elements from `x`:
+var y = take( x, indices );
+console.log( y );
diff --git a/take/lib/defaults.js b/take/lib/defaults.js
new file mode 100644
index 00000000..ea262044
--- /dev/null
+++ b/take/lib/defaults.js
@@ -0,0 +1,42 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MAIN //
+
+/**
+* Returns default options.
+*
+* @private
+* @returns {Object} default options
+*
+* @example
+* var o = defaults();
+* // returns {...}
+*/
+function defaults() {
+ return {
+ 'mode': 'normalize'
+ };
+}
+
+
+// EXPORTS //
+
+module.exports = defaults;
diff --git a/take/lib/index.js b/take/lib/index.js
new file mode 100644
index 00000000..ae09036b
--- /dev/null
+++ b/take/lib/index.js
@@ -0,0 +1,43 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+/**
+* Take elements from an array.
+*
+* @module @stdlib/array/take
+*
+* @example
+* var take = require( '@stdlib/array/take' );
+*
+* var x = [ 1, 2, 3, 4 ];
+*
+* var indices = [ 0, 0, 1, 1, 3, 3 ];
+* var y = take( x, indices );
+* // returns [ 1, 1, 2, 2, 4, 4 ]
+*/
+
+// MODULES //
+
+var main = require( './main.js' );
+
+
+// EXPORTS //
+
+module.exports = main;
diff --git a/take/lib/main.js b/take/lib/main.js
new file mode 100644
index 00000000..0ebfff78
--- /dev/null
+++ b/take/lib/main.js
@@ -0,0 +1,81 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var isCollection = require( '@stdlib/assert/is-collection' );
+var base = require( './../../base/take' );
+var zeros = require( './../../zeros' );
+var dtype = require( './../../dtype' );
+var format = require( '@stdlib/string/format' );
+var defaults = require( './defaults.js' );
+var validate = require( './validate.js' );
+
+
+// MAIN //
+
+/**
+* Takes elements from an array.
+*
+* @param {Collection} x - input array
+* @param {IntegerArray} indices - list of indices
+* @param {Options} [options] - function options
+* @param {string} [options.mode='normalize'] - index mode
+* @throws {TypeError} first argument must be a collection
+* @throws {TypeError} second argument must be a collection
+* @throws {TypeError} options argument must be an object
+* @throws {Error} must provide valid options
+* @returns {Collection} output array
+*
+* @example
+* var x = [ 1, 2, 3, 4 ];
+* var indices = [ 3, 1, 2, 0 ];
+*
+* var y = take( x, indices );
+* // returns [ 4, 2, 3, 1 ]
+*/
+function take( x, indices ) {
+ var opts;
+ var err;
+ var dt;
+ if ( !isCollection( x ) ) {
+ throw new TypeError( format( 'invalid argument. First argument must be an array-like object. Value: `%s`.', x ) );
+ }
+ if ( !isCollection( indices ) ) {
+ throw new TypeError( format( 'invalid argument. Second argument must be an array-like object. Value: `%s`.', indices ) );
+ }
+ opts = defaults();
+ if ( arguments.length > 2 ) {
+ err = validate( opts, arguments[ 2 ] );
+ if ( err ) {
+ throw err;
+ }
+ }
+ dt = dtype( x );
+ if ( dt === 'generic' || dt === null ) {
+ return base( x, indices, opts.mode );
+ }
+ return base.assign( x, indices, opts.mode, zeros( indices.length, dt ), 1, 0 ); // eslint-disable-line max-len
+}
+
+
+// EXPORTS //
+
+module.exports = take;
diff --git a/take/lib/validate.js b/take/lib/validate.js
new file mode 100644
index 00000000..24e7153e
--- /dev/null
+++ b/take/lib/validate.js
@@ -0,0 +1,67 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var isObject = require( '@stdlib/assert/is-plain-object' );
+var hasOwnProp = require( '@stdlib/assert/has-own-property' );
+var isIndexMode = require( '@stdlib/ndarray/base/assert/is-index-mode' );
+var modes = require( '@stdlib/ndarray/index-modes' );
+var format = require( '@stdlib/string/format' );
+
+
+// MAIN //
+
+/**
+* Validates function options.
+*
+* @private
+* @param {Object} opts - destination object
+* @param {Options} options - function options
+* @param {string} [options.mode] - index mode
+* @returns {(Error|null)} null or an error object
+*
+* @example
+* var opts = {};
+* var options = {
+* 'mode': 'normalize'
+* };
+* var err = validate( opts, options );
+* if ( err ) {
+* throw err;
+* }
+*/
+function validate( opts, options ) {
+ if ( !isObject( options ) ) {
+ return new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) );
+ }
+ if ( hasOwnProp( options, 'mode' ) ) {
+ opts.mode = options.mode;
+ if ( !isIndexMode( opts.mode ) ) {
+ return new TypeError( format( 'invalid option. `%s` option must be one of the following: "%s". Option: `%s`.', 'mode', modes().join( '", "' ), opts.mode ) );
+ }
+ }
+ return null;
+}
+
+
+// EXPORTS //
+
+module.exports = validate;
diff --git a/take/package.json b/take/package.json
new file mode 100644
index 00000000..208f4f03
--- /dev/null
+++ b/take/package.json
@@ -0,0 +1,62 @@
+{
+ "name": "@stdlib/array/take",
+ "version": "0.0.0",
+ "description": "Take elements from an array.",
+ "license": "Apache-2.0",
+ "author": {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ },
+ "contributors": [
+ {
+ "name": "The Stdlib Authors",
+ "url": "https://github.com/stdlib-js/stdlib/graphs/contributors"
+ }
+ ],
+ "main": "./lib",
+ "directories": {
+ "benchmark": "./benchmark",
+ "doc": "./docs",
+ "example": "./examples",
+ "lib": "./lib",
+ "test": "./test"
+ },
+ "types": "./docs/types",
+ "scripts": {},
+ "homepage": "https://github.com/stdlib-js/stdlib",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/stdlib-js/stdlib.git"
+ },
+ "bugs": {
+ "url": "https://github.com/stdlib-js/stdlib/issues"
+ },
+ "dependencies": {},
+ "devDependencies": {},
+ "engines": {
+ "node": ">=0.10.0",
+ "npm": ">2.7.0"
+ },
+ "os": [
+ "aix",
+ "darwin",
+ "freebsd",
+ "linux",
+ "macos",
+ "openbsd",
+ "sunos",
+ "win32",
+ "windows"
+ ],
+ "keywords": [
+ "stdlib",
+ "utilities",
+ "utils",
+ "generic",
+ "array",
+ "take",
+ "extract",
+ "copy",
+ "index"
+ ]
+}
diff --git a/take/test/test.js b/take/test/test.js
new file mode 100644
index 00000000..0c6e453c
--- /dev/null
+++ b/take/test/test.js
@@ -0,0 +1,419 @@
+/**
+* @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 toAccessorArray = require( './../../base/to-accessor-array' );
+var isSameComplex64Array = require( '@stdlib/assert/is-same-complex64array' );
+var isArray = require( '@stdlib/assert/is-array' );
+var take = require( './../lib' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof take, '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() {
+ take( 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() {
+ take( 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() {
+ take( [], 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() {
+ take( [], 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() {
+ take( [], [], value );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided a `mode` option which is not a valid index mode', function test( t ) {
+ var values;
+ var i;
+
+ values = [
+ '5',
+ 5,
+ NaN,
+ true,
+ false,
+ null,
+ void 0,
+ [],
+ {},
+ function noop() {}
+ ];
+ for ( i = 0; i < values.length; i++ ) {
+ t.throws( badValue( values[ i ] ), TypeError, 'throws an error when provided ' + values[ i ] );
+ }
+ t.end();
+
+ function badValue( value ) {
+ return function badValue() {
+ take( [], [], {
+ 'mode': value
+ });
+ };
+ }
+});
+
+tape( 'the function takes elements from an array (generic)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ 1, 3 ];
+ actual = take( x, indices );
+
+ expected = [ 2, 4 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 3, 3 ];
+ actual = take( x, indices );
+
+ expected = [ 2, 2, 4, 4 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 3, 2, 1, 0 ];
+ actual = take( x, indices );
+
+ expected = [ 4, 3, 2, 1 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ];
+ actual = take( x, indices );
+
+ expected = [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function takes elements from an array (accessor)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = toAccessorArray( [ 1, 2, 3, 4 ] );
+
+ indices = toAccessorArray( [ 1, 3 ] );
+ actual = take( x, indices );
+
+ expected = [ 2, 4 ];
+ t.strictEqual( isArray( actual ), true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = toAccessorArray( [ 1, 1, 3, 3 ] );
+ actual = take( x, indices );
+
+ expected = [ 2, 2, 4, 4 ];
+ t.strictEqual( isArray( actual ), true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = toAccessorArray( [ 3, 2, 1, 0 ] );
+ actual = take( x, indices );
+
+ expected = [ 4, 3, 2, 1 ];
+ t.strictEqual( isArray( actual ), true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ indices = toAccessorArray( [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] );
+ actual = take( x, indices );
+
+ expected = [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ];
+ t.strictEqual( isArray( actual ), true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function takes elements from an array (complex typed)', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
+
+ indices = toAccessorArray( [ 1, 1, 3 ] );
+ actual = take( x, indices );
+
+ expected = new Complex64Array( [ 3.0, 4.0, 3.0, 4.0, 7.0, 8.0 ] );
+ t.notEqual( actual, x, 'returns different reference' );
+ t.strictEqual( isSameComplex64Array( actual, expected ), true, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function returns an empty array if provided a second argument which is empty', function test( t ) {
+ var x = [ 1, 2, 3, 4 ];
+ t.deepEqual( take( x, [] ), [], 'returns expected value' );
+ t.end();
+});
+
+tape( 'by default, the function normalizes negative indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -1, -2, -3, -4 ];
+ actual = take( x, indices );
+ expected = [ 4, 3, 2, 1 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'by default, the function throws an error if provided an out-of-bounds index', function test( t ) {
+ var indices;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 2, 50, 1, 2 ];
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices );
+ }
+});
+
+tape( 'when the "mode" is "throw", the function throws an error if provided an out-of-bounds index', function test( t ) {
+ var indices;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 4, 5, 1, 2 ];
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, {
+ 'mode': 'throw'
+ });
+ }
+});
+
+tape( 'when the "mode" is "normalize", the function normalizes negative indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -1, -2, -3, -4 ];
+ actual = take( x, indices, {
+ 'mode': 'normalize'
+ });
+ expected = [ 4, 3, 2, 1 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "normalize", the function throws an error if provided an out-of-bounds index', function test( t ) {
+ var indices;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+ indices = [ 2, 50, 1, 2 ];
+
+ t.throws( badValue, RangeError, 'throws an error' );
+ t.end();
+
+ function badValue() {
+ take( x, indices, {
+ 'mode': 'normalize'
+ });
+ }
+});
+
+tape( 'when the "mode" is "clamp", the function clamps out-of-bounds indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -10, 10, -5, 5 ];
+ actual = take( x, indices, {
+ 'mode': 'clamp'
+ });
+ expected = [ 1, 4, 1, 4 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'when the "mode" is "wrap", the function wraps out-of-bounds indices', function test( t ) {
+ var expected;
+ var indices;
+ var actual;
+ var x;
+
+ x = [ 1, 2, 3, 4 ];
+
+ indices = [ -10, 10, -5, 5 ];
+ actual = take( x, indices, {
+ 'mode': 'wrap'
+ });
+ expected = [ 3, 3, 4, 2 ];
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
diff --git a/take/test/test.validate.js b/take/test/test.validate.js
new file mode 100644
index 00000000..5001a5e6
--- /dev/null
+++ b/take/test/test.validate.js
@@ -0,0 +1,128 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var tape = require( 'tape' );
+var validate = require( './../lib/validate.js' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof validate, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function returns an error if not provided an options object', function test( t ) {
+ var values;
+ var err;
+ var i;
+
+ values = [
+ '5',
+ 5,
+ NaN,
+ true,
+ false,
+ null,
+ void 0,
+ [],
+ function noop() {}
+ ];
+
+ for ( i = 0; i < values.length; i++ ) {
+ err = validate( {}, values[i] );
+ t.strictEqual( err instanceof TypeError, true, 'returns an error when provided '+values[i] );
+ }
+ t.end();
+});
+
+tape( 'the function returns an error if provided a `mode` option which is not a valid index mode', function test( t ) {
+ var values;
+ var err;
+ var i;
+
+ values = [
+ '5',
+ 5,
+ NaN,
+ true,
+ false,
+ null,
+ void 0,
+ [],
+ {},
+ function noop() {}
+ ];
+
+ for ( i = 0; i < values.length; i++ ) {
+ err = validate( {}, {
+ 'mode': values[i]
+ });
+ t.strictEqual( err instanceof TypeError, true, 'returns an error when provided '+values[i] );
+ }
+ t.end();
+});
+
+tape( 'the function returns `null` if all options are valid', function test( t ) {
+ var expected;
+ var options;
+ var opts;
+ var err;
+
+ options = {
+ 'mode': 'throw'
+ };
+ opts = {};
+
+ expected = {
+ 'mode': 'throw'
+ };
+
+ err = validate( opts, options );
+
+ t.strictEqual( err, null, 'returns expected value' );
+ t.deepEqual( opts, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function ignores unrecognized options', function test( t ) {
+ var options;
+ var opts;
+ var err;
+
+ options = {
+ 'beep': 'boop',
+ 'foo': 5,
+ 'bar': {}
+ };
+
+ opts = {};
+
+ err = validate( opts, options );
+
+ t.strictEqual( err, null, 'returns expected value' );
+ t.deepEqual( opts, {}, 'returns expected value' );
+
+ t.end();
+});
diff --git a/to-fancy/README.md b/to-fancy/README.md
index ed225622..33fe8605 100644
--- a/to-fancy/README.md
+++ b/to-fancy/README.md
@@ -114,6 +114,7 @@ v = y[ ':' ];
The function supports the following options:
- **strict**: boolean indicating whether to enforce strict bounds checking. Default: `false`.
+- **cache**: cache for resolving array index objects. Default: [`ArrayIndex`][@stdlib/array/index].
By default, the function returns a fancy array which does **not** enforce strict bounds checking. For example,
@@ -137,16 +138,64 @@ var v = y[ 10 ];
// throws
```
+#### array2fancy.factory( \[options] )
+
+Returns a function for converting an array to an object supporting fancy indexing.
+
+```javascript
+var fcn = array2fancy.factory();
+
+var x = [ 1, 2, 3, 4 ];
+
+var y = fcn( x );
+// returns
+
+var v = y[ ':' ];
+// returns [ 1, 2, 3, 4 ]
+```
+
+The function supports the following options:
+
+- **strict**: boolean indicating whether to enforce strict bounds checking by default. Default: `false`.
+- **cache**: cache for resolving array index objects. Default: [`ArrayIndex`][@stdlib/array/index].
+
+By default, the function returns a function which, by default, does **not** enforce strict bounds checking. For example,
+
+```javascript
+var fcn = array2fancy.factory();
+
+var y = fcn( [ 1, 2, 3, 4 ] );
+
+var v = y[ 10 ];
+// returns undefined
+```
+
+To enforce strict bounds checking by default, set the `strict` option to `true`.
+
+
+
+```javascript
+var fcn = array2fancy.factory({
+ 'strict': true
+});
+var y = fcn( [ 1, 2, 3, 4 ] );
+
+var v = y[ 10 ];
+// throws
+```
+
+The returned function supports the same options as above. When the returned function is provided option values, those values override the factory method defaults.
+
-
-
* * *
+
+
## Notes
- A fancy array shares the **same** data as the provided input array. Hence, any mutations to the returned array will affect the underlying input array and vice versa.
@@ -313,10 +362,10 @@ y[ ':' ] = new Float64Array( [ 5.0, 6.0 ] ); // is this a single complex number
-
-
* * *
+
+
## Examples
@@ -388,6 +437,8 @@ z = y[ ':' ];
[@stdlib/array/complex64]: https://github.com/stdlib-js/array/tree/main/complex64
+[@stdlib/array/index]: https://github.com/stdlib-js/array/tree/main/index
+
diff --git a/to-fancy/benchmark/benchmark.factory.js b/to-fancy/benchmark/benchmark.factory.js
new file mode 100644
index 00000000..d1dd1a91
--- /dev/null
+++ b/to-fancy/benchmark/benchmark.factory.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';
+
+// MODULES //
+
+var bench = require( '@stdlib/bench' );
+var isFunction = require( '@stdlib/assert/is-function' );
+var pkg = require( './../package.json' ).name;
+var array2fancy = require( './../lib' );
+
+
+// MAIN //
+
+bench( pkg+':factory', function benchmark( b ) {
+ var v;
+ var i;
+
+ b.tic();
+ for ( i = 0; i < b.iterations; i++ ) {
+ v = array2fancy.factory();
+ if ( typeof v !== 'function' ) {
+ b.fail( 'should return a function' );
+ }
+ }
+ b.toc();
+ if ( !isFunction( v ) ) {
+ b.fail( 'should return a function' );
+ }
+ b.pass( 'benchmark finished' );
+ b.end();
+});
diff --git a/to-fancy/docs/repl.txt b/to-fancy/docs/repl.txt
index a4ed2de2..1481081f 100644
--- a/to-fancy/docs/repl.txt
+++ b/to-fancy/docs/repl.txt
@@ -69,6 +69,19 @@
Boolean indicating whether to enforce strict bounds checking. Default:
false.
+ options.cache: Object (optional)
+ Cache for resolving array index objects. Must have a 'get' method which
+ accepts a single argument: an identifier associated with an array index.
+ If an array index associated with a provided identifier exists, the
+ 'get' method should return an object having the following properties:
+
+ - data: the underlying index array.
+ - type: the index type. Must be either 'mask', 'bool', or 'int'.
+ - dtype: the data type of the underlying array.
+
+ If an array index is not associated with a provided identifier, the
+ 'get' method should return `null`.
+
Returns
-------
out: Array|TypedArray|Object
@@ -82,6 +95,47 @@
> y[ '::-1' ]
[ 4, 3, 2, 1 ]
+
+{{alias}}.factory( [options] )
+ Returns a function for converting an array to an object supporting fancy
+ indexing.
+
+ Parameters
+ ----------
+ options: Object (optional)
+ Function options.
+
+ options.strict: boolean (optional)
+ Boolean indicating whether to enforce strict bounds checking by default.
+ Default: false.
+
+ options.cache: Object (optional)
+ Cache for resolving array index objects. Must have a 'get' method which
+ accepts a single argument: an identifier associated with an array index.
+ If an array index associated with a provided identifier exists, the
+ 'get' method should return an object having the following properties:
+
+ - data: the underlying index array.
+ - type: the index type. Must be either 'mask', 'bool', or 'int'.
+ - dtype: the data type of the underlying array.
+
+ If an array index is not associated with a provided identifier, the
+ 'get' method should return `null`.
+
+ Returns
+ -------
+ fcn: Function
+ Function for converting an array to an object supporting fancy indexing.
+
+ Examples
+ --------
+ > var f = {{alias}}.factory();
+ > var y = f( [ 1, 2, 3, 4 ] );
+ > y[ '1::2' ]
+ [ 2, 4 ]
+ > y[ '::-1' ]
+ [ 4, 3, 2, 1 ]
+
See Also
--------
diff --git a/to-fancy/docs/types/index.d.ts b/to-fancy/docs/types/index.d.ts
index 33348510..2cd4da18 100644
--- a/to-fancy/docs/types/index.d.ts
+++ b/to-fancy/docs/types/index.d.ts
@@ -20,311 +20,410 @@
///
-import { Collection, ArrayLike, AccessorArrayLike, Complex128Array, Complex64Array } from '@stdlib/types/array';
+import { Collection, ArrayLike, AccessorArrayLike, Complex128Array, Complex64Array, DataType } from '@stdlib/types/array';
/**
-* Interface defining function options.
+* Interface describing an index object.
*/
-interface Options {
+interface IndexObject {
/**
- * Boolean indicating whether to enforce strict bounds checking (default: false).
+ * Underlying array index data.
*/
- strict?: boolean;
+ data: Collection | AccessorArrayLike;
+
+ /**
+ * Index type.
+ */
+ type: 'mask' | 'bool' | 'int';
+
+ /**
+ * Underlying array data type.
+ */
+ dtype: DataType | null;
}
/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Float64Array = require( '@stdlib/array/float64' );
-*
-* var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1.0, 2.0, 3.0, 4.0 ]
+* Interface describing a cache for resolving array index objects.
*/
-declare function array2fancy( x: Float64Array, options?: Options ): Float64Array;
+interface Cache {
+ /**
+ * Returns an array associated with the index object having a provided identifier.
+ *
+ * @param id - identifier
+ * @returns index data
+ */
+ get( id: any ): IndexObject | null;
+}
/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Float32Array = require( '@stdlib/array/float32' );
-*
-* var x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1.0, 2.0, 3.0, 4.0 ]
+* Interface describing function options.
*/
-declare function array2fancy( x: Float32Array, options?: Options ): Float32Array;
+interface Options {
+ /**
+ * Boolean indicating whether to enforce strict bounds checking.
+ */
+ strict?: boolean;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Complex128Array = require( '@stdlib/array/complex128' );
-*
-* var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1.0, 2.0, 3.0, 4.0 ]
-*/
-declare function array2fancy( x: Complex128Array, options?: Options ): Complex128Array;
+ /**
+ * Cache for resolving array index objects.
+ */
+ cache?: Cache;
+}
/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Complex64Array = require( '@stdlib/array/complex64' );
-*
-* var x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1.0, 2.0, 3.0, 4.0 ]
+* Interface describing the main export.
*/
-declare function array2fancy( x: Complex64Array, options?: Options ): Complex64Array;
+interface Array2Fancy {
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Float64Array = require( './../../../float64' );
+ *
+ * var x = new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1.0, 2.0, 3.0, 4.0 ]
+ */
+ ( x: Float64Array, options?: Options ): Float64Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Int32Array = require( '@stdlib/array/int32' );
-*
-* var x = new Int32Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Int32Array, options?: Options ): Int32Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Float32Array = require( './../../../float32' );
+ *
+ * var x = new Float32Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1.0, 2.0, 3.0, 4.0 ]
+ */
+ ( x: Float32Array, options?: Options ): Float32Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Int16Array = require( '@stdlib/array/int16' );
-*
-* var x = new Int16Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Int16Array, options?: Options ): Int16Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Complex128Array = require( './../../../complex128' );
+ *
+ * var x = new Complex128Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1.0, 2.0, 3.0, 4.0 ]
+ */
+ ( x: Complex128Array, options?: Options ): Complex128Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Int8Array = require( '@stdlib/array/int8' );
-*
-* var x = new Int8Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Int8Array, options?: Options ): Int8Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Complex64Array = require( './../../../complex64' );
+ *
+ * var x = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1.0, 2.0, 3.0, 4.0 ]
+ */
+ ( x: Complex64Array, options?: Options ): Complex64Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Uint32Array = require( '@stdlib/array/uint32' );
-*
-* var x = new Uint32Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Uint32Array, options?: Options ): Uint32Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Int32Array = require( './../../../int32' );
+ *
+ * var x = new Int32Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Int32Array, options?: Options ): Int32Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Uint16Array = require( '@stdlib/array/uint16' );
-*
-* var x = new Uint16Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Uint16Array, options?: Options ): Uint16Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Int16Array = require( './../../../int16' );
+ *
+ * var x = new Int16Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Int16Array, options?: Options ): Int16Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Uint8Array = require( '@stdlib/array/uint8' );
-*
-* var x = new Uint8Array( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Uint8Array, options?: Options ): Uint8Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Int8Array = require( './../../../int8' );
+ *
+ * var x = new Int8Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Int8Array, options?: Options ): Int8Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var Uint8ClampedArray = require( '@stdlib/array/uint8c' );
-*
-* var x = new Uint8ClampedArray( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Uint8ClampedArray, options?: Options ): Uint8ClampedArray;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Uint32Array = require( './../../../uint32' );
+ *
+ * var x = new Uint32Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Uint32Array, options?: Options ): Uint32Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var x = [ 1, 2, 3, 4 ];
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Array, options?: Options ): Array;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Uint16Array = require( './../../../uint16' );
+ *
+ * var x = new Uint16Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Uint16Array, options?: Options ): Uint16Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
-*
-* var x = toAccessorArray( [ 1, 2, 3, 4 ] );
-*
-* var y = array2fancy( x );
-* var v = y[ ':' ];
-*/
-declare function array2fancy( x: AccessorArrayLike, options?: Options ): AccessorArrayLike;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Uint8Array = require( './../../../uint8' );
+ *
+ * var x = new Uint8Array( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Uint8Array, options?: Options ): Uint8Array;
-/**
-* Converts an array to an object supporting fancy indexing.
-*
-* @param x - input array
-* @param options - function options
-* @param options.strict - boolean indicating whether to enforce strict bounds checking
-* @returns fancy array
-*
-* @example
-* var x = [ 1, 2, 3, 4 ];
-*
-* var y = array2fancy( x );
-* // returns
-*
-* var v = y[ ':' ];
-* // returns [ 1, 2, 3, 4 ]
-*/
-declare function array2fancy( x: Collection, options?: Options ): Collection;
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var Uint8ClampedArray = require( './../../../uint8c' );
+ *
+ * var x = new Uint8ClampedArray( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Uint8ClampedArray, options?: Options ): Uint8ClampedArray;
+
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Array, options?: Options ): Array;
+
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var toAccessorArray = require( './../../../base/to-accessor-array' );
+ *
+ * var x = toAccessorArray( [ 1, 2, 3, 4 ] );
+ *
+ * var y = array2fancy( x );
+ * var v = y[ ':' ];
+ */
+ ( x: AccessorArrayLike, options?: Options ): AccessorArrayLike;
+
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: Collection, options?: Options ): Collection;
+
+ /**
+ * Converts an array-like value to an object supporting fancy indexing.
+ *
+ * @param x - input array
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking
+ * @param options.cache - cache for resolving array index objects
+ * @returns fancy array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ ( x: ArrayLike, options?: Options ): ArrayLike;
+
+ /**
+ * Returns a function for converting an array to an object supporting fancy indexing.
+ *
+ * @param options - function options
+ * @param options.strict - boolean indicating whether to enforce strict bounds checking by default
+ * @param options.cache - cache for resolving array index objects
+ * @returns function for converting an array to an object supporting fancy indexing
+ *
+ * @example
+ * var fcn = array2fancy.factory();
+ *
+ * var x = [ 1, 2, 3, 4 ];
+ *
+ * var y = fcn( x );
+ * // returns
+ *
+ * var v = y[ ':' ];
+ * // returns [ 1, 2, 3, 4 ]
+ */
+ factory( options?: Options ): Array2Fancy;
+}
/**
-* Converts an array-like value to an object supporting fancy indexing.
+* Converts an array to an object supporting fancy indexing.
*
* @param x - input array
* @param options - function options
* @param options.strict - boolean indicating whether to enforce strict bounds checking
+* @param options.cache - cache for resolving array index objects
* @returns fancy array
*
* @example
@@ -336,7 +435,7 @@ declare function array2fancy( x: Collection, options?: Options )
* var v = y[ ':' ];
* // returns [ 1, 2, 3, 4 ]
*/
-declare function array2fancy( x: ArrayLike, options?: Options ): ArrayLike;
+declare var array2fancy: Array2Fancy;
// EXPORTS //
diff --git a/to-fancy/docs/types/test.ts b/to-fancy/docs/types/test.ts
index 2996e4f5..658d18b0 100644
--- a/to-fancy/docs/types/test.ts
+++ b/to-fancy/docs/types/test.ts
@@ -97,8 +97,67 @@ import array2fancy = require( './index' );
array2fancy( x, { 'strict': ( x: number ): number => x } ); // $ExpectError
}
+// The compiler throws an error if the function is provided a `cache` option which is not valid...
+{
+ const x = [ 1, 2, 3, 4 ];
+
+ array2fancy( x, { 'cache': '5' } ); // $ExpectError
+ array2fancy( x, { 'cache': 5 } ); // $ExpectError
+ array2fancy( x, { 'cache': true } ); // $ExpectError
+ array2fancy( x, { 'cache': false } ); // $ExpectError
+ array2fancy( x, { 'cache': null } ); // $ExpectError
+ array2fancy( x, { 'cache': [] } ); // $ExpectError
+ array2fancy( x, { 'cache': {} } ); // $ExpectError
+ array2fancy( x, { 'cache': ( x: number ): number => x } ); // $ExpectError
+}
+
// The compiler throws an error if the function is provided an unsupported number of arguments...
{
array2fancy(); // $ExpectError
array2fancy( [ 1, 2, 3 ], {}, {} ); // $ExpectError
}
+
+// Attached to the function is a `factory` method which returns a function...
+{
+ array2fancy.factory(); // $ExpectType Array2Fancy
+ array2fancy.factory( {} ); // $ExpectType Array2Fancy
+ array2fancy.factory( { 'strict': true } ); // $ExpectType Array2Fancy
+}
+
+// The compiler throws an error if the `factory` method is provided a second argument which is not an object...
+{
+ array2fancy.factory( '5' ); // $ExpectError
+ array2fancy.factory( 5 ); // $ExpectError
+ array2fancy.factory( true ); // $ExpectError
+ array2fancy.factory( false ); // $ExpectError
+ array2fancy.factory( null ); // $ExpectError
+ array2fancy.factory( [] ); // $ExpectError
+ array2fancy.factory( ( x: number ): number => x ); // $ExpectError
+}
+
+// The compiler throws an error if the `factory` method is provided a `strict` option which is not a boolean...
+{
+ array2fancy.factory( { 'strict': '5' } ); // $ExpectError
+ array2fancy.factory( { 'strict': 5 } ); // $ExpectError
+ array2fancy.factory( { 'strict': null } ); // $ExpectError
+ array2fancy.factory( { 'strict': [] } ); // $ExpectError
+ array2fancy.factory( { 'strict': {} } ); // $ExpectError
+ array2fancy.factory( { 'strict': ( x: number ): number => x } ); // $ExpectError
+}
+
+// The compiler throws an error if the `factory` method is provided a `cache` option which is not valid...
+{
+ array2fancy.factory( { 'cache': '5' } ); // $ExpectError
+ array2fancy.factory( { 'cache': 5 } ); // $ExpectError
+ array2fancy.factory( { 'cache': true } ); // $ExpectError
+ array2fancy.factory( { 'cache': false } ); // $ExpectError
+ array2fancy.factory( { 'cache': null } ); // $ExpectError
+ array2fancy.factory( { 'cache': [] } ); // $ExpectError
+ array2fancy.factory( { 'cache': {} } ); // $ExpectError
+ array2fancy.factory( { 'cache': ( x: number ): number => x } ); // $ExpectError
+}
+
+// The compiler throws an error if the `factory` method is provided an unsupported number of arguments...
+{
+ array2fancy.factory( {}, {} ); // $ExpectError
+}
diff --git a/to-fancy/lib/defaults.js b/to-fancy/lib/defaults.js
index 6776a3a8..f9ef5cf8 100644
--- a/to-fancy/lib/defaults.js
+++ b/to-fancy/lib/defaults.js
@@ -18,6 +18,11 @@
'use strict';
+// MODULES //
+
+var ArrayIndex = require( './../../index' );
+
+
// MAIN //
/**
@@ -32,6 +37,7 @@
*/
function defaults() {
return {
+ 'cache': ArrayIndex,
'strict': false
};
}
diff --git a/to-fancy/lib/factory.js b/to-fancy/lib/factory.js
new file mode 100644
index 00000000..21db01df
--- /dev/null
+++ b/to-fancy/lib/factory.js
@@ -0,0 +1,169 @@
+/**
+* @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 isArrayLike = require( '@stdlib/assert/is-array-like' );
+var Proxy = require( '@stdlib/proxy/ctor' );
+var arraylike2object = require( './../../base/arraylike2object' );
+var assign = require( '@stdlib/object/assign' );
+var format = require( '@stdlib/string/format' );
+var setElementWrapper = require( './set_element_wrapper.js' );
+var getSliceWrapper = require( './get_slice_wrapper.js' );
+var hasProxySupport = require( './has_proxy_support.js' );
+var defaults = require( './defaults.js' );
+var validate = require( './validate.js' );
+var validator = require( './validator.js' );
+var ctor = require( './ctor.js' );
+var get = require( './get.js' );
+var set = require( './set.js' );
+
+
+// MAIN //
+
+/**
+* Returns a function for converting an array to an object supporting fancy indexing.
+*
+* @param {Options} options - function options
+* @param {boolean} [options.strict=false] - boolean indicating whether to enforce strict bounds checking by default
+* @param {Function} [options.cache] - default cache for resolving array index objects
+* @throws {TypeError} options argument must be an object
+* @throws {TypeError} must provide valid options
+* @returns {Function} function for converting an array to an object supporting fancy indexing
+*
+* @example
+* var array2fancy = factory();
+*
+* var x = [ 1, 2, 3, 4, 5, 6 ];
+*
+* var y = array2fancy( x );
+* // returns
+*
+* var z = y[ '1::2' ];
+* // returns [ 2, 4, 6 ]
+*
+* var len = z.length;
+* // returns 3
+*
+* var v = z[ 0 ];
+* // returns 2
+*
+* v = z[ 1 ];
+* // returns 4
+*
+* v = z[ 2 ];
+* // returns 6
+*/
+function factory() {
+ var OPTIONS;
+ var err;
+
+ OPTIONS = defaults();
+ if ( arguments.length ) {
+ err = validate( OPTIONS, arguments[ 0 ] );
+ if ( err ) {
+ throw err;
+ }
+ }
+ return array2fancy;
+
+ /**
+ * Converts an array to an object supporting fancy indexing.
+ *
+ * @private
+ * @param {ArrayLike} x - input array
+ * @param {Options} [options] - function options
+ * @param {boolean} [options.strict] - boolean indicating whether to enforce strict bounds checking
+ * @param {Function} [options.cache] - cache for resolving array index objects
+ * @throws {TypeError} first argument must be array-like
+ * @throws {TypeError} options argument must be an object
+ * @throws {TypeError} must provide valid options
+ * @returns {ArrayLike} fancy array
+ *
+ * @example
+ * var x = [ 1, 2, 3, 4, 5, 6 ];
+ *
+ * var y = array2fancy( x );
+ * // returns
+ *
+ * var z = y[ '1::2' ];
+ * // returns [ 2, 4, 6 ]
+ *
+ * var len = z.length;
+ * // returns 3
+ *
+ * var v = z[ 0 ];
+ * // returns 2
+ *
+ * v = z[ 1 ];
+ * // returns 4
+ *
+ * v = z[ 2 ];
+ * // returns 6
+ */
+ function array2fancy( x ) {
+ var opts;
+ var err;
+ var arr;
+ var dt;
+ var o;
+ if ( !isArrayLike( x ) ) {
+ throw new TypeError( format( 'invalid argument. First argument must be array-like. Value: `%s`.', x ) );
+ }
+ if ( hasProxySupport ) {
+ opts = assign( {}, OPTIONS );
+ if ( arguments.length > 1 ) {
+ err = validate( opts, arguments[ 1 ] );
+ if ( err ) {
+ throw err;
+ }
+ }
+ arr = arraylike2object( x );
+ dt = arr.dtype || '';
+ o = {
+ 'ref': x,
+ 'dtype': dt,
+ 'getter': arr.accessors[ 0 ],
+ 'setter': arr.accessors[ 1 ],
+ 'preSetElement': setElementWrapper( dt ),
+ 'postGetSlice': getSliceWrapper( array2fancy, opts ),
+ 'cache': opts.cache,
+ 'strict': opts.strict,
+ 'validator': validator( dt ),
+ 'array2fancy': array2fancy,
+ 'ctor': new Proxy( x.constructor || Array, {
+ 'construct': ctor( array2fancy, opts )
+ })
+ };
+ return new Proxy( x, {
+ 'get': get( o ),
+ 'set': set( o )
+ });
+ }
+ // TODO: replace with `@stdlib/console/warn` (or equivalent once available)
+ console.warn( 'WARNING: Proxy objects are not supported in the current environment. Some `FancyArray` functionality may not be available.' ); // eslint-disable-line no-console
+ return x;
+ }
+}
+
+
+// EXPORTS //
+
+module.exports = factory;
diff --git a/to-fancy/lib/index.js b/to-fancy/lib/index.js
index f862cfc6..72229b29 100644
--- a/to-fancy/lib/index.js
+++ b/to-fancy/lib/index.js
@@ -49,7 +49,14 @@
// MODULES //
+var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
var main = require( './main.js' );
+var factory = require( './factory.js' );
+
+
+// MAIN //
+
+setReadOnly( main, 'factory', factory );
// EXPORTS //
diff --git a/to-fancy/lib/main.js b/to-fancy/lib/main.js
index 3fe0bca8..024e7a74 100644
--- a/to-fancy/lib/main.js
+++ b/to-fancy/lib/main.js
@@ -20,19 +20,7 @@
// MODULES //
-var isArrayLike = require( '@stdlib/assert/is-array-like' );
-var Proxy = require( '@stdlib/proxy/ctor' );
-var arraylike2object = require( './../../base/arraylike2object' );
-var format = require( '@stdlib/string/format' );
-var setElementWrapper = require( './set_element_wrapper.js' );
-var getSliceWrapper = require( './get_slice_wrapper.js' );
-var hasProxySupport = require( './has_proxy_support.js' );
-var defaults = require( './defaults.js' );
-var validate = require( './validate.js' );
-var validator = require( './validator.js' );
-var ctor = require( './ctor.js' );
-var get = require( './get.js' );
-var set = require( './set.js' );
+var factory = require( './factory.js' );
// MAIN //
@@ -40,9 +28,12 @@ var set = require( './set.js' );
/**
* Converts an array to an object supporting fancy indexing.
*
+* @name array2fancy
+* @type {Function}
* @param {ArrayLike} x - input array
* @param {Options} [options] - function options
* @param {boolean} [options.strict=false] - boolean indicating whether to enforce strict bounds checking
+* @param {Function} [options.cache] - cache for resolving array index objects
* @throws {TypeError} first argument must be array-like
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
@@ -69,48 +60,7 @@ var set = require( './set.js' );
* v = z[ 2 ];
* // returns 6
*/
-function array2fancy( x ) {
- var opts;
- var err;
- var arr;
- var dt;
- var o;
- if ( !isArrayLike( x ) ) {
- throw new TypeError( format( 'invalid argument. First argument must be array-like. Value: `%s`.', x ) );
- }
- if ( hasProxySupport ) {
- opts = defaults();
- if ( arguments.length > 1 ) {
- err = validate( opts, arguments[ 1 ] );
- if ( err ) {
- throw err;
- }
- }
- arr = arraylike2object( x );
- dt = arr.dtype || '';
- o = {
- 'ref': x,
- 'dtype': dt,
- 'getter': arr.accessors[ 0 ],
- 'setter': arr.accessors[ 1 ],
- 'preSetElement': setElementWrapper( dt ),
- 'postGetSlice': getSliceWrapper( array2fancy, opts ),
- 'strict': opts.strict,
- 'validator': validator( dt ),
- 'array2fancy': array2fancy,
- 'ctor': new Proxy( x.constructor || Array, {
- 'construct': ctor( array2fancy, opts )
- })
- };
- return new Proxy( x, {
- 'get': get( o ),
- 'set': set( o )
- });
- }
- // TODO: replace with `@stdlib/console/warn` (or equivalent once available)
- console.warn( 'WARNING: Proxy objects are not supported in the current environment. Some `FancyArray` functionality may not be available.' ); // eslint-disable-line no-console
- return x;
-}
+var array2fancy = factory();
// EXPORTS //
diff --git a/to-fancy/lib/validate.js b/to-fancy/lib/validate.js
index 6f0ef77c..84510e40 100644
--- a/to-fancy/lib/validate.js
+++ b/to-fancy/lib/validate.js
@@ -23,6 +23,7 @@
var isObject = require( '@stdlib/assert/is-plain-object' );
var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
+var isMethodIn = require( '@stdlib/assert/is-method-in' );
var format = require( '@stdlib/string/format' );
@@ -35,6 +36,7 @@ var format = require( '@stdlib/string/format' );
* @param {Object} opts - destination object
* @param {Options} options - function options
* @param {boolean} [options.strict] - boolean indicating whether to enforce strict bounds checking
+* @param {Function} [options.cache] - cache for resolving array index objects
* @returns {(Error|null)} null or an error object
*
* @example
@@ -57,6 +59,12 @@ function validate( opts, options ) {
return new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'strict', opts.strict ) );
}
}
+ if ( hasOwnProp( options, 'cache' ) ) {
+ opts.cache = options.cache;
+ if ( !isMethodIn( opts.cache, 'get' ) ) {
+ return new TypeError( format( 'invalid option. `%s` option is missing a `%s` method. Option: `%s`.', 'cache', 'get', opts.cache ) );
+ }
+ }
return null;
}
diff --git a/to-fancy/test/test.factory.js b/to-fancy/test/test.factory.js
new file mode 100644
index 00000000..2410bfd8
--- /dev/null
+++ b/to-fancy/test/test.factory.js
@@ -0,0 +1,143 @@
+/**
+* @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 proxyquire = require( 'proxyquire' );
+var Int32Array = require( './../../int32' );
+var factory = require( './../lib/factory.js' );
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof factory, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function throws an error if provided a first 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() {
+ factory( value );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid option', function test( t ) {
+ var values;
+ var i;
+
+ values = [
+ '5',
+ 5,
+ NaN,
+ 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() {
+ factory({
+ 'strict': value
+ });
+ };
+ }
+});
+
+tape( 'the function returns a function which returns an array-like object', function test( t ) {
+ var array2fancy;
+ var x;
+ var y;
+
+ array2fancy = factory();
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ t.strictEqual( y instanceof Array, true, 'returns expected value' );
+ t.notEqual( y, x, 'different reference' );
+ t.deepEqual( y, x, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'if an environment does not support Proxy objects, the function returns a function which returns the input array (generic)', function test( t ) {
+ var array2fancy;
+ var factory;
+ var x;
+ var y;
+
+ factory = proxyquire( './../lib/factory.js', {
+ './has_proxy_support.js': false
+ });
+ array2fancy = factory();
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ t.strictEqual( y, x, 'returns expected value' );
+ t.end();
+});
+
+tape( 'if an environment does not support Proxy objects, the function returns a function which returns the input array (typed)', function test( t ) {
+ var array2fancy;
+ var factory;
+ var x;
+ var y;
+
+ factory = proxyquire( './../lib/factory.js', {
+ './has_proxy_support.js': false
+ });
+ array2fancy = factory();
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ t.strictEqual( y, x, 'returns expected value' );
+ t.end();
+});
diff --git a/to-fancy/test/test.js b/to-fancy/test/test.js
index 71ea5060..be5024e7 100644
--- a/to-fancy/test/test.js
+++ b/to-fancy/test/test.js
@@ -21,20 +21,10 @@
// MODULES //
var tape = require( 'tape' );
-var proxyquire = require( 'proxyquire' );
-var hasProxySupport = require( '@stdlib/assert/has-proxy-support' );
-var Int32Array = require( './../../int32' );
-var propertiesIn = require( '@stdlib/utils/properties-in' );
+var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var array2fancy = require( './../lib' );
-// VARIABLES //
-
-var opts = {
- 'skip': !hasProxySupport()
-};
-
-
// TESTS //
tape( 'main export is a function', function test( t ) {
@@ -43,396 +33,8 @@ tape( 'main export is a function', function test( t ) {
t.end();
});
-tape( 'the function throws an error if provided a first argument which is not an array-like value', function test( t ) {
- var values;
- var i;
-
- values = [
- 5,
- NaN,
- true,
- false,
- null,
- void 0,
- {}
- ];
- 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() {
- array2fancy( value );
- };
- }
-});
-
-tape( 'the function throws an error if provided a first argument which is not an array-like value (options)', function test( t ) {
- var values;
- var i;
-
- values = [
- 5,
- NaN,
- true,
- false,
- null,
- void 0,
- {}
- ];
- 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() {
- array2fancy( value, {} );
- };
- }
-});
-
-tape( 'the function throws an error if provided a second 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() {
- array2fancy( [ 1, 2, 3 ], value );
- };
- }
-});
-
-tape( 'the function throws an error if provided an invalid option', function test( t ) {
- var values;
- var i;
-
- values = [
- '5',
- 5,
- NaN,
- 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() {
- array2fancy( [ 1, 2, 3 ], {
- 'strict': value
- });
- };
- }
-});
-
-tape( 'if an environment does not support Proxy objects, the function returns the input array (generic)', function test( t ) {
- var array2fancy;
- var x;
- var y;
-
- array2fancy = proxyquire( './../lib/main.js', {
- './has_proxy_support.js': false
- });
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- t.strictEqual( y, x, 'returns expected value' );
- t.end();
-});
-
-tape( 'if an environment does not support Proxy objects, the function returns the input array (typed)', function test( t ) {
- var array2fancy;
- var x;
- var y;
-
- array2fancy = proxyquire( './../lib/main.js', {
- './has_proxy_support.js': false
- });
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- t.strictEqual( y, x, 'returns expected value' );
- t.end();
-});
-
-tape( 'the function returns an array-like object which satisfies the same instance check (generic)', function test( t ) {
- var x;
- var y;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- t.notEqual( y, x, 'different reference' );
- t.strictEqual( y instanceof Array, true, 'returns expected value' );
- t.end();
-});
-
-tape( 'the function returns an array-like object which satisfies the same instance check (typed)', function test( t ) {
- var x;
- var y;
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- t.notEqual( y, x, 'different reference' );
- t.strictEqual( y instanceof Int32Array, true, 'returns expected value' );
- t.end();
-});
-
-tape( 'the function returns an array-like object having the same properties, both own and inherited, as the input array (generic)', function test( t ) {
- var x;
- var y;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- t.deepEqual( propertiesIn( y ), propertiesIn( x ), 'returns expected value' );
- t.end();
-});
-
-tape( 'the function returns an array-like object having the same properties, both own and inherited, as the input array (typed)', function test( t ) {
- var x;
- var y;
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- t.deepEqual( propertiesIn( y ), propertiesIn( x ), 'returns expected value' );
- t.end();
-});
-
-tape( 'the function returns an array-like object supporting bracket syntax for element retrieval (generic)', function test( t ) {
- var x;
- var y;
- var i;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- for ( i = 0; i < x.length; i++ ) {
- t.strictEqual( y[ i ], x[ i ], 'returns expected value' );
- }
- t.end();
-});
-
-tape( 'the function returns an array-like object supporting bracket syntax for element retrieval (typed)', function test( t ) {
- var x;
- var y;
- var i;
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- for ( i = 0; i < x.length; i++ ) {
- t.strictEqual( y[ i ], x[ i ], 'returns expected value' );
- }
- t.end();
-});
-
-tape( 'the function returns an array-like object supporting the calling of input array methods (generic)', function test( t ) {
- var expected;
- var actual;
- var x;
- var y;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- expected = [ 2, 4, 6, 8 ];
- actual = y.map( fcn );
-
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
- t.end();
-
- function fcn( v ) {
- return v * 2;
- }
-});
-
-tape( 'the function returns an array-like object supporting the calling of input array methods (typed)', function test( t ) {
- var expected;
- var actual;
- var x;
- var y;
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- expected = new Int32Array( [ 2, 4, 6, 8 ] );
- actual = y.map( fcn );
-
- t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
- t.end();
-
- function fcn( v ) {
- return v * 2;
- }
-});
-
-tape( 'the function returns an array-like object supporting the return of array instances supporting slice expressions (generic)', opts, function test( t ) {
- var expected;
- var actual;
- var x;
- var y;
- var z;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- expected = [ 1, 2, 3, 4 ];
- actual = y.slice();
-
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- t.strictEqual( x[ ':' ], void 0, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4 ];
- actual = y[ ':' ];
-
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- z = actual;
-
- expected = [ 1, 2, 3, 4 ];
- actual = z[ ':' ];
-
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- t.end();
-});
-
-tape( 'the function returns an array-like object supporting the return of array instances supporting slice expressions (typed)', opts, function test( t ) {
- var expected;
- var actual;
- var x;
- var y;
- var z;
-
- x = new Int32Array( [ 1, 2, 3, 4 ] );
- y = array2fancy( x );
-
- expected = new Int32Array( [ 1, 2, 3, 4 ] );
- actual = y.slice();
-
- t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- t.strictEqual( x[ ':' ], void 0, 'returns expected value' );
-
- expected = new Int32Array( [ 1, 2, 3, 4 ] );
- actual = y[ ':' ];
-
- t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- z = actual;
-
- expected = new Int32Array( [ 1, 2, 3, 4 ] );
- actual = z[ ':' ];
-
- t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- t.end();
-});
-
-tape( 'the function returns an array-like object supporting constructor access (generic)', function test( t ) {
- var expected;
- var actual;
- var x;
- var y;
-
- x = [ 1, 2, 3, 4 ];
- y = array2fancy( x );
-
- expected = [];
- actual = new y.constructor();
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- actual = new y.constructor( 1 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.strictEqual( actual.length, 1, 'returns expected value' );
-
- expected = [ 1, 2 ];
- actual = new y.constructor( 1, 2 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3 ];
- actual = new y.constructor( 1, 2, 3 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4 ];
- actual = new y.constructor( 1, 2, 3, 4 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5 ];
- actual = new y.constructor( 1, 2, 3, 4, 5 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6, 7 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
- expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
- actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 );
- t.strictEqual( actual instanceof Array, true, 'returns expected value' );
- t.deepEqual( actual, expected, 'returns expected value' );
-
+tape( 'attached to the main export is a `factory` method', function test( t ) {
+ t.strictEqual( hasOwnProp( array2fancy, 'factory' ), true, 'has property' );
+ t.strictEqual( typeof array2fancy.factory, 'function', 'has method' );
t.end();
});
diff --git a/to-fancy/test/test.main.js b/to-fancy/test/test.main.js
new file mode 100644
index 00000000..4f332687
--- /dev/null
+++ b/to-fancy/test/test.main.js
@@ -0,0 +1,405 @@
+/**
+* @license Apache-2.0
+*
+* Copyright (c) 2024 The Stdlib Authors.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+'use strict';
+
+// MODULES //
+
+var tape = require( 'tape' );
+var hasProxySupport = require( '@stdlib/assert/has-proxy-support' );
+var Int32Array = require( './../../int32' );
+var propertiesIn = require( '@stdlib/utils/properties-in' );
+var array2fancy = require( './../lib' );
+
+
+// VARIABLES //
+
+var opts = {
+ 'skip': !hasProxySupport()
+};
+
+
+// TESTS //
+
+tape( 'main export is a function', function test( t ) {
+ t.ok( true, __filename );
+ t.strictEqual( typeof array2fancy, 'function', 'main export is a function' );
+ t.end();
+});
+
+tape( 'the function throws an error if provided a first argument which is not an array-like value', function test( t ) {
+ var values;
+ var i;
+
+ values = [
+ 5,
+ NaN,
+ true,
+ false,
+ null,
+ void 0,
+ {}
+ ];
+ 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() {
+ array2fancy( value );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided a first argument which is not an array-like value (options)', function test( t ) {
+ var values;
+ var i;
+
+ values = [
+ 5,
+ NaN,
+ true,
+ false,
+ null,
+ void 0,
+ {}
+ ];
+ 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() {
+ array2fancy( value, {} );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided a second 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() {
+ array2fancy( [ 1, 2, 3 ], value );
+ };
+ }
+});
+
+tape( 'the function throws an error if provided an invalid option', function test( t ) {
+ var values;
+ var i;
+
+ values = [
+ '5',
+ 5,
+ NaN,
+ 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() {
+ array2fancy( [ 1, 2, 3 ], {
+ 'strict': value
+ });
+ };
+ }
+});
+
+tape( 'the function returns an array-like object which satisfies the same instance check (generic)', function test( t ) {
+ var x;
+ var y;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ t.notEqual( y, x, 'different reference' );
+ t.strictEqual( y instanceof Array, true, 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function returns an array-like object which satisfies the same instance check (typed)', function test( t ) {
+ var x;
+ var y;
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ t.notEqual( y, x, 'different reference' );
+ t.strictEqual( y instanceof Int32Array, true, 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function returns an array-like object having the same properties, both own and inherited, as the input array (generic)', function test( t ) {
+ var x;
+ var y;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ t.deepEqual( propertiesIn( y ), propertiesIn( x ), 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function returns an array-like object having the same properties, both own and inherited, as the input array (typed)', function test( t ) {
+ var x;
+ var y;
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ t.deepEqual( propertiesIn( y ), propertiesIn( x ), 'returns expected value' );
+ t.end();
+});
+
+tape( 'the function returns an array-like object supporting bracket syntax for element retrieval (generic)', function test( t ) {
+ var x;
+ var y;
+ var i;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ for ( i = 0; i < x.length; i++ ) {
+ t.strictEqual( y[ i ], x[ i ], 'returns expected value' );
+ }
+ t.end();
+});
+
+tape( 'the function returns an array-like object supporting bracket syntax for element retrieval (typed)', function test( t ) {
+ var x;
+ var y;
+ var i;
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ for ( i = 0; i < x.length; i++ ) {
+ t.strictEqual( y[ i ], x[ i ], 'returns expected value' );
+ }
+ t.end();
+});
+
+tape( 'the function returns an array-like object supporting the calling of input array methods (generic)', function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ expected = [ 2, 4, 6, 8 ];
+ actual = y.map( fcn );
+
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+ t.end();
+
+ function fcn( v ) {
+ return v * 2;
+ }
+});
+
+tape( 'the function returns an array-like object supporting the calling of input array methods (typed)', function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ expected = new Int32Array( [ 2, 4, 6, 8 ] );
+ actual = y.map( fcn );
+
+ t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+ t.end();
+
+ function fcn( v ) {
+ return v * 2;
+ }
+});
+
+tape( 'the function returns an array-like object supporting the return of array instances supporting slice expressions (generic)', opts, function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+ var z;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ expected = [ 1, 2, 3, 4 ];
+ actual = y.slice();
+
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.strictEqual( x[ ':' ], void 0, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4 ];
+ actual = y[ ':' ];
+
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ z = actual;
+
+ expected = [ 1, 2, 3, 4 ];
+ actual = z[ ':' ];
+
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function returns an array-like object supporting the return of array instances supporting slice expressions (typed)', opts, function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+ var z;
+
+ x = new Int32Array( [ 1, 2, 3, 4 ] );
+ y = array2fancy( x );
+
+ expected = new Int32Array( [ 1, 2, 3, 4 ] );
+ actual = y.slice();
+
+ t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.strictEqual( x[ ':' ], void 0, 'returns expected value' );
+
+ expected = new Int32Array( [ 1, 2, 3, 4 ] );
+ actual = y[ ':' ];
+
+ t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ z = actual;
+
+ expected = new Int32Array( [ 1, 2, 3, 4 ] );
+ actual = z[ ':' ];
+
+ t.strictEqual( actual instanceof Int32Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
+
+tape( 'the function returns an array-like object supporting constructor access (generic)', function test( t ) {
+ var expected;
+ var actual;
+ var x;
+ var y;
+
+ x = [ 1, 2, 3, 4 ];
+ y = array2fancy( x );
+
+ expected = [];
+ actual = new y.constructor();
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ actual = new y.constructor( 1 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.strictEqual( actual.length, 1, 'returns expected value' );
+
+ expected = [ 1, 2 ];
+ actual = new y.constructor( 1, 2 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3 ];
+ actual = new y.constructor( 1, 2, 3 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4 ];
+ actual = new y.constructor( 1, 2, 3, 4 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6, 7 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ expected = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ];
+ actual = new y.constructor( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 );
+ t.strictEqual( actual instanceof Array, true, 'returns expected value' );
+ t.deepEqual( actual, expected, 'returns expected value' );
+
+ t.end();
+});
diff --git a/to-fancy/test/test.validate.js b/to-fancy/test/test.validate.js
index c8350a1e..68910ccd 100644
--- a/to-fancy/test/test.validate.js
+++ b/to-fancy/test/test.validate.js
@@ -81,6 +81,33 @@ tape( 'the function returns an error if provided a `strict` option which is not
t.end();
});
+tape( 'the function returns an error if provided a `cache` option which is not valid', 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( {}, {
+ 'cache': 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;
@@ -88,12 +115,16 @@ tape( 'the function returns `null` if all options are valid', function test( t )
var err;
options = {
- 'strict': true
+ 'strict': true,
+ 'cache': {
+ 'get': get
+ }
};
opts = {};
expected = {
- 'strict': true
+ 'strict': true,
+ 'cache': options.cache
};
err = validate( opts, options );
@@ -102,6 +133,10 @@ tape( 'the function returns `null` if all options are valid', function test( t )
t.deepEqual( opts, expected, 'returns expected value' );
t.end();
+
+ function get() {
+ // No-op...
+ }
});
tape( 'the function ignores unrecognized options', function test( t ) {