Skip to content

Commit 78cb6e3

Browse files
committed
feat: add support for additional ndarray constructor options
1 parent e6f07c9 commit 78cb6e3

6 files changed

Lines changed: 178 additions & 11 deletions

File tree

lib/node_modules/@stdlib/ndarray/zeros/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ The function accepts the following `options`:
7272

7373
- **dtype**: underlying [data type][@stdlib/ndarray/dtypes]. Default: `'float64'`.
7474
- **order**: specifies whether an [ndarray][@stdlib/ndarray/ctor] is `'row-major'` (C-style) or `'column-major'` (Fortran-style). Default: `'row-major'`.
75+
- **mode**: specifies how to handle indices which exceed array dimensions (see [`ndarray`][@stdlib/ndarray/ctor]). Default: `'throw'`.
76+
- **submode**: a mode array which specifies for each dimension how to handle subscripts which exceed array dimensions (see [`ndarray`][@stdlib/ndarray/ctor]). If provided fewer modes than dimensions, the constructor recycles modes using modulo arithmetic. Default: `[ options.mode ]`.
77+
- **readonly**: `boolean` indicating whether an array should be **read-only**. Default: `false`.
7578

7679
By default, the function returns an [ndarray][@stdlib/ndarray/ctor] having a [`float64`][@stdlib/ndarray/dtypes] data type. To specify an alternative [data type][@stdlib/ndarray/dtypes], provide a `dtype` option.
7780

lib/node_modules/@stdlib/ndarray/zeros/docs/repl.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,28 @@
1717
Specifies whether an array is row-major (C-style) or column-major
1818
(Fortran-style). Default: 'row-major'.
1919

20+
options.mode: string (optional)
21+
Specifies how to handle indices which exceed array dimensions. If equal
22+
to 'throw', an ndarray instance throws an error when an index exceeds
23+
array dimensions. If equal to 'wrap', an ndarray instance wraps around
24+
indices exceeding array dimensions using modulo arithmetic. If equal to
25+
'clamp', an ndarray instance sets an index exceeding array dimensions to
26+
either `0` (minimum index) or the maximum index. Default: 'throw'.
27+
28+
options.submode: Array<string> (optional)
29+
Specifies how to handle subscripts which exceed array dimensions. If a
30+
mode for a corresponding dimension is equal to 'throw', an ndarray
31+
instance throws an error when a subscript exceeds array dimensions. If
32+
equal to 'wrap', an ndarray instance wraps around subscripts exceeding
33+
array dimensions using modulo arithmetic. If equal to 'clamp', an
34+
ndarray instance sets a subscript exceeding array dimensions to either
35+
`0` (minimum index) or the maximum index. If the number of modes is
36+
fewer than the number of dimensions, the function recycles modes using
37+
modulo arithmetic. Default: [ options.mode ].
38+
39+
options.readonly: boolean (optional)
40+
Boolean indicating whether an array should be read-only. Default: false.
41+
2042
Returns
2143
-------
2244
out: ndarray

lib/node_modules/@stdlib/ndarray/zeros/docs/types/index.d.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
/// <reference types="@stdlib/types"/>
2222

23-
import { Shape, Order, typedndarray, float64ndarray, float32ndarray, int32ndarray, int16ndarray, int8ndarray, uint32ndarray, uint16ndarray, uint8ndarray, uint8cndarray, complex128ndarray, complex64ndarray, DataType } from '@stdlib/types/ndarray';
23+
import { Shape, Order, typedndarray, float64ndarray, float32ndarray, int32ndarray, int16ndarray, int8ndarray, uint32ndarray, uint16ndarray, uint8ndarray, uint8cndarray, complex128ndarray, complex64ndarray, DataType, Mode } from '@stdlib/types/ndarray';
2424

2525
/**
2626
* Interface describing function options.
@@ -34,6 +34,21 @@ interface Options {
3434
* - If provided, this option overrides the input array's inferred order.
3535
*/
3636
order?: Order;
37+
38+
/**
39+
* Specifies how to handle a linear index which exceeds array dimensions (default: 'throw').
40+
*/
41+
mode?: Mode;
42+
43+
/**
44+
* Specifies how to handle subscripts which exceed array dimensions on a per dimension basis (default: ['throw']).
45+
*/
46+
submode?: Array<Mode>;
47+
48+
/**
49+
* Boolean indicating whether an array should be read-only (default: false).
50+
*/
51+
readonly?: boolean;
3752
}
3853

