From 1ddcfc403144749287d1d1dff42547b8a238eba8 Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Wed, 25 Sep 2024 06:49:14 +0000 Subject: [PATCH] Auto-generated commit --- CHANGELOG.md | 24 + CONTRIBUTORS | 1 + fixed-endian-factory/README.md | 503 ++++++++++++ .../benchmark/benchmark.from.js | 311 ++++++++ .../benchmark/benchmark.get.js | 90 +++ .../benchmark/benchmark.instantiation.js | 440 +++++++++++ .../benchmark/benchmark.js | 44 +- .../benchmark/benchmark.of.js | 74 ++ .../benchmark/benchmark.property_access.js | 127 +++ .../benchmark/benchmark.set.js | 214 +++++ .../benchmark/benchmark.set.length.js | 115 +++ .../benchmark/benchmark.to_string.js | 55 ++ .../benchmark/benchmark.to_string.length.js | 99 +++ fixed-endian-factory/examples/index.js | 44 ++ .../lib/from_iterator.js | 0 .../lib/from_iterator_map.js | 0 fixed-endian-factory/lib/index.js | 106 +++ fixed-endian-factory/lib/main.js | 731 ++++++++++++++++++ fixed-endian-factory/package.json | 66 ++ fixed-endian-factory/test/test.js | 35 + .../benchmark/benchmark.from.js | 2 +- fixed-endian-float64/lib/main.js | 620 +-------------- 22 files changed, 3063 insertions(+), 638 deletions(-) create mode 100644 fixed-endian-factory/README.md create mode 100644 fixed-endian-factory/benchmark/benchmark.from.js create mode 100644 fixed-endian-factory/benchmark/benchmark.get.js create mode 100644 fixed-endian-factory/benchmark/benchmark.instantiation.js rename fixed-endian-float64/lib/from_array.js => fixed-endian-factory/benchmark/benchmark.js (53%) create mode 100644 fixed-endian-factory/benchmark/benchmark.of.js create mode 100644 fixed-endian-factory/benchmark/benchmark.property_access.js create mode 100644 fixed-endian-factory/benchmark/benchmark.set.js create mode 100644 fixed-endian-factory/benchmark/benchmark.set.length.js create mode 100644 fixed-endian-factory/benchmark/benchmark.to_string.js create mode 100644 fixed-endian-factory/benchmark/benchmark.to_string.length.js create mode 100644 fixed-endian-factory/examples/index.js rename {fixed-endian-float64 => fixed-endian-factory}/lib/from_iterator.js (100%) rename {fixed-endian-float64 => fixed-endian-factory}/lib/from_iterator_map.js (100%) create mode 100644 fixed-endian-factory/lib/index.js create mode 100644 fixed-endian-factory/lib/main.js create mode 100644 fixed-endian-factory/package.json create mode 100644 fixed-endian-factory/test/test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a5f9496..e5333bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -430,6 +430,28 @@ This release closes the following issue: +
+ +#### [@stdlib/array/fixed-endian-factory](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/fixed-endian-factory) + +
+ +
+ +##### Features + +- [`a3a04e3`](https://github.com/stdlib-js/stdlib/commit/a3a04e32057b878529b86180e38ed3ae383c34ef) - add `array/fixed-endian-factory` + +
+ + + +
+ +
+ + +
#### [@stdlib/array/fixed-endian-float64](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/fixed-endian-float64) @@ -514,6 +536,8 @@ A total of 7 people contributed to this release. Thank you to the following cont
+- [`7d9b31b`](https://github.com/stdlib-js/stdlib/commit/7d9b31bcaf049f263228d7d5c020bb24c408e6d7) - **refactor:** use `array/fixed-endian-factory` _(by Athan Reines)_ +- [`a3a04e3`](https://github.com/stdlib-js/stdlib/commit/a3a04e32057b878529b86180e38ed3ae383c34ef) - **feat:** add `array/fixed-endian-factory` _(by Athan Reines)_ - [`5742947`](https://github.com/stdlib-js/stdlib/commit/5742947f31198648b2f753e1f9322367c9e3ae06) - **feat:** add `array/base/cuany-by-right` [(#2667)](https://github.com/stdlib-js/stdlib/pull/2667) _(by DebashisMaharana, Philipp Burckhardt)_ - [`8f72b43`](https://github.com/stdlib-js/stdlib/commit/8f72b432c0fc81a78641d5689722ecc9671c6f02) - **style:** add missing spaces around parentheses _(by Philipp Burckhardt)_ - [`73266bf`](https://github.com/stdlib-js/stdlib/commit/73266bf9d7f82198bd752dafccedbc017d8c8bb1) - **feat:** add `array/base/cuany-by` [(#2818)](https://github.com/stdlib-js/stdlib/pull/2818) _(by yaswanth, Philipp Burckhardt)_ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 3a0c5470..338044b8 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -21,6 +21,7 @@ Christopher Dambamuromo Dan Rose Daniel Killenberger Daniel Yu <40680511+Daniel777y@users.noreply.github.com> +DebashisMaharana <145602692+DevMhrn@users.noreply.github.com> Dominik Moritz Dorrin Sotoudeh EuniceSim142 <77243938+EuniceSim142@users.noreply.github.com> diff --git a/fixed-endian-factory/README.md b/fixed-endian-factory/README.md new file mode 100644 index 00000000..9ae9db34 --- /dev/null +++ b/fixed-endian-factory/README.md @@ -0,0 +1,503 @@ + + +# fixedEndianFactory + +> Return a typed array constructor for creating typed arrays having a specified byte order. + + + +
+ +In contrast to built-in typed array constructors which store values according to the host platform byte order, the typed array constructors returned by the factory function allow enforcing a specific byte order. Such enforcement can be particularly advantageous when working with memory buffers which do not necessarily follow host platform byte order, such as [WebAssembly memory][@stdlib/wasm/memory]. + +
+ + + + + +
+ +## Usage + +```javascript +var fixedEndianFactory = require( '@stdlib/array/fixed-endian-factory' ); +``` + +#### fixedEndianFactory( dtype ) + +Returns a typed array constructor for creating typed arrays having a specified [data type][@stdlib/array/typed-dtypes] and byte order. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); +// returns + +Float32ArrayFE = fixedEndianFactory( 'float32' ); +// returns +``` + +* * * + +### Typed Array Constructor + +#### TypedArrayFE( endianness ) + +A typed array constructor which returns a typed array representing values stored in a specified byte order. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian' ); +// returns +``` + +#### TypedArrayFE( endianness, length ) + +Returns a typed array having a specified length and byte order. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +// returns +``` + +#### TypedArrayFE( endianness, typedarray ) + +Creates a typed array from another typed array. + +```javascript +var Float32Array = require( '@stdlib/array/float32' ); + +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr1 = new Float32Array( [ 0.5, 0.5, 0.5 ] ); +var arr2 = new Float64ArrayFE( 'little-endian', arr1 ); +// returns + +var v = arr2.get( 0 ); +// returns 0.5 +``` + +#### TypedArrayFE( endianness, obj ) + +Creates a typed array from an array-like object or iterable. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', [ 0.5, 0.5, 0.5 ] ); +// returns + +var v = arr.get( 0 ); +// returns 0.5 +``` + +#### TypedArrayFE( endianness, buffer\[, byteOffset\[, length]] ) + +Returns a typed array view of an [`ArrayBuffer`][@stdlib/array/buffer]. + +```javascript +var ArrayBuffer = require( '@stdlib/array/buffer' ); + +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var buf = new ArrayBuffer( 32 ); +var arr = new Float64ArrayFE( 'little-endian', buf, 0, 4 ); +// returns +``` + +* * * + +### Typed Array Properties + + + +#### TypedArrayFE.BYTES_PER_ELEMENT + +Number of bytes per view element. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var nbytes = Float64ArrayFE.BYTES_PER_ELEMENT; +// returns 8 +``` + + + +#### TypedArrayFE.name + +Typed array constructor name. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var str = Float64ArrayFE.name; +// returns 'Float64ArrayFE' +``` + + + +#### TypedArrayFE.prototype.buffer + +**Read-only** property which returns the [`ArrayBuffer`][@stdlib/array/buffer] referenced by the typed array. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +var buf = arr.buffer; +// returns +``` + + + +#### TypedArrayFE.prototype.byteLength + +**Read-only** property which returns the length (in bytes) of the typed array. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +var byteLength = arr.byteLength; +// returns 40 +``` + + + +#### TypedArrayFE.prototype.byteOffset + +**Read-only** property which returns the offset (in bytes) of the typed array from the start of its [`ArrayBuffer`][@stdlib/array/buffer]. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +var byteOffset = arr.byteOffset; +// returns 0 +``` + + + +#### TypedArrayFE.prototype.BYTES_PER_ELEMENT + +Number of bytes per view element. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +var nbytes = arr.BYTES_PER_ELEMENT; +// returns 8 +``` + + + +#### TypedArrayFE.prototype.length + +**Read-only** property which returns the number of view elements. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 5 ); +var len = arr.length; +// returns 5 +``` + +* * * + +### Typed Array Methods + + + +#### TypedArrayFE.from( endianness, src\[, map\[, thisArg]] ) + +Creates a new typed array from an array-like object or an iterable. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = Float64ArrayFE.from( 'little-endian', [ 1.0, -1.0 ] ); +// returns + +var v = arr.get( 0 ); +// returns 1.0 +``` + +To invoke a function for each `src` value, provide a callback function. + +```javascript +function mapFcn( v ) { + return v * 2.0; +} + +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = Float64ArrayFE.from( 'little-endian', [ 1.0, -1.0 ], mapFcn ); +// returns + +var v = arr.get( 0 ); +// returns 2.0 +``` + +A callback function is provided two arguments: + +- **value**: source value. +- **index**: source index. + +To set the callback execution context, provide a `thisArg`. + +```javascript +function mapFcn( v ) { + this.count += 1; + return v * 2.0; +} + +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var ctx = { + 'count': 0 +}; + +var arr = Float64ArrayFE.from( 'little-endian', [ 1.0, -1.0 ], mapFcn, ctx ); +// returns + +var v = arr.get( 0 ); +// returns 2.0 + +var n = ctx.count; +// returns 2 +``` + + + +#### TypedArrayFE.of( endianness, element0\[, element1\[, ...elementN]] ) + +Creates a new typed array from a variable number of arguments. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = Float64ArrayFE.of( 'little-endian', 1.0, -1.0 ); +// returns + +var v = arr.get( 0 ); +// returns 1.0 +``` + + + +#### TypedArrayFE.prototype.get( i ) + +Returns an array element located at a nonnegative integer position (index) `i`. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 10 ); + +// Set the first element: +arr.set( 1.0, 0 ); + +// Get the first element: +var v = arr.get( 0 ); +// returns 1.0 +``` + +If provided an out-of-bounds index, the method returns `undefined`. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', 10 ); + +var v = arr.get( 100 ); +// returns undefined +``` + + + +#### TypedArrayFE.prototype.set( arr\[, offset] ) + +Sets array elements. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', [ 1.0, 2.0, 3.0 ] ); +// returns + +var v = arr.get( 0 ); +// returns 1.0 + +v = arr.get( 1 ); +// returns 2.0 + +// Set the first two array elements: +arr.set( [ 4.0, 5.0 ] ); + +v = arr.get( 0 ); +// returns 4.0 + +v = arr.get( 1 ); +// returns 5.0 +``` + +By default, the method starts writing values at the first array index. To specify an alternative index, provide an index `offset`. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', [ 1.0, 2.0, 3.0 ] ); +// returns + +// Set the last two array elements: +arr.set( [ 4.0, 5.0 ], 1 ); + +var v = arr.get( 1 ); +// returns 4.0 + +v = arr.get( 2 ); +// returns 5.0 +``` + +A few notes: + +- If `i` is out-of-bounds, the method throws an error. +- If a target array cannot accommodate all values (i.e., the length of source array plus `i` exceeds the target array length), the method throws an error. +- If provided a typed array which shares an [`ArrayBuffer`][@stdlib/array/buffer] with the target array, the method will intelligently copy the source range to the destination range. + + + +#### TypedArrayFE.prototype.toString() + +Serializes an array as a string. + +```javascript +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +var arr = new Float64ArrayFE( 'little-endian', [ 1.0, 2.0, 3.0 ] ); + +var str = arr.toString(); +// returns '1,2,3' +``` + +
+ + + + + +
+ +* * * + +## Notes + +- A returned constructor supports the following byte orders: + + - **little-endian**: store values such that bytes are stored from least-to-most significant bytes. This is the dominant ordering for processor architectures and their associated memory. This is also the ordering for [WebAssembly memory][@stdlib/wasm/memory]. + - **big-endian**: store values such that bytes are stored from most-to-least significant bytes. This is the dominant ordering in network protocols. + +- While returned constructors _strive_ to maintain (but do not **guarantee**) consistency with [typed arrays][@stdlib/array/typed], significant deviations from ECMAScript-defined [typed array][@stdlib/array/typed] behavior are as follows: + + - Constructors do **not** require the `new` operator. + - Accessing array elements using bracket syntax (e.g., `X[i]`) is **not** supported. Instead, one **must** use the `.get()` method. + +
+ + + + + +
+ +* * * + +## Examples + + + +```javascript +var Float64Array = require( '@stdlib/array/float64' ); +var logEach = require( '@stdlib/console/log-each' ); +var fixedEndianFactory = require( '@stdlib/array/fixed-endian-factory' ); + +var Float64ArrayFE = fixedEndianFactory( 'float64' ); + +// Create a typed array by specifying a length: +var out = new Float64ArrayFE( 'little-endian', 3 ); +logEach( '%s', out ); + +// Create a typed array from an array: +var arr = [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ]; +out = new Float64ArrayFE( 'big-endian', arr ); +logEach( '%s', out ); + +// Create a typed array from an array buffer: +arr = new Float64Array( [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ] ); // host byte order +out = new Float64ArrayFE( 'little-endian', arr.buffer ); +logEach( '%s', out ); + +// Create a typed array from an array buffer view: +arr = new Float64Array( [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ] ); // host byte order +out = new Float64ArrayFE( 'big-endian', arr.buffer, 8, 2 ); +logEach( '%s', out ); +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/fixed-endian-factory/benchmark/benchmark.from.js b/fixed-endian-factory/benchmark/benchmark.from.js new file mode 100644 index 00000000..bb4778c7 --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.from.js @@ -0,0 +1,311 @@ +/** +* @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 Float64Array = require( './../../float64' ); +var ITERATOR_SYMBOL = require( '@stdlib/symbol/iterator' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var opts = { + 'skip': ( ITERATOR_SYMBOL === null ) +}; +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+'::typed_array:from', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new Float64Array( 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::typed_array:from:len=5', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new Float64Array( 5 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::typed_array,clbk:from:len=5', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new Float64Array( 5 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf, clbk ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function clbk( v ) { + return v * 2.0; + } +}); + +bench( pkg+'::array:from', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::array:from:len=5', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = [ 1.0, 1.0, 1.0, 1.0, 1.0 ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::array,clbk:from:len=5', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = [ 1.0, 1.0, 1.0, 1.0, 1.0 ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', buf, clbk ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function clbk( v ) { + return v * 2.0; + } +}); + +bench( pkg+'::iterable:from', opts, function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', createIterable() ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function createIterable() { + var out = {}; + out[ ITERATOR_SYMBOL ] = iterator; + return out; + + function iterator() { + return { + 'next': next + }; + } + + function next() { + return { + 'done': true + }; + } + } +}); + +bench( pkg+'::iterable:from:len=5', opts, function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', createIterable() ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function createIterable() { + var out = {}; + out[ ITERATOR_SYMBOL ] = iterator; + return out; + + function iterator() { + var it = { + 'next': next, + 'i': 0, + 'N': 5 + }; + return it; + + function next() { + it.i += 1; + if ( it.i <= it.N ) { + return { + 'value': 1.0 + }; + } + return { + 'done': true + }; + } + } + } +}); + +bench( pkg+'::iterable,clbk:from:len=5', opts, function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.from( 'little-endian', createIterable(), clbk ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); + + function createIterable() { + var out = {}; + out[ ITERATOR_SYMBOL ] = iterator; + return out; + + function iterator() { + var it = { + 'next': next, + 'i': 0, + 'N': 5 + }; + return it; + + function next() { + it.i += 1; + if ( it.i <= it.N ) { + return { + 'value': 1.0 + }; + } + return { + 'done': true + }; + } + } + } + + function clbk( v ) { + return v * 2.0; + } +}); diff --git a/fixed-endian-factory/benchmark/benchmark.get.js b/fixed-endian-factory/benchmark/benchmark.get.js new file mode 100644 index 00000000..92da9fe6 --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.get.js @@ -0,0 +1,90 @@ +/** +* @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 isNumber = require( '@stdlib/assert/is-number' ).isPrimitive; +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+':get:endianness=little-endian', function benchmark( b ) { + var arr; + var N; + var v; + var i; + + arr = []; + for ( i = 0; i < 10; i++ ) { + arr.push( i ); + } + arr = new Float64ArrayFE( 'little-endian', arr ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.get( i%N ); + if ( typeof v !== 'number' ) { + b.fail( 'should return a number' ); + } + } + b.toc(); + if ( !isNumber( v ) ) { + b.fail( 'should return a number' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':get:endianness=big-endian', function benchmark( b ) { + var arr; + var N; + var v; + var i; + + arr = []; + for ( i = 0; i < 10; i++ ) { + arr.push( i ); + } + arr = new Float64ArrayFE( 'big-endian', arr ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.get( i%N ); + if ( typeof v !== 'number' ) { + b.fail( 'should return a number' ); + } + } + b.toc(); + if ( !isNumber( v ) ) { + b.fail( 'should return a number' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-factory/benchmark/benchmark.instantiation.js b/fixed-endian-factory/benchmark/benchmark.instantiation.js new file mode 100644 index 00000000..3142a7ef --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.instantiation.js @@ -0,0 +1,440 @@ +/** +* @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 ArrayBuffer = require( './../../buffer' ); +var Float64Array = require( './../../float64' ); +var ITERATOR_SYMBOL = require( '@stdlib/symbol/iterator' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var opts = { + 'skip': ( ITERATOR_SYMBOL === null ) +}; +var Float64ArrayFE = factory( 'float64' ); + + +// FUNCTIONS // + +/** +* Returns an "iterable" object. +* +* @private +* @returns {Object} iterable object +*/ +function createIterable() { + var out = {}; + out[ ITERATOR_SYMBOL ] = iterator; + return out; + + function iterator() { + return { + 'next': next + }; + } + + function next() { + return { + 'done': true + }; + } +} + + +// MAIN // + +bench( pkg+'::instantiation,new:endianness=little-endian', function benchmark( b ) { + var arr; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian' ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,new:endianness=big-endian', function benchmark( b ) { + var arr; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian' ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,no_new:endianness=little-endian', function benchmark( b ) { + var ctor; + var arr; + var i; + + ctor = Float64ArrayFE; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = ctor( 'little-endian' ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,no_new:endianness=big-endian', function benchmark( b ) { + var ctor; + var arr; + var i; + + ctor = Float64ArrayFE; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = ctor( 'big-endian' ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,length:endianness=little-endian', function benchmark( b ) { + var arr; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', 0 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,length:endianness=big-endian', function benchmark( b ) { + var arr; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', 0 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,typed_array:endianness=little-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new Float64Array( 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,typed_array:endianness=big-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new Float64Array( 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,array:endianness=little-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,array:endianness=big-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = []; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,iterable:endianness=little-endian', opts, function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', createIterable() ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,iterable:endianness=big-endian', opts, function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', createIterable() ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer:endianness=little-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer:endianness=big-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 0 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', buf ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer,byte_offset:endianness=little-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 8 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', buf, 8 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer,byte_offset:endianness=big-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 8 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', buf, 8 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer,byte_offset,length:endianness=little-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 8 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'little-endian', buf, 8, 0 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::instantiation,arraybuffer,byte_offset,length:endianness=big-endian', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = new ArrayBuffer( 8 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = new Float64ArrayFE( 'big-endian', buf, 8, 0 ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-float64/lib/from_array.js b/fixed-endian-factory/benchmark/benchmark.js similarity index 53% rename from fixed-endian-float64/lib/from_array.js rename to fixed-endian-factory/benchmark/benchmark.js index c8cfb23f..619c1f96 100644 --- a/fixed-endian-float64/lib/from_array.js +++ b/fixed-endian-factory/benchmark/benchmark.js @@ -18,29 +18,31 @@ 'use strict'; -// MAIN // +// MODULES // -/** -* Fills an output DataView with double-precision values. -* -* @private -* @param {DataView} view - output data view -* @param {Array} arr - input array -* @param {boolean} isLE - boolean indicating whether the store values in little-endian byte order -* @returns {DataView} output data view -*/ -function fromArray( view, arr, isLE ) { - var len; - var i; +var bench = require( '@stdlib/bench' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); - len = arr.length; - for ( i = 0; i < len; i++ ) { - view.setFloat64( i*8, arr[ i ], isLE ); // FIXME: handle accessor arrays, FIXME: avoid hardcoding bytes per element - } - return view; -} +// MAIN // -// EXPORTS // +bench( pkg, function benchmark( b ) { + var v; + var i; -module.exports = fromArray; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = factory( 'float64' ); + 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/fixed-endian-factory/benchmark/benchmark.of.js b/fixed-endian-factory/benchmark/benchmark.of.js new file mode 100644 index 00000000..273c669a --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.of.js @@ -0,0 +1,74 @@ +/** +* @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 pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+':of', function benchmark( b ) { + var arr; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.of( 'little-endian' ); + if ( arr.length !== 0 ) { + b.fail( 'should have length 0' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':len=5', function benchmark( b ) { + var buf; + var arr; + var i; + + buf = [ 'little-endian', 1.0, 1.0, 1.0, 1.0, 1.0 ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + arr = Float64ArrayFE.of.apply( Float64ArrayFE, buf ); + if ( arr.length !== 5 ) { + b.fail( 'should have length 5' ); + } + } + b.toc(); + if ( !(arr instanceof Float64ArrayFE) ) { + b.fail( 'should return an instance' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-factory/benchmark/benchmark.property_access.js b/fixed-endian-factory/benchmark/benchmark.property_access.js new file mode 100644 index 00000000..e3f26a0f --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.property_access.js @@ -0,0 +1,127 @@ +/** +* @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 isArrayBuffer = require( '@stdlib/assert/is-arraybuffer' ); +var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive; +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+'::get:buffer', function benchmark( b ) { + var arr; + var v; + var i; + + arr = new Float64ArrayFE( 'little-endian' ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Note: the following may be optimized away due to loop invariant code motion and/or other compiler optimizations, rendering this benchmark meaningless... + v = arr.buffer; + if ( typeof v !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isArrayBuffer( v ) ) { + b.fail( 'should return an ArrayBuffer' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::get:byteLength', function benchmark( b ) { + var arr; + var v; + var i; + + arr = new Float64ArrayFE( 'little-endian' ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Note: the following may be optimized away due to loop invariant code motion and/or other compiler optimizations, rendering this benchmark meaningless... + v = arr.byteLength; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( !isNonNegativeInteger( v ) ) { + b.fail( 'should return a nonnegative integer' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::get:byteOffset', function benchmark( b ) { + var arr; + var v; + var i; + + arr = new Float64ArrayFE( 'little-endian' ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Note: the following may be optimized away due to loop invariant code motion and/or other compiler optimizations, rendering this benchmark meaningless... + v = arr.byteOffset; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( !isNonNegativeInteger( v ) ) { + b.fail( 'should return a nonnegative integer' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::get:length', function benchmark( b ) { + var arr; + var v; + var i; + + arr = new Float64ArrayFE( 'little-endian' ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Note: the following may be optimized away due to loop invariant code motion and/or other compiler optimizations, rendering this benchmark meaningless... + v = arr.length; + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( !isNonNegativeInteger( v ) ) { + b.fail( 'should return a nonnegative integer' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-factory/benchmark/benchmark.set.js b/fixed-endian-factory/benchmark/benchmark.set.js new file mode 100644 index 00000000..db914423 --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.set.js @@ -0,0 +1,214 @@ +/** +* @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 Float64Array = require( './../../float64' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+'::number:set:endianness=little-endian', function benchmark( b ) { + var values; + var arr; + var N; + var v; + var i; + + values = []; + for ( i = 0; i < 10; i++ ) { + values.push( i ); + } + arr = new Float64ArrayFE( 'little-endian', values ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.set( values[ (i+1)%N ] ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::number:set:endianness=big-endian', function benchmark( b ) { + var values; + var arr; + var N; + var v; + var i; + + values = []; + for ( i = 0; i < 10; i++ ) { + values.push( i ); + } + arr = new Float64ArrayFE( 'big-endian', values ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.set( values[ (i+1)%N ] ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::array:set:endianness=little-endian', function benchmark( b ) { + var values; + var arr; + var N; + var v; + var i; + + values = []; + for ( i = 0; i < 10; i++ ) { + values.push( i ); + } + arr = new Float64ArrayFE( 'little-endian', values ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.set( [ values[ (i+1)%N ] ] ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::array:set:endianness=big-endian', function benchmark( b ) { + var values; + var arr; + var N; + var v; + var i; + + values = []; + for ( i = 0; i < 10; i++ ) { + values.push( i ); + } + arr = new Float64ArrayFE( 'big-endian', values ); + N = arr.length; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr.set( [ values[ (i+1)%N ] ] ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::typed_array:set:endianness=little-endian', function benchmark( b ) { + var values; + var arr; + var buf; + var N; + var v; + var i; + + values = new Float64Array( 20 ); + N = values.length; + for ( i = 0; i < N; i++ ) { + values[ i ] = i; + } + arr = new Float64ArrayFE( 'little-endian', values ); + buf = new Float64Array( 1 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + buf[ 0 ] = values[ i%N ]; + v = arr.set( buf ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+'::typed_array:set:endianness=big-endian', function benchmark( b ) { + var values; + var arr; + var buf; + var N; + var v; + var i; + + values = new Float64Array( 20 ); + N = values.length; + for ( i = 0; i < N; i++ ) { + values[ i ] = i; + } + arr = new Float64ArrayFE( 'big-endian', values ); + buf = new Float64Array( 1 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + buf[ 0 ] = values[ i%N ]; + v = arr.set( buf ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-factory/benchmark/benchmark.set.length.js b/fixed-endian-factory/benchmark/benchmark.set.length.js new file mode 100644 index 00000000..c459e955 --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.set.length.js @@ -0,0 +1,115 @@ +/** +* @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 randu = require( '@stdlib/random/array/randu' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var values; + var arr1; + var arr2; + var arr3; + var N; + + arr1 = randu( len ); + arr2 = randu( len ); + arr3 = randu( len ); + arr1 = new Float64ArrayFE( 'little-endian', arr1 ); + + values = [ + new Float64ArrayFE( 'little-endian', arr2 ), + new Float64ArrayFE( 'big-endian', arr3 ) + ]; + N = values.length; + + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var v; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = arr1.set( values[ i%N ] ); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + } + b.toc(); + if ( typeof v !== 'undefined' ) { + b.fail( 'should return undefined' ); + } + 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+':set:len='+len, f ); + } +} + +main(); diff --git a/fixed-endian-factory/benchmark/benchmark.to_string.js b/fixed-endian-factory/benchmark/benchmark.to_string.js new file mode 100644 index 00000000..47494aa7 --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.to_string.js @@ -0,0 +1,55 @@ +/** +* @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 pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// MAIN // + +bench( pkg+':toString', function benchmark( b ) { + var out; + var arr; + var i; + + arr = new Float64ArrayFE( 'little-endian', [ 1.0, 2.0, 2.0, 1.0 ] ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = arr.toString(); + if ( typeof out !== 'string' ) { + b.fail( 'should return a string' ); + } + } + b.toc(); + if ( typeof out !== 'string' ) { + b.fail( 'should return a string' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/fixed-endian-factory/benchmark/benchmark.to_string.length.js b/fixed-endian-factory/benchmark/benchmark.to_string.length.js new file mode 100644 index 00000000..1b5abedb --- /dev/null +++ b/fixed-endian-factory/benchmark/benchmark.to_string.length.js @@ -0,0 +1,99 @@ +/** +* @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 zeroTo = require( './../../zero-to' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ); + + +// VARIABLES // + +var Float64ArrayFE = factory( 'float64' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - array length +* @returns {Function} benchmark function +*/ +function createBenchmark( len ) { + var arr = new Float64ArrayFE( 'little-endian', zeroTo( len ) ); + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var out; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = arr.toString(); + if ( typeof out !== 'string' ) { + b.fail( 'should return a string' ); + } + } + b.toc(); + if ( typeof out !== 'string' ) { + b.fail( 'should return a string' ); + } + 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+':toString:len='+len, f ); + } +} + +main(); diff --git a/fixed-endian-factory/examples/index.js b/fixed-endian-factory/examples/index.js new file mode 100644 index 00000000..52a53723 --- /dev/null +++ b/fixed-endian-factory/examples/index.js @@ -0,0 +1,44 @@ +/** +* @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 Float64Array = require( './../../float64' ); +var logEach = require( '@stdlib/console/log-each' ); +var factory = require( './../lib' ); + +var Float64ArrayFE = factory( 'float64' ); + +// Create a typed array by specifying a length: +var out = new Float64ArrayFE( 'little-endian', 3 ); +logEach( '%s', out ); + +// Create a typed array from an array: +var arr = [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ]; +out = new Float64ArrayFE( 'big-endian', arr ); +logEach( '%s', out ); + +// Create a typed array from an array buffer: +arr = new Float64Array( [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ] ); // host byte order +out = new Float64ArrayFE( 'little-endian', arr.buffer ); +logEach( '%s', out ); + +// Create a typed array from an array buffer view: +arr = new Float64Array( [ 1.0, -1.0, -3.14, 3.14, 0.5, 0.5 ] ); // host byte order +out = new Float64ArrayFE( 'big-endian', arr.buffer, 8, 2 ); +logEach( '%s', out ); diff --git a/fixed-endian-float64/lib/from_iterator.js b/fixed-endian-factory/lib/from_iterator.js similarity index 100% rename from fixed-endian-float64/lib/from_iterator.js rename to fixed-endian-factory/lib/from_iterator.js diff --git a/fixed-endian-float64/lib/from_iterator_map.js b/fixed-endian-factory/lib/from_iterator_map.js similarity index 100% rename from fixed-endian-float64/lib/from_iterator_map.js rename to fixed-endian-factory/lib/from_iterator_map.js diff --git a/fixed-endian-factory/lib/index.js b/fixed-endian-factory/lib/index.js new file mode 100644 index 00000000..0183dad6 --- /dev/null +++ b/fixed-endian-factory/lib/index.js @@ -0,0 +1,106 @@ +/** +* @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'; + +/** +* Return a typed array constructor for creating typed arrays having a specified byte order. +* +* @module @stdlib/array/fixed-endian-factory +* +* @example +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian' ); +* // returns +* +* var len = arr.length; +* // returns 0 +* +* @example +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian', 2 ); +* // returns +* +* var len = arr.length; +* // returns 2 +* +* @example +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian', [ 1.0 ] ); +* // returns +* +* var len = arr.length; +* // returns 1 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 16 ); +* var arr = new Float64ArrayFE( 'little-endian', buf ); +* // returns +* +* var len = arr.length; +* // returns 2 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 16 ); +* var arr = new Float64ArrayFE( 'little-endian', buf, 8 ); +* // returns +* +* var len = arr.length; +* // returns 1 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* var factory = require( '@stdlib/array/fixed-endian-factory' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 32 ); +* var arr = new Float64ArrayFE( 'little-endian', buf, 8, 2 ); +* // returns +* +* var len = arr.length; +* // returns 2 +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/fixed-endian-factory/lib/main.js b/fixed-endian-factory/lib/main.js new file mode 100644 index 00000000..e9b44f5e --- /dev/null +++ b/fixed-endian-factory/lib/main.js @@ -0,0 +1,731 @@ +/** +* @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 max-len, no-restricted-syntax, no-invalid-this, max-lines */ + +'use strict'; + +// MODULES // + +var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive; +var isCollection = require( '@stdlib/assert/is-collection' ); +var isArrayBuffer = require( '@stdlib/assert/is-arraybuffer' ); +var isObject = require( '@stdlib/assert/is-object' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var isString = require( '@stdlib/assert/is-string' ).isPrimitive; +var isByteOrder = require( './../../base/assert/is-byte-order' ); +var lowercase = require( '@stdlib/string/base/lowercase' ); +var hasIteratorSymbolSupport = require( '@stdlib/assert/has-iterator-symbol-support' ); +var ITERATOR_SYMBOL = require( '@stdlib/symbol/iterator' ); +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var isPrototypeOf = require( '@stdlib/assert/is-prototype-of' ); // eslint-disable-line stdlib/no-redeclare +var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); +var ArrayBuffer = require( './../../buffer' ); +var DataView = require( './../../dataview' ); +var getter = require( './../../base/getter' ); +var accessorGetter = require( './../../base/accessor-getter' ); +var contains = require( './../../base/assert/contains' ).factory; +var bytesPerElement = require( '@stdlib/ndarray/base/bytes-per-element' ); +var capitalize = require( '@stdlib/string/base/capitalize' ); +var format = require( '@stdlib/string/format' ); +var fromIterator = require( './from_iterator.js' ); +var fromIteratorMap = require( './from_iterator_map.js' ); + + +// VARIABLES // + +var HAS_ITERATOR_SYMBOL = hasIteratorSymbolSupport(); +var DTYPES = [ 'float64', 'float32', 'int32', 'int16', 'uint32', 'uint16' ]; +var DTYPE2SET = { + 'float64': 'setFloat64', + 'float32': 'setFloat32', + 'int32': 'setInt32', + 'int16': 'setInt16', + 'uint32': 'setUint32', + 'uint16': 'setUint16' +}; +var DTYPE2GET = { + 'float64': 'getFloat64', + 'float32': 'getFloat32', + 'int32': 'getInt32', + 'int16': 'getInt16', + 'uint32': 'getUint32', + 'uint16': 'getUint16' +}; +var DTYPE2ARTICLE = { + 'float64': 'a', + 'float32': 'a', + 'int32': 'an', + 'int16': 'an', + 'uint32': 'a', + 'uint16': 'a' +}; +var isDataType = contains( DTYPES ); + + +// FUNCTIONS // + +/** +* Normalizes a byte order value. +* +* @private +* @param {*} value - byte order +* @returns {(string|null)} normalized byte order +*/ +function byteOrder( value ) { + return ( isString( value ) ) ? lowercase( value ) : null; +} + +/** +* Tests whether a provided byte order is little-endian byte order. +* +* @private +* @param {string} value - byte order +* @returns {boolean} boolean indicating whether a byte order is little-endian byte order +*/ +function isLittleEndian( value ) { + return ( value === 'little-endian' ); +} + +/** +* Converts a data type string to a constructor name. +* +* @private +* @param {string} dtype - data type +* @returns {string} constructor name +* +* @example +* var n = dtype2ctor( 'float64' ); +* // returns 'Float64ArrayFE' +* +* @example +* var n = dtype2ctor( 'int32' ); +* // returns 'Int32ArrayFE' +*/ +function dtype2ctor( dtype ) { + return capitalize( dtype ) + 'ArrayFE'; +} + + +// MAIN // + +/** +* Returns a typed array constructor for creating typed arrays having a specified byte order. +* +* @param {string} dtype - typed array data type +* @throws {TypeError} first argument must be a supported data type +* @returns {Function} typed array constructor +* +* @example +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian' ); +* // returns +* +* var len = arr.length; +* // returns 0 +* +* @example +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian', 2 ); +* // returns +* +* var len = arr.length; +* // returns 2 +* +* @example +* var Float64ArrayFE = factory( 'float64' ); +* +* var arr = new Float64ArrayFE( 'little-endian', [ 1.0, 2.0 ] ); +* // returns +* +* var len = arr.length; +* // returns 2 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 16 ); +* var arr = new Float64ArrayFE( 'little-endian', buf ); +* // returns +* +* var len = arr.length; +* // returns 2 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 16 ); +* var arr = new Float64ArrayFE( 'little-endian', buf, 8 ); +* // returns +* +* var len = arr.length; +* // returns 1 +* +* @example +* var ArrayBuffer = require( '@stdlib/array/buffer' ); +* +* var Float64ArrayFE = factory( 'float64' ); +* +* var buf = new ArrayBuffer( 32 ); +* var arr = new Float64ArrayFE( 'little-endian', buf, 8, 2 ); +* // returns +* +* var len = arr.length; +* // returns 2 +*/ +function factory( dtype ) { // eslint-disable-line max-lines-per-function, stdlib/jsdoc-require-throws-tags + var BYTES_PER_ELEMENT; + var CTOR_NAME; + var GETTER; + var SETTER; + + if ( !isDataType( dtype ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a supported data type. Value: `%s`.', dtype ) ); + } + BYTES_PER_ELEMENT = bytesPerElement( dtype ); + CTOR_NAME = dtype2ctor( dtype ); + GETTER = DTYPE2GET[ dtype ]; + SETTER = DTYPE2SET[ dtype ]; + + /** + * Typed array constructor which returns a typed array representing an array of values in a specified byte order. + * + * @private + * @constructor + * @param {string} endianness - byte order + * @param {(NonNegativeInteger|Collection|ArrayBuffer|Iterable)} [arg] - length, typed array, array-like object, buffer, or an iterable + * @param {NonNegativeInteger} [byteOffset=0] - byte offset + * @param {NonNegativeInteger} [length] - view length + * @throws {TypeError} first argument must be a supported byte order + * @throws {TypeError} if provided only two arguments, the second argument must be a valid argument + * @throws {TypeError} byte offset must be a nonnegative integer + * @throws {RangeError} must provide sufficient memory to accommodate byte offset and view length requirements + * @returns {TypedArray} typed array instance + */ + function TypedArray() { + var byteOffset; + var endianness; + var nargs; + var isLE; + var buf; + var len; + var arg; + var tmp; + + nargs = arguments.length; + if ( !(this instanceof TypedArray) ) { + if ( nargs < 2 ) { + return new TypedArray( arguments[0] ); + } + if ( nargs === 2 ) { + return new TypedArray( arguments[0], arguments[1] ); + } + if ( nargs === 3 ) { + return new TypedArray( arguments[0], arguments[1], arguments[2] ); + } + return new TypedArray( arguments[0], arguments[1], arguments[2], arguments[3] ); + } + endianness = byteOrder( arguments[ 0 ] ); + if ( endianness === null || !isByteOrder( endianness ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', arguments[ 0 ] ) ); + } + isLE = isLittleEndian( endianness ); + + nargs -= 1; + + // Create the underlying data buffer... + if ( nargs === 0 ) { + buf = new DataView( new ArrayBuffer( 0 ) ); // backward-compatibility + } else if ( nargs === 1 ) { + arg = arguments[ nargs ]; + if ( isNonNegativeInteger( arg ) ) { + buf = new DataView( new ArrayBuffer( arg*BYTES_PER_ELEMENT ) ); + } else if ( isCollection( arg ) ) { + buf = fromArray( new DataView( new ArrayBuffer( arg.length*BYTES_PER_ELEMENT ) ), arg, isLE ); + } else if ( isArrayBuffer( arg ) ) { + buf = new DataView( arg ); + } else if ( isObject( arg ) ) { + if ( HAS_ITERATOR_SYMBOL === false ) { + throw new TypeError( format( 'invalid argument. Environment lacks Symbol.iterator support. Must provide a length, ArrayBuffer, typed array, or array-like object. Value: `%s`.', arg ) ); + } + if ( !isFunction( arg[ ITERATOR_SYMBOL ] ) ) { + throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); + } + buf = arg[ ITERATOR_SYMBOL ](); + if ( !isFunction( buf.next ) ) { + throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); + } + tmp = fromIterator( buf ); + buf = fromArray( new DataView( new ArrayBuffer( tmp.length*BYTES_PER_ELEMENT ) ), tmp, isLE ); + } else { + throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); + } + } else { + buf = arguments[ 1 ]; + if ( !isArrayBuffer( buf ) ) { + throw new TypeError( format( 'invalid argument. Must provide an ArrayBuffer. Value: `%s`.', buf ) ); + } + byteOffset = arguments[ 2 ]; + if ( !isNonNegativeInteger( byteOffset ) ) { + throw new TypeError( format( 'invalid argument. Byte offset must be a nonnegative integer. Value: `%s`.', byteOffset ) ); + } + if ( nargs === 2 ) { + buf = new DataView( buf, byteOffset ); + } else { + len = arguments[ 3 ]; + if ( !isNonNegativeInteger( len ) ) { + throw new TypeError( format( 'invalid argument. Length must be a nonnegative integer. Value: `%s`.', len ) ); + } + len *= BYTES_PER_ELEMENT; + if ( len > (buf.byteLength-byteOffset) ) { + throw new RangeError( format( 'invalid arguments. ArrayBuffer has insufficient capacity. Either decrease the array length or provide a bigger buffer. Minimum capacity: `%u`.', len ) ); + } + buf = new DataView( buf, byteOffset, len ); + } + } + setReadOnly( this, '_buffer', buf ); + setReadOnly( this, '_length', buf.byteLength/BYTES_PER_ELEMENT ); + setReadOnly( this, '_isLE', isLE ); + + return this; + } + + /** + * Size (in bytes) of each array element. + * + * @private + * @name BYTES_PER_ELEMENT + * @memberof TypedArray + * @readonly + * @type {PositiveInteger} + */ + setReadOnly( TypedArray, 'BYTES_PER_ELEMENT', BYTES_PER_ELEMENT ); + + /** + * Constructor name. + * + * @private + * @name name + * @memberof TypedArray + * @readonly + * @type {string} + */ + setReadOnly( TypedArray, 'name', CTOR_NAME ); + + /** + * Creates a new typed array from an array-like object or an iterable. + * + * @private + * @name from + * @memberof TypedArray + * @type {Function} + * @param {string} endianness - byte order + * @param {(Collection|Iterable)} src - array-like object or iterable + * @param {Function} [clbk] - callback to invoke for each source element + * @param {*} [thisArg] - context + * @throws {TypeError} `this` context must be a constructor + * @throws {TypeError} `this` must be a typed array constructor + * @throws {TypeError} first argument must be a supported byte order + * @throws {TypeError} second argument must be an array-like object or an iterable + * @throws {TypeError} third argument must be a function + * @returns {TypedArray} typed array instance + */ + setReadOnly( TypedArray, 'from', function from( endianness, src ) { + var thisArg; + var order; + var nargs; + var clbk; + var isLE; + var out; + var buf; + var tmp; + var get; + var len; + var i; + if ( !isFunction( this ) ) { + throw new TypeError( 'invalid invocation. `this` context must be a constructor.' ); + } + if ( !isTypedArrayConstructor( this ) ) { + throw new TypeError( format( 'invalid invocation. `this` is not %s %s.', DTYPE2ARTICLE[ dtype ], CTOR_NAME ) ); + } + order = byteOrder( endianness ); + if ( order === null || !isByteOrder( order ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', endianness ) ); + } + isLE = isLittleEndian( order ); + + nargs = arguments.length; + if ( nargs > 2 ) { + clbk = arguments[ 2 ]; + if ( !isFunction( clbk ) ) { + throw new TypeError( format( 'invalid argument. Third argument must be a function. Value: `%s`.', clbk ) ); + } + if ( nargs > 3 ) { + thisArg = arguments[ 3 ]; + } + } + if ( isCollection( src ) ) { + if ( clbk ) { + len = src.length; + if ( src.get && src.set ) { + get = accessorGetter( 'default' ); + } else { + get = getter( 'default' ); + } + out = new this( order, len ); + buf = out._buffer; // eslint-disable-line no-underscore-dangle + for ( i = 0; i < len; i++ ) { + buf[ SETTER ]( i*BYTES_PER_ELEMENT, clbk.call( thisArg, get( src, i ), i ), isLE ); + } + return out; + } + return new this( order, src ); + } + if ( isObject( src ) && HAS_ITERATOR_SYMBOL && isFunction( src[ ITERATOR_SYMBOL ] ) ) { + buf = src[ ITERATOR_SYMBOL ](); + if ( !isFunction( buf.next ) ) { + throw new TypeError( format( 'invalid argument. Second argument must be an array-like object or an iterable. Value: `%s`.', src ) ); + } + if ( clbk ) { + tmp = fromIteratorMap( buf, clbk, thisArg ); + } else { + tmp = fromIterator( buf ); + } + len = tmp.length; + out = new this( order, len ); + buf = out._buffer; // eslint-disable-line no-underscore-dangle + for ( i = 0; i < len; i++ ) { + buf[ SETTER ]( i*BYTES_PER_ELEMENT, tmp[ i ], isLE ); + } + return out; + } + throw new TypeError( format( 'invalid argument. Second argument must be an array-like object or an iterable. Value: `%s`.', src ) ); + }); + + /** + * Creates a new typed array from a variable number of arguments. + * + * @private + * @name of + * @memberof TypedArray + * @type {Function} + * @param {string} endianness - byte order + * @param {...*} element - array elements + * @throws {TypeError} `this` context must be a constructor + * @throws {TypeError} `this` must be a typed array constructor + * @throws {TypeError} first argument must be a supported byte order + * @returns {TypedArray} typed array instance + */ + setReadOnly( TypedArray, 'of', function of( endianness ) { + var order; + var args; + var i; + if ( !isFunction( this ) ) { + throw new TypeError( 'invalid invocation. `this` context must be a constructor.' ); + } + if ( !isTypedArrayConstructor( this ) ) { + throw new TypeError( format( 'invalid invocation. `this` is not %s %s.', DTYPE2ARTICLE[ dtype ], CTOR_NAME ) ); + } + order = byteOrder( endianness ); + if ( order === null || !isByteOrder( order ) ) { + throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', endianness ) ); + } + args = []; + for ( i = 1; i < arguments.length; i++ ) { + args.push( arguments[ i ] ); + } + return new this( order, args ); + }); + + /** + * Pointer to the underlying data buffer. + * + * @private + * @name buffer + * @memberof TypedArray.prototype + * @readonly + * @type {ArrayBuffer} + */ + setReadOnlyAccessor( TypedArray.prototype, 'buffer', function get() { + return this._buffer.buffer; + }); + + /** + * Size (in bytes) of the array. + * + * @private + * @name byteLength + * @memberof TypedArray.prototype + * @readonly + * @type {NonNegativeInteger} + */ + setReadOnlyAccessor( TypedArray.prototype, 'byteLength', function get() { + return this._buffer.byteLength; + }); + + /** + * Offset (in bytes) of the array from the start of its underlying `ArrayBuffer`. + * + * @private + * @name byteOffset + * @memberof TypedArray.prototype + * @readonly + * @type {NonNegativeInteger} + */ + setReadOnlyAccessor( TypedArray.prototype, 'byteOffset', function get() { + return this._buffer.byteOffset; + }); + + /** + * Size (in bytes) of each array element. + * + * @private + * @name BYTES_PER_ELEMENT + * @memberof TypedArray.prototype + * @readonly + * @type {PositiveInteger} + */ + setReadOnly( TypedArray.prototype, 'BYTES_PER_ELEMENT', TypedArray.BYTES_PER_ELEMENT ); + + /** + * Returns an array element. + * + * @private + * @name get + * @memberof TypedArray.prototype + * @type {Function} + * @param {NonNegativeInteger} idx - element index + * @throws {TypeError} `this` must be a typed array instance + * @throws {TypeError} must provide a nonnegative integer + * @returns {(*|void)} array element + */ + setReadOnly( TypedArray.prototype, 'get', function get( idx ) { + if ( !isTypedArray( this ) ) { + throw new TypeError( format( 'invalid invocation. `this` is not %s %s.', DTYPE2ARTICLE[ dtype ], CTOR_NAME ) ); + } + if ( !isNonNegativeInteger( idx ) ) { + throw new TypeError( format( 'invalid argument. Must provide a nonnegative integer. Value: `%s`.', idx ) ); + } + if ( idx >= this._length ) { + return; + } + return this._buffer[ GETTER ]( idx*BYTES_PER_ELEMENT, this._isLE ); + }); + + /** + * Number of array elements. + * + * @private + * @name length + * @memberof TypedArray.prototype + * @readonly + * @type {NonNegativeInteger} + */ + setReadOnlyAccessor( TypedArray.prototype, 'length', function get() { + return this._length; + }); + + /** + * Sets an array element. + * + * ## Notes + * + * - When provided a typed array, we must check whether the source array shares the same buffer as the target array and whether the underlying memory overlaps. In particular, we are concerned with the following scenario: + * + * ```text + * buf: --------------------- + * src: --------------------- + * ``` + * + * In the above, as we copy values from `src`, we will overwrite values in the `src` view, resulting in duplicated values copied into the end of `buf`, which is not intended. Hence, to avoid overwriting source values, we must **copy** source values to a temporary array. + * + * In the other overlapping scenario, + * + * ```text + * buf: --------------------- + * src: --------------------- + * ``` + * + * by the time we begin copying into the overlapping region, we are copying from the end of `src`, a non-overlapping region, which means we don't run the risk of copying copied values, rather than the original `src` values, as intended. + * + * @private + * @name set + * @memberof TypedArray.prototype + * @type {Function} + * @param {(Collection|TypedArray|*)} value - value(s) + * @param {NonNegativeInteger} [i=0] - element index at which to start writing values + * @throws {TypeError} `this` must be a typed array instance + * @throws {TypeError} index argument must be a nonnegative integer + * @throws {RangeError} index argument is out-of-bounds + * @throws {RangeError} target array lacks sufficient storage to accommodate source values + * @returns {void} + */ + setReadOnly( TypedArray.prototype, 'set', function set( value ) { + var sbuf; + var idx; + var buf; + var tmp; + var get; + var N; + var i; + var j; + if ( !isTypedArray( this ) ) { + throw new TypeError( format( 'invalid invocation. `this` is not %s %s.', DTYPE2ARTICLE[ dtype ], CTOR_NAME ) ); + } + buf = this._buffer; + if ( arguments.length > 1 ) { + idx = arguments[ 1 ]; + if ( !isNonNegativeInteger( idx ) ) { + throw new TypeError( format( 'invalid argument. Index argument must be a nonnegative integer. Value: `%s`.', idx ) ); + } + } else { + idx = 0; + } + if ( isCollection( value ) ) { + N = value.length; + if ( idx+N > this._length ) { + throw new RangeError( 'invalid arguments. Target array lacks sufficient storage to accommodate source values.' ); + } + sbuf = value; + if ( sbuf.get && sbuf.set ) { + get = accessorGetter( 'default' ); + } else { + get = getter( 'default' ); + } + // Check for overlapping memory... + j = buf.byteOffset + (idx*BYTES_PER_ELEMENT); + if ( + sbuf.buffer === buf.buffer && + ( + sbuf.byteOffset < j && + sbuf.byteOffset+sbuf.byteLength > j + ) + ) { + // We need to copy source values... + tmp = []; + for ( i = 0; i < value.length; i++ ) { + tmp.push( get( value, i ) ); + } + sbuf = tmp; + get = getter( 'default' ); + } + for ( i = 0; i < N; idx++, i++ ) { + buf[ SETTER ]( idx*BYTES_PER_ELEMENT, get( sbuf, i ), this._isLE ); + } + return; + } + if ( idx >= this._length ) { + throw new RangeError( format( 'invalid argument. Index argument is out-of-bounds. Value: `%u`.', idx ) ); + } + buf[ SETTER ]( idx*BYTES_PER_ELEMENT, value, this._isLE ); + }); + + /** + * Serializes an array as a string. + * + * @private + * @name toString + * @memberof TypedArray.prototype + * @type {Function} + * @throws {TypeError} `this` must be a typed array instance + * @returns {string} string representation + */ + setReadOnly( TypedArray.prototype, 'toString', function toString() { + var out; + var buf; + var i; + if ( !isTypedArray( this ) ) { + throw new TypeError( format( 'invalid invocation. `this` is not %s %s.', DTYPE2ARTICLE[ dtype ], CTOR_NAME ) ); + } + out = []; + buf = this._buffer; + for ( i = 0; i < this._length; i++ ) { + out.push( buf[ GETTER ]( i*BYTES_PER_ELEMENT, this._isLE ) ); + } + return out.join( ',' ); + }); + + return TypedArray; + + /** + * Returns a boolean indicating if a value is a typed array constructor. + * + * @private + * @param {*} value - value to test + * @returns {boolean} boolean indicating if a value is a typed array constructor + */ + function isTypedArrayConstructor( value ) { + return ( value === TypedArray ); + } + + /** + * Returns a boolean indicating if a value is a typed array. + * + * @private + * @param {*} value - value to test + * @returns {boolean} boolean indicating if a value is a typed array + */ + function isTypedArray( value ) { + return ( + typeof value === 'object' && + value !== null && + ( + value.constructor.name === CTOR_NAME || + isPrototypeOf( value, TypedArray.prototype ) + ) && + value.BYTES_PER_ELEMENT === BYTES_PER_ELEMENT + ); + } + + /** + * Fills an output DataView with array values. + * + * @private + * @param {DataView} view - output data view + * @param {Array} arr - input array + * @param {boolean} isLE - boolean indicating whether to store values in little-endian byte order + * @returns {DataView} output data view + */ + function fromArray( view, arr, isLE ) { + var len; + var get; + var i; + + len = arr.length; + if ( arr.get && arr.set ) { + get = accessorGetter( 'default' ); + } else { + get = getter( 'default' ); + } + for ( i = 0; i < len; i++ ) { + view[ SETTER ]( i*BYTES_PER_ELEMENT, get( arr, i ), isLE ); + } + return view; + } +} + + +// EXPORTS // + +module.exports = factory; diff --git a/fixed-endian-factory/package.json b/fixed-endian-factory/package.json new file mode 100644 index 00000000..26450528 --- /dev/null +++ b/fixed-endian-factory/package.json @@ -0,0 +1,66 @@ +{ + "name": "@stdlib/array/fixed-endian-factory", + "version": "0.0.0", + "description": "Return a typed array constructor for creating typed arrays having a specified byte order.", + "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", + "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", + "typed", + "typed array", + "typed-array", + "factory", + "endian", + "little-endian", + "big-endian", + "byte-order" + ] +} diff --git a/fixed-endian-factory/test/test.js b/fixed-endian-factory/test/test.js new file mode 100644 index 00000000..99d011d0 --- /dev/null +++ b/fixed-endian-factory/test/test.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'; + +// MODULES // + +var tape = require( 'tape' ); +var factory = require( './../lib' ); + + +// 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(); +}); + +// TODO: add tests diff --git a/fixed-endian-float64/benchmark/benchmark.from.js b/fixed-endian-float64/benchmark/benchmark.from.js index 62c07c39..06f8c4fb 100644 --- a/fixed-endian-float64/benchmark/benchmark.from.js +++ b/fixed-endian-float64/benchmark/benchmark.from.js @@ -41,7 +41,7 @@ bench( pkg+'::typed_array:from', function benchmark( b ) { var arr; var i; - buf = new Float64Array( 'little-endian', 0 ); + buf = new Float64Array( 0 ); b.tic(); for ( i = 0; i < b.iterations; i++ ) { diff --git a/fixed-endian-float64/lib/main.js b/fixed-endian-float64/lib/main.js index ac480bbb..4ba443b8 100644 --- a/fixed-endian-float64/lib/main.js +++ b/fixed-endian-float64/lib/main.js @@ -16,95 +16,11 @@ * limitations under the License. */ -/* eslint-disable max-len, no-restricted-syntax, no-invalid-this */ - 'use strict'; // MODULES // -var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive; -var isCollection = require( '@stdlib/assert/is-collection' ); -var isArrayBuffer = require( '@stdlib/assert/is-arraybuffer' ); -var isObject = require( '@stdlib/assert/is-object' ); -var isFunction = require( '@stdlib/assert/is-function' ); -var isString = require( '@stdlib/assert/is-string' ).isPrimitive; -var contains = require( './../../base/assert/contains' ).factory; -var lowercase = require( '@stdlib/string/base/lowercase' ); -var hasIteratorSymbolSupport = require( '@stdlib/assert/has-iterator-symbol-support' ); -var ITERATOR_SYMBOL = require( '@stdlib/symbol/iterator' ); -var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); -var isPrototypeOf = require( '@stdlib/assert/is-prototype-of' ); // eslint-disable-line stdlib/no-redeclare -var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); -var ArrayBuffer = require( './../../buffer' ); -var DataView = require( './../../dataview' ); -var getter = require( './../../base/getter' ); -var accessorGetter = require( './../../base/accessor-getter' ); -var format = require( '@stdlib/string/format' ); -var fromIterator = require( './from_iterator.js' ); -var fromIteratorMap = require( './from_iterator_map.js' ); -var fromArray = require( './from_array.js' ); - - -// VARIABLES // - -var BYTES_PER_ELEMENT = 8; // 8 bytes per double -var HAS_ITERATOR_SYMBOL = hasIteratorSymbolSupport(); -var isByteOrder = contains( [ 'little-endian', 'big-endian' ] ); - - -// FUNCTIONS // - -/** -* Normalizes a byte order value. -* -* @private -* @param {*} value - byte order -* @returns {(string|null)} normalized byte order -*/ -function byteOrder( value ) { - return ( isString( value ) ) ? lowercase( value ) : null; -} - -/** -* Tests whether a provided byte order is little-endian byte order. -* -* @private -* @param {string} value - byte order -* @returns {boolean} boolean indicating whether a byte order is little-endian byte order -*/ -function isLittleEndian( value ) { - return ( value === 'little-endian' ); -} - -/** -* Returns a boolean indicating if a value is a `Float64ArrayFE` constructor. -* -* @private -* @param {*} value - value to test -* @returns {boolean} boolean indicating if a value is a `Float64ArrayFE` constructor -*/ -function isFloat64ArrayFEConstructor( value ) { // eslint-disable-line id-length - return ( value === Float64ArrayFE ); -} - -/** -* Returns a boolean indicating if a value is a `Float64ArrayFE`. -* -* @private -* @param {*} value - value to test -* @returns {boolean} boolean indicating if a value is a `Float64ArrayFE` -*/ -function isFloat64ArrayFE( value ) { - return ( - typeof value === 'object' && - value !== null && - ( - value.constructor.name === 'Float64ArrayFE' || - isPrototypeOf( value, Float64ArrayFE.prototype ) - ) && - value.BYTES_PER_ELEMENT === BYTES_PER_ELEMENT - ); -} +var factory = require( './../../fixed-endian-factory' ); // MAIN // @@ -112,7 +28,9 @@ function isFloat64ArrayFE( value ) { /** * Typed array constructor which returns a typed array representing an array of double-precision floating-point numbers in a specified byte order. * +* @name Float64ArrayFE * @constructor +* @type {Function} * @param {string} endianness - byte order * @param {(NonNegativeInteger|Collection|ArrayBuffer|Iterable)} [arg] - length, typed array, array-like object, buffer, or an iterable * @param {NonNegativeInteger} [byteOffset=0] - byte offset @@ -174,537 +92,7 @@ function isFloat64ArrayFE( value ) { * var len = arr.length; * // returns 2 */ -function Float64ArrayFE() { - var byteOffset; - var endianness; - var nargs; - var isLE; - var buf; - var len; - var arg; - var tmp; - - nargs = arguments.length; - if ( !(this instanceof Float64ArrayFE) ) { - if ( nargs < 2 ) { - return new Float64ArrayFE( arguments[0] ); - } - if ( nargs === 2 ) { - return new Float64ArrayFE( arguments[0], arguments[1] ); - } - if ( nargs === 3 ) { - return new Float64ArrayFE( arguments[0], arguments[1], arguments[2] ); - } - return new Float64ArrayFE( arguments[0], arguments[1], arguments[2], arguments[3] ); - } - endianness = byteOrder( arguments[ 0 ] ); - if ( endianness === null || !isByteOrder( endianness ) ) { - throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', arguments[ 0 ] ) ); - } - isLE = isLittleEndian( endianness ); - - nargs -= 1; - - // Create the underlying data buffer... - if ( nargs === 0 ) { - buf = new DataView( new ArrayBuffer( 0 ) ); // backward-compatibility - } else if ( nargs === 1 ) { - arg = arguments[ nargs ]; - if ( isNonNegativeInteger( arg ) ) { - buf = new DataView( new ArrayBuffer( arg*BYTES_PER_ELEMENT ) ); - } else if ( isCollection( arg ) ) { - buf = fromArray( new DataView( new ArrayBuffer( arg.length*BYTES_PER_ELEMENT ) ), arg, isLE ); - } else if ( isArrayBuffer( arg ) ) { - buf = new DataView( arg ); - } else if ( isObject( arg ) ) { - if ( HAS_ITERATOR_SYMBOL === false ) { - throw new TypeError( format( 'invalid argument. Environment lacks Symbol.iterator support. Must provide a length, ArrayBuffer, typed array, or array-like object. Value: `%s`.', arg ) ); - } - if ( !isFunction( arg[ ITERATOR_SYMBOL ] ) ) { - throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); - } - buf = arg[ ITERATOR_SYMBOL ](); - if ( !isFunction( buf.next ) ) { - throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); - } - tmp = fromIterator( buf ); - buf = fromArray( new DataView( new ArrayBuffer( tmp.length*BYTES_PER_ELEMENT ) ), tmp, isLE ); - } else { - throw new TypeError( format( 'invalid argument. Must provide a length, ArrayBuffer, typed array, array-like object, or an iterable. Value: `%s`.', arg ) ); - } - } else { - buf = arguments[ 1 ]; - if ( !isArrayBuffer( buf ) ) { - throw new TypeError( format( 'invalid argument. Must provide an ArrayBuffer. Value: `%s`.', buf ) ); - } - byteOffset = arguments[ 2 ]; - if ( !isNonNegativeInteger( byteOffset ) ) { - throw new TypeError( format( 'invalid argument. Byte offset must be a nonnegative integer. Value: `%s`.', byteOffset ) ); - } - if ( nargs === 2 ) { - buf = new DataView( buf, byteOffset ); - } else { - len = arguments[ 3 ]; - if ( !isNonNegativeInteger( len ) ) { - throw new TypeError( format( 'invalid argument. Length must be a nonnegative integer. Value: `%s`.', len ) ); - } - len *= BYTES_PER_ELEMENT; - if ( len > (buf.byteLength-byteOffset) ) { - throw new RangeError( format( 'invalid arguments. ArrayBuffer has insufficient capacity. Either decrease the array length or provide a bigger buffer. Minimum capacity: `%u`.', len ) ); - } - buf = new DataView( buf, byteOffset, len ); - } - } - setReadOnly( this, '_buffer', buf ); - setReadOnly( this, '_length', buf.byteLength/BYTES_PER_ELEMENT ); - setReadOnly( this, '_isLE', isLE ); - - return this; -} - -/** -* Size (in bytes) of each array element. -* -* @name BYTES_PER_ELEMENT -* @memberof Float64ArrayFE -* @readonly -* @type {PositiveInteger} -* @default 8 -* -* @example -* var nbytes = Float64ArrayFE.BYTES_PER_ELEMENT; -* // returns 8 -*/ -setReadOnly( Float64ArrayFE, 'BYTES_PER_ELEMENT', BYTES_PER_ELEMENT ); - -/** -* Constructor name. -* -* @name name -* @memberof Float64ArrayFE -* @readonly -* @type {string} -* @default 'Float64ArrayFE' -* -* @example -* var str = Float64ArrayFE.name; -* // returns 'Float64ArrayFE' -*/ -setReadOnly( Float64ArrayFE, 'name', 'Float64ArrayFE' ); - -/** -* Creates a new `Float64ArrayFE` from an array-like object or an iterable. -* -* @name from -* @memberof Float64ArrayFE -* @type {Function} -* @param {string} endianness - byte order -* @param {(Collection|Iterable)} src - array-like object or iterable -* @param {Function} [clbk] - callback to invoke for each source element -* @param {*} [thisArg] - context -* @throws {TypeError} `this` context must be a constructor -* @throws {TypeError} `this` must be a Float64ArrayFE -* @throws {TypeError} first argument must be a supported byte order -* @throws {TypeError} second argument must be an array-like object or an iterable -* @throws {TypeError} third argument must be a function -* @returns {Float64ArrayFE} typed array instance -* -* @example -* var arr = Float64ArrayFE.from( 'little-endian', [ 1.0, 2.0 ] ); -* // returns -* -* var len = arr.length; -* // returns 2 -* -* @example -* function clbk( v ) { -* return v * 2.0; -* } -* -* var arr = Float64ArrayFE.from( 'big-endian', [ 1.0, 2.0 ], clbk ); -* // returns -* -* var len = arr.length; -* // returns 2 -*/ -setReadOnly( Float64ArrayFE, 'from', function from( endianness, src ) { - var thisArg; - var order; - var nargs; - var clbk; - var isLE; - var out; - var buf; - var tmp; - var get; - var len; - var i; - if ( !isFunction( this ) ) { - throw new TypeError( 'invalid invocation. `this` context must be a constructor.' ); - } - if ( !isFloat64ArrayFEConstructor( this ) ) { - throw new TypeError( 'invalid invocation. `this` is not a Float64ArrayFE.' ); - } - order = byteOrder( endianness ); - if ( order === null || !isByteOrder( order ) ) { - throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', endianness ) ); - } - isLE = isLittleEndian( order ); - - nargs = arguments.length; - if ( nargs > 2 ) { - clbk = arguments[ 2 ]; - if ( !isFunction( clbk ) ) { - throw new TypeError( format( 'invalid argument. Third argument must be a function. Value: `%s`.', clbk ) ); - } - if ( nargs > 3 ) { - thisArg = arguments[ 3 ]; - } - } - if ( isCollection( src ) ) { - if ( clbk ) { - len = src.length; - if ( src.get && src.set ) { - get = accessorGetter( 'default' ); - } else { - get = getter( 'default' ); - } - out = new this( order, len ); - buf = out._buffer; // eslint-disable-line no-underscore-dangle - for ( i = 0; i < len; i++ ) { - buf.setFloat64( i*BYTES_PER_ELEMENT, clbk.call( thisArg, get( src, i ), i ), isLE ); - } - return out; - } - return new this( order, src ); - } - if ( isObject( src ) && HAS_ITERATOR_SYMBOL && isFunction( src[ ITERATOR_SYMBOL ] ) ) { - buf = src[ ITERATOR_SYMBOL ](); - if ( !isFunction( buf.next ) ) { - throw new TypeError( format( 'invalid argument. Second argument must be an array-like object or an iterable. Value: `%s`.', src ) ); - } - if ( clbk ) { - tmp = fromIteratorMap( buf, clbk, thisArg ); - } else { - tmp = fromIterator( buf ); - } - len = tmp.length; - out = new this( order, len ); - buf = out._buffer; // eslint-disable-line no-underscore-dangle - for ( i = 0; i < len; i++ ) { - buf.setFloat64( i*BYTES_PER_ELEMENT, tmp[ i ], isLE ); - } - return out; - } - throw new TypeError( format( 'invalid argument. Second argument must be an array-like object or an iterable. Value: `%s`.', src ) ); -}); - -/** -* Creates a new `Float64ArrayFE` from a variable number of arguments. -* -* @name of -* @memberof Float64ArrayFE -* @type {Function} -* @param {string} endianness - byte order -* @param {...*} element - array elements -* @throws {TypeError} `this` context must be a constructor -* @throws {TypeError} `this` must be a Float64ArrayFE -* @throws {TypeError} first argument must be a supported byte order -* @returns {Float64ArrayFE} typed array instance -* -* @example -* var arr = Float64ArrayFE.of( 'little-endian', 1.0, 1.0, 1.0, 1.0 ); -* // returns -* -* var len = arr.length; -* // returns 4 -*/ -setReadOnly( Float64ArrayFE, 'of', function of( endianness ) { - var order; - var args; - var i; - if ( !isFunction( this ) ) { - throw new TypeError( 'invalid invocation. `this` context must be a constructor.' ); - } - if ( !isFloat64ArrayFEConstructor( this ) ) { - throw new TypeError( 'invalid invocation. `this` is not a Float64ArrayFE.' ); - } - order = byteOrder( endianness ); - if ( order === null || !isByteOrder( order ) ) { - throw new TypeError( format( 'invalid argument. First argument must be a supported byte order. Value: `%s`.', endianness ) ); - } - args = []; - for ( i = 1; i < arguments.length; i++ ) { - args.push( arguments[ i ] ); - } - return new this( order, args ); -}); - -/** -* Pointer to the underlying data buffer. -* -* @name buffer -* @memberof Float64ArrayFE.prototype -* @readonly -* @type {ArrayBuffer} -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var buf = arr.buffer; -* // returns -*/ -setReadOnlyAccessor( Float64ArrayFE.prototype, 'buffer', function get() { - return this._buffer.buffer; -}); - -/** -* Size (in bytes) of the array. -* -* @name byteLength -* @memberof Float64ArrayFE.prototype -* @readonly -* @type {NonNegativeInteger} -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var byteLength = arr.byteLength; -* // returns 80 -*/ -setReadOnlyAccessor( Float64ArrayFE.prototype, 'byteLength', function get() { - return this._buffer.byteLength; -}); - -/** -* Offset (in bytes) of the array from the start of its underlying `ArrayBuffer`. -* -* @name byteOffset -* @memberof Float64ArrayFE.prototype -* @readonly -* @type {NonNegativeInteger} -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var byteOffset = arr.byteOffset; -* // returns 0 -*/ -setReadOnlyAccessor( Float64ArrayFE.prototype, 'byteOffset', function get() { - return this._buffer.byteOffset; -}); - -/** -* Size (in bytes) of each array element. -* -* @name BYTES_PER_ELEMENT -* @memberof Float64ArrayFE.prototype -* @readonly -* @type {PositiveInteger} -* @default 8 -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var nbytes = arr.BYTES_PER_ELEMENT; -* // returns 8 -*/ -setReadOnly( Float64ArrayFE.prototype, 'BYTES_PER_ELEMENT', Float64ArrayFE.BYTES_PER_ELEMENT ); - -/** -* Returns an array element. -* -* @name get -* @memberof Float64ArrayFE.prototype -* @type {Function} -* @param {NonNegativeInteger} idx - element index -* @throws {TypeError} `this` must be a Float64ArrayFE -* @throws {TypeError} must provide a nonnegative integer -* @returns {(number|void)} array element -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var v = arr.get( 0 ); -* // returns 0.0 -* -* arr.set( [ 1.0, 2.0 ], 0 ); -* -* v = arr.get( 0 ); -* // returns 1.0 -* -* v = arr.get( 100 ); -* // returns undefined -*/ -setReadOnly( Float64ArrayFE.prototype, 'get', function get( idx ) { - if ( !isFloat64ArrayFE( this ) ) { - throw new TypeError( 'invalid invocation. `this` is not a Float64ArrayFE.' ); - } - if ( !isNonNegativeInteger( idx ) ) { - throw new TypeError( format( 'invalid argument. Must provide a nonnegative integer. Value: `%s`.', idx ) ); - } - if ( idx >= this._length ) { - return; - } - return this._buffer.getFloat64( idx*BYTES_PER_ELEMENT, this._isLE ); -}); - -/** -* Number of array elements. -* -* @name length -* @memberof Float64ArrayFE.prototype -* @readonly -* @type {NonNegativeInteger} -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var len = arr.length; -* // returns 10 -*/ -setReadOnlyAccessor( Float64ArrayFE.prototype, 'length', function get() { - return this._length; -}); - -/** -* Sets an array element. -* -* ## Notes -* -* - When provided a typed array, we must check whether the source array shares the same buffer as the target array and whether the underlying memory overlaps. In particular, we are concerned with the following scenario: -* -* ```text -* buf: --------------------- -* src: --------------------- -* ``` -* -* In the above, as we copy values from `src`, we will overwrite values in the `src` view, resulting in duplicated values copied into the end of `buf`, which is not intended. Hence, to avoid overwriting source values, we must **copy** source values to a temporary array. -* -* In the other overlapping scenario, -* -* ```text -* buf: --------------------- -* src: --------------------- -* ``` -* -* by the time we begin copying into the overlapping region, we are copying from the end of `src`, a non-overlapping region, which means we don't run the risk of copying copied values, rather than the original `src` values, as intended. -* -* @name set -* @memberof Float64ArrayFE.prototype -* @type {Function} -* @param {(Collection|Float64ArrayFE|*)} value - value(s) -* @param {NonNegativeInteger} [i=0] - element index at which to start writing values -* @throws {TypeError} `this` must be a Float64ArrayFE -* @throws {TypeError} index argument must be a nonnegative integer -* @throws {RangeError} index argument is out-of-bounds -* @throws {RangeError} target array lacks sufficient storage to accommodate source values -* @returns {void} -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 10 ); -* -* var v = arr.get( 0 ); -* // returns 0.0 -* -* arr.set( [ 1.0, 2.0 ], 0 ); -* -* v = arr.get( 0 ); -* // returns 1.0 -*/ -setReadOnly( Float64ArrayFE.prototype, 'set', function set( value ) { - var sbuf; - var idx; - var buf; - var tmp; - var get; - var N; - var i; - var j; - if ( !isFloat64ArrayFE( this ) ) { - throw new TypeError( 'invalid invocation. `this` is not a Float64ArrayFE.' ); - } - buf = this._buffer; - if ( arguments.length > 1 ) { - idx = arguments[ 1 ]; - if ( !isNonNegativeInteger( idx ) ) { - throw new TypeError( format( 'invalid argument. Index argument must be a nonnegative integer. Value: `%s`.', idx ) ); - } - } else { - idx = 0; - } - if ( isCollection( value ) ) { - N = value.length; - if ( idx+N > this._length ) { - throw new RangeError( 'invalid arguments. Target array lacks sufficient storage to accommodate source values.' ); - } - sbuf = value; - if ( sbuf.get && sbuf.set ) { - get = accessorGetter( 'default' ); - } else { - get = getter( 'default' ); - } - // Check for overlapping memory... - j = buf.byteOffset + (idx*BYTES_PER_ELEMENT); - if ( - sbuf.buffer === buf.buffer && - ( - sbuf.byteOffset < j && - sbuf.byteOffset+sbuf.byteLength > j - ) - ) { - // We need to copy source values... - tmp = []; - for ( i = 0; i < value.length; i++ ) { - tmp.push( get( value, i ) ); - } - sbuf = tmp; - get = getter( 'default' ); - } - for ( i = 0; i < N; idx++, i++ ) { - buf.setFloat64( idx*BYTES_PER_ELEMENT, get( sbuf, i ), this._isLE ); - } - return; - } - if ( idx >= this._length ) { - throw new RangeError( format( 'invalid argument. Index argument is out-of-bounds. Value: `%u`.', idx ) ); - } - buf.setFloat64( idx*BYTES_PER_ELEMENT, value, this._isLE ); -}); - -/** -* Serializes an array as a string. -* -* @name toString -* @memberof Float64ArrayFE.prototype -* @type {Function} -* @throws {TypeError} `this` must be a Float64ArrayFE -* @returns {string} string representation -* -* @example -* var arr = new Float64ArrayFE( 'little-endian', 3 ); -* -* arr.set( 1.0, 0 ); -* arr.set( 2.0, 1 ); -* arr.set( 3.0, 2 ); -* -* var str = arr.toString(); -* // returns '1,2,3' -*/ -setReadOnly( Float64ArrayFE.prototype, 'toString', function toString() { - var out; - var buf; - var i; - if ( !isFloat64ArrayFE( this ) ) { - throw new TypeError( 'invalid invocation. `this` is not a Float64ArrayFE.' ); - } - out = []; - buf = this._buffer; - for ( i = 0; i < this._length; i++ ) { - out.push( buf.getFloat64( i*BYTES_PER_ELEMENT, this._isLE ) ); - } - return out.join( ',' ); -}); +var Float64ArrayFE = factory( 'float64' ); // EXPORTS //