Skip to content

Commit c13dd70

Browse files
committed
refactor: normalize dtypes to enums to reduce memory consumption and speed-up comparisons
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: na - task: lint_repl_help status: skipped - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 2041e12 commit c13dd70

4 files changed

Lines changed: 45 additions & 38 deletions

File tree

lib/node_modules/@stdlib/ndarray/base/unary-strided1d-dispatch/README.md

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ Applies a strided function to a provided input ndarray.
8888

8989
```javascript
9090
var ndarray = require( '@stdlib/ndarray/base/ctor' );
91-
var ndarray2array = require( '@stdlib/ndarray/to-array' );
9291
var base = require( '@stdlib/stats/base/ndarray/cumax' );
9392

9493
var table = {
@@ -107,10 +106,7 @@ var xbuf = [ -1.0, 2.0, -3.0 ];
107106
var x = new ndarray( 'generic', xbuf, [ xbuf.length ], [ 1 ], 0, 'row-major' );
108107

109108
var y = unary.apply( x );
110-
// returns <ndarray>
111-
112-
var arr = ndarray2array( y );
113-
// returns [ -1.0, 2.0, 2.0 ]
109+
// returns <ndarray>[ -1.0, 2.0, 2.0 ]
114110
```
115111

116112
The method has the following parameters:
@@ -151,7 +147,7 @@ var y = unary.apply( x, {
151147
});
152148
// returns <ndarray>
153149

154-
var dt = getDType( y );
150+
var dt = String( getDType( y ) );
155151
// returns 'float64'
156152
```
157153

@@ -161,7 +157,6 @@ Applies a strided function a provided input ndarray and assigns results to a pro
161157

162158
```javascript
163159
var base = require( '@stdlib/stats/base/ndarray/cumax' );
164-
var ndarray2array = require( '@stdlib/ndarray/to-array' );
165160
var dtypes = require( '@stdlib/ndarray/dtypes' );
166161
var ndarray = require( '@stdlib/ndarray/base/ctor' );
167162

@@ -184,10 +179,7 @@ var ybuf = [ 0.0, 0.0, 0.0 ];
184179
var y = new ndarray( 'generic', ybuf, [ ybuf.length ], [ 1 ], 0, 'row-major' );
185180

186181
var out = unary.assign( x, y );
187-
// returns <ndarray>
188-
189-
var arr = ndarray2array( y );
190-
// returns [ -1.0, 2.0, 2.0 ]
182+
// returns <ndarray>[ -1.0, 2.0, 2.0 ]
191183

192184
var bool = ( out === y );
193185
// returns true

lib/node_modules/@stdlib/ndarray/base/unary-strided1d-dispatch/docs/repl.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
- arrays: array containing an input and an output ndarray, followed by
3030
any additional ndarray arguments.
3131

32-
idtypes: Array<Array<string>>
32+
idtypes: Array<Array<string|DataType>>
3333
List containing lists of supported input array data types for each input
3434
ndarray argument.
3535

36-
odtypes: Array<string>
36+
odtypes: Array<string|DataType>
3737
List of supported output array data types.
3838

3939
policies: Object
@@ -76,7 +76,7 @@
7676
options: Object (optional)
7777
Function options.
7878

79-
options.dtype: string (optional)
79+
options.dtype: string|DataType (optional)
8080
Output array data type. Setting this option overrides the output data
8181
type policy.
8282