3954
/**

lib/node_modules/@stdlib/ndarray/zeros/docs/types/test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,37 @@ import zeros = require( './index' );
9494
zeros( [ 2, 2 ], { 'order': ( x: number ): number => x } ); // $ExpectError
9595
}
9696

97+
// The compiler throws an error if the function is provided a `mode` option which is not a valid mode...
98+
{
99+
zeros( [ 2, 2 ], { 'mode': '5' } ); // $ExpectError
100+
zeros( [ 2, 2 ], { 'mode': 5 } ); // $ExpectError
101+
zeros( [ 2, 2 ], { 'mode': false } ); // $ExpectError
102+
zeros( [ 2, 2 ], { 'mode': true } ); // $ExpectError
103+
zeros( [ 2, 2 ], { 'mode': [ '5' ] } ); // $ExpectError
104+
zeros( [ 2, 2 ], { 'mode': {} } ); // $ExpectError
105+
zeros( [ 2, 2 ], { 'mode': ( x: number ): number => x } ); // $ExpectError
106+
}
107+
108+
// The compiler throws an error if the function is provided a `submode` option which is not valid...
109+
{
110+
zeros( [ 2, 2 ], { 'submode': '5' } ); // $ExpectError
111+
zeros( [ 2, 2 ], { 'submode': 5 } ); // $ExpectError
112+
zeros( [ 2, 2 ], { 'submode': false } ); // $ExpectError
113+
zeros( [ 2, 2 ], { 'submode': true } ); // $ExpectError
114+
zeros( [ 2, 2 ], { 'submode': [ '5' ] } ); // $ExpectError
115+
zeros( [ 2, 2 ], { 'submode': {} } ); // $ExpectError
116+
zeros( [ 2, 2 ], { 'submode': ( x: number ): number => x } ); // $ExpectError
117+
}
118+
119+
// The compiler throws an error if the function is provided a `readonly` option which is not a boolean...
120+
{
121+
zeros( [ 2, 2 ], { 'readonly': '5' } ); // $ExpectError
122+
zeros( [ 2, 2 ], { 'readonly': 5 } ); // $ExpectError
123+
zeros( [ 2, 2 ], { 'readonly': [ '5' ] } ); // $ExpectError
124+
zeros( [ 2, 2 ], { 'readonly': {} } ); // $ExpectError
125+
zeros( [ 2, 2 ], { 'readonly': ( x: number ): number => x } ); // $ExpectError
126+
}
127+
97128
// The compiler throws an error if the function is provided an unsupported number of arguments...
98129
{
99130
zeros(); // $ExpectError

lib/node_modules/@stdlib/ndarray/zeros/lib/main.js

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,14 @@ var ORDER = 'row-major';
4646
* @param {Options} [options] - options
4747
* @param {string} [options.dtype='float64'] - data type
4848
* @param {string} [options.order='row-major'] - array order
49+
* @param {string} [options.mode="throw"] - specifies how to handle indices which exceed array dimensions
50+
* @param {StringArray} [options.submode=["throw"]] - specifies how to handle subscripts which exceed array dimensions on a per dimension basis
51+
* @param {boolean} [options.readonly=false] - boolean indicating whether an array should be read-only
4952
* @throws {TypeError} first argument must be either a nonnegative integer or an array of nonnegative integers
5053
* @throws {TypeError} options argument must be an object
5154
* @throws {TypeError} `dtype` option must be a recognized data type
5255
* @throws {TypeError} `order` option must be a recognized array order
56+
* @throws {TypeError} must provide valid options
5357
* @returns {ndarray} ndarray
5458
*
5559
* @example
@@ -64,6 +68,8 @@ var ORDER = 'row-major';
6468
*/
6569
function zeros( shape ) {
6670
var options;
71+
var dtype;
72+
var order;
6773
var ndims;
6874
var opts;
6975
var buf;
@@ -78,18 +84,27 @@ function zeros( shape ) {
7884
throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) );
7985
}
8086
if ( hasOwnProp( options, 'dtype' ) ) {
81-
opts.dtype = options.dtype;
87+
dtype = options.dtype;
8288
} else {
83-
opts.dtype = DTYPE;
89+
dtype = DTYPE;
8490
}
8591
if ( hasOwnProp( options, 'order' ) ) {
86-
opts.order = options.order;
92+
order = options.order;
8793
} else {
88-
opts.order = ORDER;
94+
order = ORDER;
95+
}
96+
if ( hasOwnProp( options, 'mode' ) ) {
97+
opts.mode = options.mode;
98+
}
99+
if ( hasOwnProp( options, 'submode' ) ) {
100+
opts.submode = options.submode;
101+
}
102+
if ( hasOwnProp( options, 'readonly' ) ) {
103+
opts.readonly = options.readonly;
89104
}
90105
} else {
91-
opts.dtype = DTYPE;
92-
opts.order = ORDER;
106+
dtype = DTYPE;
107+
order = ORDER;
93108
}
94109
if ( typeof shape === 'number' ) {
95110
sh = [ shape ];
@@ -105,17 +120,17 @@ function zeros( shape ) {
105120
// We should only get here if we've been provided an invalid shape (e.g., an array containing negative integers, etc)...
106121
throw new TypeError( format( 'invalid argument. First argument must be either a nonnegative integer or an array of nonnegative integers. Value: `%s`.', shape ) );
107122
}
108-
st = shape2strides( sh, opts.order );
123+
st = shape2strides( sh, order );
109124
} else {
110125
// For 0-dimensional arrays, the buffer should contain a single element...
111126
len = 1;
112127
st = [ 0 ];
113128
}
114-
buf = buffer( opts.dtype, len );
129+
buf = buffer( dtype, len );
115130
if ( buf === null ) {
116-
throw new TypeError( format( 'invalid option. `%s` option must be a recognized data type. Option: `%s`.', 'dtype', opts.dtype ) );
131+
throw new TypeError( format( 'invalid option. `%s` option must be a recognized data type. Option: `%s`.', 'dtype', dtype ) );
117132
}
118-
return new ndarray( opts.dtype, buf, sh, st, strides2offset( sh, st ), opts.order ); // eslint-disable-line max-len
133+
return new ndarray( dtype, buf, sh, st, strides2offset( sh, st ), order, opts ); // eslint-disable-line max-len
119134
}
120135

