time-to-botec

Benchmark sampling in different programming languages
Log | Files | Refs | README

main.js (15437B)


      1 /**
      2 * @license Apache-2.0
      3 *
      4 * Copyright (c) 2018 The Stdlib Authors.
      5 *
      6 * Licensed under the Apache License, Version 2.0 (the "License");
      7 * you may not use this file except in compliance with the License.
      8 * You may obtain a copy of the License at
      9 *
     10 *    http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing, software
     13 * distributed under the License is distributed on an "AS IS" BASIS,
     14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15 * See the License for the specific language governing permissions and
     16 * limitations under the License.
     17 */
     18 
     19 /* eslint-disable no-restricted-syntax, no-invalid-this */
     20 
     21 'use strict';
     22 
     23 // MODULES //
     24 
     25 var hasBigIntSupport = require( '@stdlib/assert/has-bigint-support' );
     26 var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
     27 var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' );
     28 var bytesPerElement = require( './../../../base/bytes-per-element' );
     29 var iterationOrder = require( './../../../base/iteration-order' );
     30 var strides2order = require( './../../../base/strides2order' );
     31 var isColumnMajorContiguous = require( './is_column_major_contiguous.js' );
     32 var isRowMajorContiguous = require( './is_row_major_contiguous.js' );
     33 var isContiguous = require( './is_contiguous.js' );
     34 var copyFlags = require( './copy_flags.js' );
     35 var igetValue = require( './iget.js' );
     36 var isetValue = require( './iset.js' );
     37 var setValue = require( './set.js' );
     38 var getValue = require( './get.js' );
     39 var toJSON = require( './tojson.js' );
     40 var toString = require( './tostring.js' ); // eslint-disable-line stdlib/no-redeclare
     41 var meta2dataview = require( './meta2dataview.js' );
     42 var meta2dataviewPolyfill = require( './meta2dataview.polyfill.js' );
     43 
     44 
     45 // MAIN //
     46 
     47 /**
     48 * ndarray constructor.
     49 *
     50 * ## Notes
     51 *
     52 * -   To create a zero-dimensional array,
     53 *
     54 *     ```javascript
     55 *     var buffer = [ 1 ];
     56 *     var shape = [];
     57 *     var strides = [ 0 ];
     58 *     var offset = 0;
     59 *
     60 *     var out = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
     61 *     ```
     62 *
     63 * @constructor
     64 * @param {string} dtype - data type
     65 * @param {(ArrayLikeObject|TypedArray|Buffer)} buffer - data buffer
     66 * @param {NonNegativeIntegerArray} shape - array shape
     67 * @param {IntegerArray} strides - array strides
     68 * @param {NonNegativeInteger} offset - index offset
     69 * @param {string} order - specifies whether an array is row-major (C-style) or column-major (Fortran-style)
     70 * @returns {ndarray} ndarray instance
     71 *
     72 * @example
     73 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
     74 * var shape = [ 3, 2 ];
     75 * var strides = [ 2, 1 ];
     76 * var offset = 0;
     77 *
     78 * var out = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
     79 */
     80 function ndarray( dtype, buffer, shape, strides, offset, order ) {
     81 	var contiguous;
     82 	var nbytes;
     83 	var ord;
     84 	var len;
     85 	var i;
     86 	if ( !(this instanceof ndarray) ) {
     87 		return new ndarray( dtype, buffer, shape, strides, offset, order );
     88 	}
     89 	// Compute the number of elements...
     90 	len = 1;
     91 	for ( i = 0; i < shape.length; i++ ) {
     92 		len *= shape[ i ];
     93 	}
     94 	// Compute the number of bytes...
     95 	if ( buffer.BYTES_PER_ELEMENT ) {
     96 		nbytes = buffer.BYTES_PER_ELEMENT * len;
     97 	} else {
     98 		nbytes = null;
     99 	}
    100 	// Set private properties...
    101 	this._byteLength = nbytes;
    102 	this._bytesPerElement = bytesPerElement( dtype );
    103 	this._buffer = buffer;
    104 	this._dtype = dtype;
    105 	this._length = len;
    106 	this._ndims = shape.length;
    107 	this._offset = offset;
    108 	this._order = order;
    109 	this._shape = shape;
    110 	this._strides = strides;
    111 	this._accessors = Boolean( buffer.get && buffer.set );
    112 
    113 	this._iterationOrder = iterationOrder( strides );
    114 
    115 	// Determine if the array can be stored contiguously:
    116 	contiguous = isContiguous( len, shape, strides, offset, this._iterationOrder ); // eslint-disable-line max-len
    117 
    118 	// Infer the array "order" from the stride array (this is supplementary to the `order` parameter):
    119 	ord = strides2order( strides );
    120 
    121 	this._flags = {
    122 		'ROW_MAJOR_CONTIGUOUS': isRowMajorContiguous( ord, contiguous ),
    123 		'COLUMN_MAJOR_CONTIGUOUS': isColumnMajorContiguous( ord, contiguous )
    124 	};
    125 
    126 	// Initialize a property for caching serialized meta data:
    127 	this.__meta_dataview__ = null;
    128 
    129 	return this;
    130 }
    131 
    132 /**
    133 * Constructor name.
    134 *
    135 * @name name
    136 * @memberof ndarray
    137 * @type {string}
    138 * @default 'ndarray'
    139 *
    140 * @example
    141 * var str = ndarray.name;
    142 * // returns 'ndarray'
    143 */
    144 setReadOnly( ndarray, 'name', 'ndarray' );
    145 
    146 /**
    147 * Size (in bytes) of the array (if known).
    148 *
    149 * @name byteLength
    150 * @memberof ndarray.prototype
    151 * @type {(NonNegativeInteger|null)}
    152 *
    153 * @example
    154 * var Float64Array = require( '@stdlib/array/float64' );
    155 *
    156 * var buffer = new Float64Array( [ 1, 2, 3, 4, 5, 6 ] );
    157 * var shape = [ 3, 2 ];
    158 * var strides = [ 2, 1 ];
    159 * var offset = 0;
    160 *
    161 * var x = ndarray( 'float64', buffer, shape, strides, offset, 'row-major' );
    162 *
    163 * var byteLength = x.byteLength;
    164 * // returns 48
    165 */
    166 setReadOnlyAccessor( ndarray.prototype, 'byteLength', function get() {
    167 	return this._byteLength;
    168 });
    169 
    170 /**
    171 * Size (in bytes) of each array element (if known).
    172 *
    173 * @name BYTES_PER_ELEMENT
    174 * @memberof ndarray.prototype
    175 * @type {(PositiveInteger|null)}
    176 *
    177 * @example
    178 * var Float64Array = require( '@stdlib/array/float64' );
    179 *
    180 * var buffer = new Float64Array( [ 1, 2, 3, 4, 5, 6 ] );
    181 * var shape = [ 3, 2 ];
    182 * var strides = [ 2, 1 ];
    183 * var offset = 0;
    184 *
    185 * var x = ndarray( 'float64', buffer, shape, strides, offset, 'row-major' );
    186 *
    187 * var nbytes = x.BYTES_PER_ELEMENT;
    188 * // returns 8
    189 */
    190 setReadOnlyAccessor( ndarray.prototype, 'BYTES_PER_ELEMENT', function get() {
    191 	return this._bytesPerElement;
    192 });
    193 
    194 /**
    195 * Pointer to the underlying data buffer.
    196 *
    197 * @name data
    198 * @memberof ndarray.prototype
    199 * @type {(Array|TypedArray|Buffer)}
    200 *
    201 * @example
    202 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    203 * var shape = [ 3, 2 ];
    204 * var strides = [ 2, 1 ];
    205 * var offset = 0;
    206 *
    207 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    208 *
    209 * var data = x.data;
    210 * // returns [ 1, 2, 3, 4, 5, 6 ]
    211 */
    212 setReadOnlyAccessor( ndarray.prototype, 'data', function get() {
    213 	return this._buffer;
    214 });
    215 
    216 /**
    217 * Underlying data type.
    218 *
    219 * @name dtype
    220 * @memberof ndarray.prototype
    221 * @type {string}
    222 *
    223 * @example
    224 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    225 * var shape = [ 3, 2 ];
    226 * var strides = [ 2, 1 ];
    227 * var offset = 0;
    228 *
    229 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    230 *
    231 * var dtype = x.dtype;
    232 * // returns 'generic'
    233 */
    234 setReadOnlyAccessor( ndarray.prototype, 'dtype', function get() {
    235 	return this._dtype;
    236 });
    237 
    238 /**
    239 * Information about the memory layout of the array.
    240 *
    241 * @name flags
    242 * @memberof ndarray.prototype
    243 * @type {Object}
    244 *
    245 * @example
    246 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    247 * var shape = [ 3, 2 ];
    248 * var strides = [ 2, 1 ];
    249 * var offset = 0;
    250 *
    251 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    252 *
    253 * var flgs = x.flags;
    254 * // returns <Object>
    255 */
    256 setReadOnlyAccessor( ndarray.prototype, 'flags', function get() {
    257 	return copyFlags( this._flags );
    258 });
    259 
    260 /**
    261 * Length of the array.
    262 *
    263 * @name length
    264 * @memberof ndarray.prototype
    265 * @type {NonNegativeInteger}
    266 *
    267 * @example
    268 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    269 * var shape = [ 3, 2 ];
    270 * var strides = [ 2, 1 ];
    271 * var offset = 0;
    272 *
    273 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    274 *
    275 * var len = x.length;
    276 * // returns 6
    277 */
    278 setReadOnlyAccessor( ndarray.prototype, 'length', function get() {
    279 	return this._length;
    280 });
    281 
    282 /**
    283 * Number of dimensions.
    284 *
    285 * @name ndims
    286 * @memberof ndarray.prototype
    287 * @type {PositiveInteger}
    288 *
    289 * @example
    290 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    291 * var shape = [ 3, 2 ];
    292 * var strides = [ 2, 1 ];
    293 * var offset = 0;
    294 *
    295 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    296 *
    297 * var ndims = x.ndims;
    298 * // returns 2
    299 */
    300 setReadOnlyAccessor( ndarray.prototype, 'ndims', function get() {
    301 	return this._ndims;
    302 });
    303 
    304 /**
    305 * Index offset which specifies the buffer index at which to start iterating over array elements.
    306 *
    307 * @name offset
    308 * @memberof ndarray.prototype
    309 * @type {NonNegativeInteger}
    310 *
    311 * @example
    312 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    313 * var shape = [ 3, 2 ];
    314 * var strides = [ 2, 1 ];
    315 * var offset = 0;
    316 *
    317 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    318 *
    319 * var o = x.offset;
    320 * // returns 0
    321 */
    322 setReadOnlyAccessor( ndarray.prototype, 'offset', function get() {
    323 	return this._offset;
    324 });
    325 
    326 /**
    327 * Array order.
    328 *
    329 * ## Notes
    330 *
    331 * -   The array order is either row-major (C-style) or column-major (Fortran-style).
    332 *
    333 *
    334 * @name order
    335 * @memberof ndarray.prototype
    336 * @type {string}
    337 *
    338 * @example
    339 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    340 * var shape = [ 3, 2 ];
    341 * var strides = [ 2, 1 ];
    342 * var offset = 0;
    343 *
    344 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    345 *
    346 * var order = x.order;
    347 * // returns 'row-major'
    348 */
    349 setReadOnlyAccessor( ndarray.prototype, 'order', function get() {
    350 	return this._order;
    351 });
    352 
    353 /**
    354 * Shape of the array.
    355 *
    356 * @name shape
    357 * @memberof ndarray.prototype
    358 * @type {NonNegativeIntegerArray}
    359 *
    360 * @example
    361 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    362 * var shape = [ 3, 2 ];
    363 * var strides = [ 2, 1 ];
    364 * var offset = 0;
    365 *
    366 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    367 *
    368 * var s = x.shape;
    369 * // returns [ 3, 2 ]
    370 */
    371 setReadOnlyAccessor( ndarray.prototype, 'shape', function get() {
    372 	return this._shape.slice();
    373 });
    374 
    375 /**
    376 * Index strides which specify how to access data along corresponding array dimensions.
    377 *
    378 * @name strides
    379 * @memberof ndarray.prototype
    380 * @type {IntegerArray}
    381 *
    382 * @example
    383 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    384 * var shape = [ 3, 2 ];
    385 * var strides = [ 2, 1 ];
    386 * var offset = 0;
    387 *
    388 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    389 *
    390 * var s = x.strides;
    391 * // returns [ 2, 1 ]
    392 */
    393 setReadOnlyAccessor( ndarray.prototype, 'strides', function get() {
    394 	return this._strides.slice();
    395 });
    396 
    397 /**
    398 * Returns an array element.
    399 *
    400 * ## Notes
    401 *
    402 * -   The number of indices should **equal** the number of dimensions. Accordingly, for zero-dimensional arrays, no indices should be provided.
    403 *
    404 * @name get
    405 * @memberof ndarray.prototype
    406 * @type {Function}
    407 * @param {...integer} [idx] - indices
    408 * @returns {*} array element
    409 *
    410 * @example
    411 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    412 * var shape = [ 3, 2 ];
    413 * var strides = [ 2, 1 ];
    414 * var offset = 0;
    415 *
    416 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    417 *
    418 * var v = x.get( 1, 1 );
    419 * // returns 4
    420 */
    421 setReadOnly( ndarray.prototype, 'get', getValue );
    422 
    423 /**
    424 * Returns an array element located at a specified linear index.
    425 *
    426 * ## Notes
    427 *
    428 * -   For zero-dimensional arrays, the input argument is ignored and, for clarity, should not be provided.
    429 *
    430 * @name iget
    431 * @memberof ndarray.prototype
    432 * @type {Function}
    433 * @param {integer} [idx] - linear index
    434 * @returns {*} array element
    435 *
    436 * @example
    437 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    438 * var shape = [ 3, 2 ];
    439 * var strides = [ 2, 1 ];
    440 * var offset = 0;
    441 *
    442 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    443 *
    444 * var v = x.iget( 3 );
    445 * // returns 4
    446 */
    447 setReadOnly( ndarray.prototype, 'iget', igetValue );
    448 
    449 /**
    450 * Sets an array element.
    451 *
    452 * ## Notes
    453 *
    454 * -   The number of indices should **equal** the number of dimensions. Accordingly, for zero-dimensional arrays, no indices should be provided.
    455 *
    456 * @name set
    457 * @memberof ndarray.prototype
    458 * @type {Function}
    459 * @param {...integer} [idx] - indices
    460 * @param {*} v - value to set
    461 * @returns {ndarray} ndarray instance
    462 *
    463 * @example
    464 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    465 * var shape = [ 3, 2 ];
    466 * var strides = [ 2, 1 ];
    467 * var offset = 0;
    468 *
    469 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    470 *
    471 * var v = x.get( 1, 1 );
    472 * // returns 4
    473 *
    474 * x.set( 1, 1, 10 );
    475 *
    476 * var b = x.data;
    477 * // returns [ 1, 2, 3, 10, 5, 6 ]
    478 *
    479 * v = x.get( 1, 1 );
    480 * // returns 10
    481 */
    482 setReadOnly( ndarray.prototype, 'set', setValue );
    483 
    484 /**
    485 * Sets an array element located at a specified linear index.
    486 *
    487 * ## Notes
    488 *
    489 * -   For zero-dimensional arrays, the first, and only, argument should be the value to set.
    490 *
    491 * @name iset
    492 * @memberof ndarray.prototype
    493 * @type {Function}
    494 * @param {integer} [idx] - linear index
    495 * @param {*} v - value to set
    496 * @returns {ndarray} ndarray instance
    497 *
    498 * @example
    499 * var buffer = [ 1, 2, 3, 4, 5, 6 ];
    500 * var shape = [ 3, 2 ];
    501 * var strides = [ 2, 1 ];
    502 * var offset = 0;
    503 *
    504 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    505 *
    506 * var v = x.iget( 3 );
    507 * // returns 4
    508 *
    509 * x.iset( 3, 10 );
    510 *
    511 * var b = x.data;
    512 * // returns [ 1, 2, 3, 10, 5, 6 ]
    513 *
    514 * v = x.iget( 3 );
    515 * // returns 10
    516 */
    517 setReadOnly( ndarray.prototype, 'iset', isetValue );
    518 
    519 /**
    520 * Serializes an ndarray as a string.
    521 *
    522 * ## Notes
    523 *
    524 * -   The method does **not** serialize data outside of the buffer region defined by the array configuration.
    525 *
    526 *
    527 * @name toString
    528 * @memberof ndarray.prototype
    529 * @type {Function}
    530 * @returns {string} serialized ndarray
    531 *
    532 * @example
    533 * var buffer = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
    534 * var shape = [ 3, 2 ];
    535 * var strides = [ 2, 1 ];
    536 * var offset = 2;
    537 *
    538 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    539 *
    540 * var str = x.toString();
    541 * // returns "ndarray( 'generic', [ 3, 4, 5, 6, 7, 8 ], [ 3, 2 ], [ 2, 1 ], 0, 'row-major' )"
    542 */
    543 setReadOnly( ndarray.prototype, 'toString', toString );
    544 
    545 /**
    546 * Serializes an ndarray as a JSON object.
    547 *
    548 * ## Notes
    549 *
    550 * -   `JSON.stringify()` implicitly calls this method when stringifying an `ndarray` instance.
    551 * -   The method does **not** serialize data outside of the buffer region defined by the array configuration.
    552 *
    553 *
    554 * @name toJSON
    555 * @memberof ndarray.prototype
    556 * @type {Function}
    557 * @returns {Object} serialized ndarray
    558 *
    559 * @example
    560 * var buffer = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
    561 * var shape = [ 3, 2 ];
    562 * var strides = [ 2, 1 ];
    563 * var offset = 2;
    564 *
    565 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    566 *
    567 * var o = x.toJSON();
    568 * // e.g., returns { 'type': 'ndarray', 'dtype': 'generic', 'flags': {...}, 'offset': 0, 'order': 'row-major', 'shape': [ 3, 2 ], 'strides': [ 2, 1 ], 'data': [ 3, 4, 5, 6, 7, 8 ] }
    569 */
    570 setReadOnly( ndarray.prototype, 'toJSON', toJSON );
    571 
    572 /**
    573 * Serializes ndarray meta data to a `DataView`.
    574 *
    575 * ## Notes
    576 *
    577 * -   Meta data format:
    578 *
    579 *     ```text
    580 *     | <endianness> (1 byte) | <dtype> (2 bytes) | <ndims> (8 bytes) | <shape> (ndims*8 bytes) | <strides> (ndims*8 bytes) | <offset> (8 bytes) | <order> (1 byte) | <mode> (1 byte) | <nsubmodes> (8 bytes) | <submodes> (nsubmodes*1 bytes) |
    581 *     ```
    582 *
    583 *     where `strides` and `offset` are in units of bytes.
    584 *
    585 * -   If the endianness is `1`, the byte order is little endian. If the endianness is `0`, the byte order is big endian.
    586 *
    587 * -   Serialization is performed according to host byte order (endianness).
    588 *
    589 * -   Consumers of this method should treat the returned `DataView` as **immutable**. Otherwise, mutation can invalidate meta data and potentially affect other consumers.
    590 *
    591 * @private
    592 * @name __array_meta_dataview__
    593 * @memberof ndarray.prototype
    594 * @type {Function}
    595 * @returns {DataView} serialized meta data
    596 *
    597 * @example
    598 * var buffer = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
    599 * var shape = [ 3, 2 ];
    600 * var strides = [ 2, 1 ];
    601 * var offset = 2;
    602 *
    603 * var x = ndarray( 'generic', buffer, shape, strides, offset, 'row-major' );
    604 *
    605 * var dv = x.__array_meta_dataview__();
    606 * // returns <DataView>
    607 */
    608 setReadOnly( ndarray.prototype, '__array_meta_dataview__', ( hasBigIntSupport() ) ? meta2dataview : meta2dataviewPolyfill );
    609 
    610 
    611 // EXPORTS //
    612 
    613 module.exports = ndarray;