lib/node_modules/@stdlib/ndarray/base/unary-strided1d-dispatch/lib/main.js

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ var contains = require( '@stdlib/array/base/assert/contains' );
3737
var unaryStrided1d = require( '@stdlib/ndarray/base/unary-strided1d' );
3838
var unaryOutputDataType = require( '@stdlib/ndarray/base/unary-output-dtype' );
3939
var unaryInputCastingDataType = require( '@stdlib/ndarray/base/unary-input-casting-dtype' );
40+
var resolveEnum = require( '@stdlib/ndarray/base/dtype-resolve-enum' );
4041
var dtypes2enums = require( '@stdlib/ndarray/base/dtypes2enums' );
42+
var dtypes2strings = require( '@stdlib/ndarray/base/dtypes2strings' );
4143
var getShape = require( '@stdlib/ndarray/shape' ); // note: non-base accessor is intentional due to input ndarrays originating in userland
4244
var ndims = require( '@stdlib/ndarray/ndims' );
4345
var getDType = require( '@stdlib/ndarray/base/dtype' );
@@ -65,10 +67,10 @@ var validate = require( './validate.js' );
6567
* @constructor
6668
* @param {Object} table - dispatch table
6769
* @param {Function} table.default - default strided function
68-
* @param {StringArray} [table.types=[]] - one-dimensional list of ndarray data types describing specialized input and output ndarray argument signatures
70+
* @param {ArrayLikeObject} [table.types=[]] - one-dimensional list of ndarray data types describing specialized input and output ndarray argument signatures
6971
* @param {ArrayLikeObject<Function>} [table.fcns=[]] - list of strided functions which are specific to specialized input and output ndarray argument signatures
70-
* @param {ArrayLikeObject<StringArray>} idtypes - list containing lists of supported input data types for each ndarray argument
71-
* @param {StringArray} odtypes - list of supported output data types
72+
* @param {ArrayLikeObject<ArrayLikeObject>} idtypes - list containing lists of supported input data types for each ndarray argument
73+
* @param {ArrayLikeObject} odtypes - list of supported output data types
7274
* @param {Object} policies - policies
7375
* @param {string} policies.output - output data type policy
7476
* @param {string} policies.casting - input ndarray casting policy
@@ -111,6 +113,8 @@ var validate = require( './validate.js' );
111113
* // returns [ -1.0, 2.0, 2.0 ]
112114
*/
113115
function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
116+
var idt;
117+
var odt;
114118
var dt;
115119
var i;
116120
if ( !( this instanceof UnaryStrided1dDispatch ) ) {
@@ -134,6 +138,7 @@ function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
134138
if ( !isCollection( idtypes ) ) {
135139
throw new TypeError( format( 'invalid argument. Second argument must be an array-like object. Value: `%s`.', idtypes ) );
136140
}
141+
idt = [];
137142
for ( i = 0; i < idtypes.length; i++ ) {
138143
dt = idtypes[ i ];
139144
if (
@@ -143,6 +148,7 @@ function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
143148
) {
144149
throw new TypeError( format( 'invalid argument. Second argument must contain arrays of data types. Value: `%s`.', idtypes ) );
145150
}
151+
idt.push( dtypes2enums( dt ) ); // note: convert to enums (i.e., integers) to ensure faster comparisons and reduced storage requirements
146152
}
147153
if (
148154
!isCollection( odtypes ) ||
@@ -151,6 +157,8 @@ function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
151157
) {
152158
throw new TypeError( format( 'invalid argument. Third argument must be an array of data types. Value: `%s`.', odtypes ) );
153159
}
160+
odt = dtypes2enums( odtypes ); // note: convert to enums (i.e., integers) to ensure faster comparisons and reduced storage requirements
161+
154162
if ( !isObject( policies ) ) {
155163
throw new TypeError( format( 'invalid argument. Fourth argument must be an object. Value: `%s`.', policies ) );
156164
}
@@ -162,14 +170,14 @@ function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
162170
}
163171
this._table = {
164172
'default': table.default,
165-
'types': ( table.types ) ? dtypes2enums( table.types ) : [], // note: convert to enums (i.e., integers) to ensure faster comparisons
173+
'types': ( table.types ) ? dtypes2enums( table.types ) : [], // note: convert to enums (i.e., integers) to ensure faster comparisons and reduced storage requirements
166174
'fcns': ( table.fcns ) ? copy( table.fcns ) : []
167175
};
168176
if ( this._table.types.length !== this._table.fcns.length*2 ) {
169177
throw new Error( 'invalid argument. First argument specifies an unexpected number of types. A pair of input and output ndarray data types must be specified for each provided strided function.' );
170178
}
171-
this._idtypes = idtypes;
172-
this._odtypes = odtypes;
179+
this._idtypes = idt;
180+
this._odtypes = odt;
173181
this._policies = {
174182
'output': policies.output,
175183
'casting': policies.casting
@@ -192,7 +200,7 @@ function UnaryStrided1dDispatch( table, idtypes, odtypes, policies, options ) {
192200
* @param {...ndarrayLike} [args] - additional ndarray arguments
193201
* @param {Options} [options] - function options
194202
* @param {IntegerArray} [options.dims] - list of dimensions over which to perform an operation
195-
* @param {string} [options.dtype] - output ndarray data type
203+
* @param {*} [options.dtype] - output ndarray data type
196204
* @throws {TypeError} first argument must be an ndarray-like object
197205
* @throws {TypeError} options argument must be an object
198206
* @throws {RangeError} dimension indices must not exceed input ndarray bounds
@@ -232,6 +240,7 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'apply', function apply( x ) {
232240
var nargs;
233241
var args;
234242
var opts;
243+
var xdte;
235244
var err;
236245
var shx;
237246
var arr;
@@ -249,8 +258,9 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'apply', function apply( x ) {
249258
throw new TypeError( format( 'invalid argument. First argument must be an ndarray-like object. Value: `%s`.', x ) );
250259
}
251260
xdt = getDType( x );
252-
if ( !contains( this._idtypes[ 0 ], xdt ) ) {
253-
throw new TypeError( format( 'invalid argument. First argument must have one of the following data types: "%s". Data type: `%s`.', join( this._idtypes[ 0 ], '", "' ), xdt ) );
261+
xdte = resolveEnum( xdt );
262+
if ( !contains( this._idtypes[ 0 ], xdte ) ) {
263+
throw new TypeError( format( 'invalid argument. First argument must have one of the following data types: "%s". Data type: `%s`.', join( dtypes2strings( this._idtypes[ 0 ] ), '", "' ), xdt ) );
254264
}
255265
args = [ x ];
256266
for ( i = 1; i < nargs; i++ ) {
@@ -259,9 +269,10 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'apply', function apply( x ) {
259269
break;
260270
}
261271
dt = getDType( arr );
262-
if ( !contains( this._idtypes[ i ], dt ) ) {
263-
throw new TypeError( format( 'invalid argument. Argument %d must have one of the following data types: "%s". Data type: `%s`.', i, join( this._idtypes[ i ], '", "' ), dt ) );
272+
if ( !contains( this._idtypes[ i ], resolveEnum( dt ) ) ) {
273+
throw new TypeError( format( 'invalid argument. Argument %d must have one of the following data types: "%s". Data type: `%s`.', i, join( dtypes2strings( this._idtypes[ i ] ), '", "' ), dt ) );
264274
}
275+
// Note: we don't type promote additional ndarray arguments...
265276
args.push( arr );
266277
}
267278
// If we didn't make it up until the last argument, this means that we found a non-options argument which was not an ndarray...
@@ -292,15 +303,15 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'apply', function apply( x ) {
292303

293304
// Determine whether we need to cast the input ndarray...
294305
dt = unaryInputCastingDataType( xdt, ydt, this._policies.casting );
295-
if ( xdt !== dt ) {
296-
// TODO: replace the following logic with a call to `ndarray/base/(?maybe-)(cast|convert|copy)` or similar utility
306+
if ( xdte !== resolveEnum( dt ) ) {
307+
// TODO: consider replacing the following logic with a call to `ndarray/base/(?maybe-)(cast|convert)` or similar utility
297308
tmp = baseEmpty( dt, shx, getOrder( x ) );
298309
assign( [ x, tmp ] );
299310
args[ 0 ] = tmp;
300311
xdt = dt;
301312
}
302313
// Resolve the lower-level strided function satisfying the input and output ndarray data types:
303-
i = gindexOfRow( this._table.fcns.length, 2, this._table.types, 2, 1, 0, dtypes2enums( [ xdt, ydt ] ), 1, 0 ); // eslint-disable-line max-len
314+
i = gindexOfRow( this._table.fcns.length, 2, this._table.types, 2, 1, 0, [ xdte, resolveEnum( ydt ) ], 1, 0 ); // eslint-disable-line max-len
304315
if ( i >= 0 ) {
305316
f = this._table.fcns[ i ];
306317
} else {
@@ -370,6 +381,7 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'assign', function assign( x ) {
370381
var nargs;
371382
var opts;
372383
var args;
384+
var xdte;
373385
var arr;
374386
var err;
375387
var flg;
@@ -388,8 +400,9 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'assign', function assign( x ) {
388400
}
389401
// Validate the input ndarray data type in order to maintain similar behavior to `apply` above...
390402
xdt = getDType( x );
391-
if ( !contains( this._idtypes[ 0 ], xdt ) ) {
392-
throw new TypeError( format( 'invalid argument. First argument must have one of the following data types: "%s". Data type: `%s`.', join( this._idtypes[ 0 ], '", "' ), xdt ) );
403+
xdte = resolveEnum( xdt );
404+
if ( !contains( this._idtypes[ 0 ], xdte ) ) {
405+
throw new TypeError( format( 'invalid argument. First argument must have one of the following data types: "%s". Data type: `%s`.', join( dtypes2strings( this._idtypes[ 0 ] ), '", "' ), xdt ) );
393406
}
394407
args = [ x ];
395408

@@ -420,8 +433,8 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'assign', function assign( x ) {
420433
// Verify that additional ndarray arguments have expected dtypes (note: we intentionally don't validate the output ndarray dtype in order to provide an escape hatch for a user wanting to have an output ndarray having a specific dtype that `apply` does not support)...
421434
for ( i = 1; i < args.length; i++ ) {
422435
dt = getDType( args[ i ] );
423-
if ( !contains( this._idtypes[ i ], dt ) ) {
424-
throw new TypeError( format( 'invalid argument. Argument %d must have one of the following data types: "%s". Data type: `%s`.', i, join( this._idtypes[ i ], '", "' ), dt ) );
436+
if ( !contains( this._idtypes[ i ], resolveEnum( dt ) ) ) {
437+
throw new TypeError( format( 'invalid argument. Argument %d must have one of the following data types: "%s". Data type: `%s`.', i, join( dtypes2strings( this._idtypes[ i ] ), '", "' ), dt ) );
425438
}
426439
}
427440
// Validate any provided options...
@@ -440,15 +453,15 @@ setReadOnly( UnaryStrided1dDispatch.prototype, 'assign', function assign( x ) {
440453
// Determine whether we need to cast the input ndarray...
441454
ydt = getDType( y );
442455
dt = unaryInputCastingDataType( xdt, ydt, this._policies.casting );
443-
if ( xdt !== dt ) {
444-
// TODO: replace the following logic with a call to `ndarray/base/(?maybe-)(cast|convert|copy)` or similar utility
456+
if ( xdte !== resolveEnum( dt ) ) {
457+
// TODO: consider replacing the following logic with a call to `ndarray/base/(?maybe-)(cast|convert)` or similar utility
445458
tmp = baseEmpty( dt, getShape( x ), getOrder( x ) );
446459
assign( [ x, tmp ] );
447460
args[ 0 ] = tmp;
448461
xdt = dt;
449462
}
450463
// Resolve the lower-level strided function satisfying the input and output ndarray data types:
451-
i = gindexOfRow( this._table.fcns.length, 2, this._table.types, 2, 1, 0, dtypes2enums( [ xdt, ydt ] ), 1, 0 ); // eslint-disable-line max-len
464+
i = gindexOfRow( this._table.fcns.length, 2, this._table.types, 2, 1, 0, [ xdte, resolveEnum( ydt ) ], 1, 0 ); // eslint-disable-line max-len
452465
if ( i >= 0 ) {
453466
f = this._table.fcns[ i ];
454467
} else {

lib/node_modules/@stdlib/ndarray/base/unary-strided1d-dispatch/lib/validate.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ var hasOwnProp = require( '@stdlib/assert/has-own-property' );
2525
var isIntegerArray = require( '@stdlib/assert/is-integer-array' ).primitives;
2626
var isEmptyCollection = require( '@stdlib/assert/is-empty-collection' );
2727
var normalizeIndices = require( '@stdlib/ndarray/base/to-unique-normalized-indices' );
28+
var resolveEnum = require( '@stdlib/ndarray/base/dtype-resolve-enum' );
29+
var dtypes2strings = require( '@stdlib/ndarray/base/dtypes2strings' );
2830
var join = require( '@stdlib/array/base/join' );
2931
var contains = require( '@stdlib/array/base/assert/contains' );
3032
var format = require( '@stdlib/string/format' );
@@ -41,7 +43,7 @@ var format = require( '@stdlib/string/format' );
4143
* @param {Array} dtypes - list of supported output data types
4244
* @param {Options} options - function options
4345
* @param {IntegerArray} [options.dims] - list of dimensions over which to perform an operation
44-
* @param {string} [options.dtype] - output ndarray data type
46+
* @param {*} [options.dtype] - output ndarray data type
4547
* @returns {(Error|null)} null or an error object
4648
*
4749
* @example
@@ -77,8 +79,8 @@ function validate( opts, ndims, dtypes, options ) {
7779
}
7880
if ( hasOwnProp( options, 'dtype' ) ) {
7981
opts.dtype = options.dtype;
80-
if ( !contains( dtypes, opts.dtype ) ) {
81-
return new TypeError( format( 'invalid option. `%s` option must be one of the following: "%s". Option: `%s`.', 'dtype', join( dtypes, '", "' ), opts.dtype ) );
82+
if ( !contains( dtypes, resolveEnum( opts.dtype ) ) ) {
83+
return new TypeError( format( 'invalid option. `%s` option must be one of the following: "%s". Option: `%s`.', 'dtype', join( dtypes2strings( dtypes ), '", "' ), options.dtype ) );
8284
}
8385
}
8486
return null;

0 commit comments

Comments
 (0)