121136

lib/node_modules/@stdlib/ndarray/zeros/test/test.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,3 +901,84 @@ tape( 'the function supports empty arrays (options)', function test( t ) {
901901

902902
t.end();
903903
});
904+
905+
tape( 'the function supports returning read-only arrays', function test( t ) {
906+
var expected;
907+
var opts;
908+
var arr;
909+
910+
expected = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
911+
912+
opts = {
913+
'dtype': 'generic',
914+
'order': 'row-major',
915+
'readonly': true
916+
};
917+
arr = zeros( [ 2, 2, 2 ], opts );
918+
t.strictEqual( instanceOf( arr, ndarray ), true, 'returns expected value' );
919+
t.strictEqual( arr.dtype, opts.dtype, 'returns expected value' );
920+
t.deepEqual( arr.shape, [ 2, 2, 2 ], 'returns expected value' );
921+
t.strictEqual( instanceOf( arr.data, Array ), true, 'returns expected value' );
922+
t.deepEqual( arr.data, expected, 'returns expected value' );
923+
t.strictEqual( arr.order, opts.order, 'returns expected value' );
924+
t.strictEqual( arr.flags.READONLY, true, 'returns expected value' );
925+
926+
t.end();
927+
});
928+
929+
tape( 'the function supports returning writable arrays', function test( t ) {
930+
var expected;
931+
var opts;
932+
var arr;
933+
934+
expected = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
935+
936+
opts = {
937+
'dtype': 'generic',
938+
'order': 'row-major',
939+
'readonly': false
940+
};
941+
arr = zeros( [ 2, 2, 2 ], opts );
942+
t.strictEqual( instanceOf( arr, ndarray ), true, 'returns expected value' );
943+
t.strictEqual( arr.dtype, opts.dtype, 'returns expected value' );
944+
t.deepEqual( arr.shape, [ 2, 2, 2 ], 'returns expected value' );
945+
t.strictEqual( instanceOf( arr.data, Array ), true, 'returns expected value' );
946+
t.deepEqual( arr.data, expected, 'returns expected value' );
947+
t.strictEqual( arr.order, opts.order, 'returns expected value' );
948+
t.strictEqual( arr.flags.READONLY, false, 'returns expected value' );
949+
950+
t.end();
951+
});
952+
953+
tape( 'the function supports specifying array index modes and submodes', function test( t ) {
954+
var expected;
955+
var opts;
956+
var arr;
957+
958+
expected = [ 0, 0, 0, 0, 0, 0, 0, 0 ];
959+
960+
opts = {
961+
'dtype': 'generic',
962+
'order': 'row-major',
963+
'mode': 'clamp',
964+
'submode': [ 'wrap' ]
965+
};
966+
arr = zeros( [ 2, 2, 2 ], opts );
967+
t.strictEqual( instanceOf( arr, ndarray ), true, 'returns expected value' );
968+
t.strictEqual( arr.dtype, opts.dtype, 'returns expected value' );
969+
t.deepEqual( arr.shape, [ 2, 2, 2 ], 'returns expected value' );
970+
t.strictEqual( instanceOf( arr.data, Array ), true, 'returns expected value' );
971+
t.deepEqual( arr.data, expected, 'returns expected value' );
972+
t.strictEqual( arr.order, opts.order, 'returns expected value' );
973+
974+
t.strictEqual( arr.iget( arr.length+10 ), 0, 'returns expected value' );
975+
arr.iset( arr.length+10, 1 );
976+
t.strictEqual( arr.iget( arr.length+10 ), 1, 'returns expected value' );
977+
978+
t.strictEqual( arr.get( 2, 2, 2 ), 0, 'returns expected value' );
979+
arr.set( 2, 2, 2, 3 );
980+
t.strictEqual( arr.get( 0, 0, 0 ), 3, 'returns expected value' );
981+
t.strictEqual( arr.get( 2, 2, 2 ), 3, 'returns expected value' );
982+
983+
t.end();
984+
});

0 commit comments

Comments
 (0)