From 1c3faa44fc0dd816f524a181654d4709ed89cc0a Mon Sep 17 00:00:00 2001 From: stdlib-bot Date: Fri, 16 Aug 2024 08:29:48 +0000 Subject: [PATCH] Auto-generated commit --- CHANGELOG.md | 23 + CONTRIBUTORS | 1 + base/map/README.md | 185 ++++++++ .../benchmark.10d_blocked_columnmajor.js | 152 +++++++ .../benchmark.10d_blocked_rowmajor.js | 152 +++++++ .../benchmark/benchmark.10d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.10d_rowmajor.js | 152 +++++++ .../benchmark/benchmark.11d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.11d_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.1d_columnmajor.js | 141 ++++++ base/map/benchmark/benchmark.1d_rowmajor.js | 141 ++++++ .../benchmark.2d_blocked_columnmajor.js | 153 +++++++ .../benchmark.2d_blocked_rowmajor.js | 153 +++++++ .../map/benchmark/benchmark.2d_columnmajor.js | 153 +++++++ base/map/benchmark/benchmark.2d_rowmajor.js | 154 +++++++ .../benchmark.2d_rowmajor_accessors.js | 181 ++++++++ ...benchmark.2d_rowmajor_accessors_complex.js | 188 ++++++++ .../benchmark.3d_blocked_columnmajor.js | 153 +++++++ .../benchmark.3d_blocked_rowmajor.js | 153 +++++++ .../map/benchmark/benchmark.3d_columnmajor.js | 153 +++++++ base/map/benchmark/benchmark.3d_rowmajor.js | 153 +++++++ .../benchmark.4d_blocked_columnmajor.js | 152 +++++++ .../benchmark.4d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.4d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.4d_rowmajor.js | 152 +++++++ .../benchmark.5d_blocked_columnmajor.js | 152 +++++++ .../benchmark.5d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.5d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.5d_rowmajor.js | 152 +++++++ .../benchmark.6d_blocked_columnmajor.js | 152 +++++++ .../benchmark.6d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.6d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.6d_rowmajor.js | 152 +++++++ .../benchmark.7d_blocked_columnmajor.js | 152 +++++++ .../benchmark.7d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.7d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.7d_rowmajor.js | 152 +++++++ .../benchmark.8d_blocked_columnmajor.js | 152 +++++++ .../benchmark.8d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.8d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.8d_rowmajor.js | 152 +++++++ .../benchmark.9d_blocked_columnmajor.js | 152 +++++++ .../benchmark.9d_blocked_rowmajor.js | 152 +++++++ .../map/benchmark/benchmark.9d_columnmajor.js | 152 +++++++ base/map/benchmark/benchmark.9d_rowmajor.js | 152 +++++++ base/map/docs/repl.txt | 78 ++++ base/map/docs/types/index.d.ts | 117 +++++ base/map/docs/types/test.ts | 128 ++++++ base/map/examples/index.js | 50 +++ base/map/lib/0d.js | 100 +++++ base/map/lib/0d_accessors.js | 121 +++++ base/map/lib/10d.js | 280 ++++++++++++ base/map/lib/10d_accessors.js | 305 +++++++++++++ base/map/lib/10d_blocked.js | 389 ++++++++++++++++ base/map/lib/10d_blocked_accessors.js | 414 ++++++++++++++++++ base/map/lib/1d.js | 129 ++++++ base/map/lib/1d_accessors.js | 154 +++++++ base/map/lib/2d.js | 166 +++++++ base/map/lib/2d_accessors.js | 191 ++++++++ base/map/lib/2d_blocked.js | 195 +++++++++ base/map/lib/2d_blocked_accessors.js | 220 ++++++++++ base/map/lib/3d.js | 180 ++++++++ base/map/lib/3d_accessors.js | 205 +++++++++ base/map/lib/3d_blocked.js | 221 ++++++++++ base/map/lib/3d_blocked_accessors.js | 246 +++++++++++ base/map/lib/4d.js | 194 ++++++++ base/map/lib/4d_accessors.js | 219 +++++++++ base/map/lib/4d_blocked.js | 245 +++++++++++ base/map/lib/4d_blocked_accessors.js | 270 ++++++++++++ base/map/lib/5d.js | 208 +++++++++ base/map/lib/5d_accessors.js | 233 ++++++++++ base/map/lib/5d_blocked.js | 269 ++++++++++++ base/map/lib/5d_blocked_accessors.js | 294 +++++++++++++ base/map/lib/6d.js | 224 ++++++++++ base/map/lib/6d_accessors.js | 249 +++++++++++ base/map/lib/6d_blocked.js | 293 +++++++++++++ base/map/lib/6d_blocked_accessors.js | 318 ++++++++++++++ base/map/lib/7d.js | 238 ++++++++++ base/map/lib/7d_accessors.js | 263 +++++++++++ base/map/lib/7d_blocked.js | 317 ++++++++++++++ base/map/lib/7d_blocked_accessors.js | 342 +++++++++++++++ base/map/lib/8d.js | 252 +++++++++++ base/map/lib/8d_accessors.js | 277 ++++++++++++ base/map/lib/8d_blocked.js | 341 +++++++++++++++ base/map/lib/8d_blocked_accessors.js | 366 ++++++++++++++++ base/map/lib/9d.js | 266 +++++++++++ base/map/lib/9d_accessors.js | 291 ++++++++++++ base/map/lib/9d_blocked.js | 365 +++++++++++++++ base/map/lib/9d_blocked_accessors.js | 390 +++++++++++++++++ base/map/lib/index.js | 81 ++++ base/map/lib/main.js | 342 +++++++++++++++ base/map/lib/nd.js | 154 +++++++ base/map/lib/nd_accessors.js | 179 ++++++++ base/map/package.json | 65 +++ base/map/test/test.js | 35 ++ 95 files changed, 18114 insertions(+) create mode 100644 base/map/README.md create mode 100644 base/map/benchmark/benchmark.10d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.10d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.10d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.10d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.11d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.11d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.1d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.1d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.2d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.2d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.2d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.2d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.2d_rowmajor_accessors.js create mode 100644 base/map/benchmark/benchmark.2d_rowmajor_accessors_complex.js create mode 100644 base/map/benchmark/benchmark.3d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.3d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.3d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.3d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.4d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.4d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.4d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.4d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.5d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.5d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.5d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.5d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.6d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.6d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.6d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.6d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.7d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.7d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.7d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.7d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.8d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.8d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.8d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.8d_rowmajor.js create mode 100644 base/map/benchmark/benchmark.9d_blocked_columnmajor.js create mode 100644 base/map/benchmark/benchmark.9d_blocked_rowmajor.js create mode 100644 base/map/benchmark/benchmark.9d_columnmajor.js create mode 100644 base/map/benchmark/benchmark.9d_rowmajor.js create mode 100644 base/map/docs/repl.txt create mode 100644 base/map/docs/types/index.d.ts create mode 100644 base/map/docs/types/test.ts create mode 100644 base/map/examples/index.js create mode 100644 base/map/lib/0d.js create mode 100644 base/map/lib/0d_accessors.js create mode 100644 base/map/lib/10d.js create mode 100644 base/map/lib/10d_accessors.js create mode 100644 base/map/lib/10d_blocked.js create mode 100644 base/map/lib/10d_blocked_accessors.js create mode 100644 base/map/lib/1d.js create mode 100644 base/map/lib/1d_accessors.js create mode 100644 base/map/lib/2d.js create mode 100644 base/map/lib/2d_accessors.js create mode 100644 base/map/lib/2d_blocked.js create mode 100644 base/map/lib/2d_blocked_accessors.js create mode 100644 base/map/lib/3d.js create mode 100644 base/map/lib/3d_accessors.js create mode 100644 base/map/lib/3d_blocked.js create mode 100644 base/map/lib/3d_blocked_accessors.js create mode 100644 base/map/lib/4d.js create mode 100644 base/map/lib/4d_accessors.js create mode 100644 base/map/lib/4d_blocked.js create mode 100644 base/map/lib/4d_blocked_accessors.js create mode 100644 base/map/lib/5d.js create mode 100644 base/map/lib/5d_accessors.js create mode 100644 base/map/lib/5d_blocked.js create mode 100644 base/map/lib/5d_blocked_accessors.js create mode 100644 base/map/lib/6d.js create mode 100644 base/map/lib/6d_accessors.js create mode 100644 base/map/lib/6d_blocked.js create mode 100644 base/map/lib/6d_blocked_accessors.js create mode 100644 base/map/lib/7d.js create mode 100644 base/map/lib/7d_accessors.js create mode 100644 base/map/lib/7d_blocked.js create mode 100644 base/map/lib/7d_blocked_accessors.js create mode 100644 base/map/lib/8d.js create mode 100644 base/map/lib/8d_accessors.js create mode 100644 base/map/lib/8d_blocked.js create mode 100644 base/map/lib/8d_blocked_accessors.js create mode 100644 base/map/lib/9d.js create mode 100644 base/map/lib/9d_accessors.js create mode 100644 base/map/lib/9d_blocked.js create mode 100644 base/map/lib/9d_blocked_accessors.js create mode 100644 base/map/lib/index.js create mode 100644 base/map/lib/main.js create mode 100644 base/map/lib/nd.js create mode 100644 base/map/lib/nd_accessors.js create mode 100644 base/map/package.json create mode 100644 base/map/test/test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 495ecc0f..bea80fc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -276,6 +276,28 @@ +
+ +#### [@stdlib/ndarray/base/map](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/map) + +
+ +
+ +##### Features + +- [`72ed2e1`](https://github.com/stdlib-js/stdlib/commit/72ed2e1e6331858c078564e22b6dca041f5daaca) - add `ndarray/base/map` [(#2715)](https://github.com/stdlib-js/stdlib/pull/2715) + +
+ + + +
+ +
+ + +
#### [@stdlib/ndarray/base/nullary](https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/nullary) @@ -967,6 +989,7 @@ A total of 4 people contributed to this release. Thank you to the following cont
+- [`72ed2e1`](https://github.com/stdlib-js/stdlib/commit/72ed2e1e6331858c078564e22b6dca041f5daaca) - **feat:** add `ndarray/base/map` [(#2715)](https://github.com/stdlib-js/stdlib/pull/2715) _(by Muhammad Haris, Athan Reines)_ - [`96c7ddf`](https://github.com/stdlib-js/stdlib/commit/96c7ddfdbcecc6ff60fcb56681db16463d19020e) - **fix:** use computed order and fix strides in examples _(by Athan Reines)_ - [`e2b7fb5`](https://github.com/stdlib-js/stdlib/commit/e2b7fb5df61f15ae7dbf148ec0c0412ff434b123) - **fix:** use computed order and fix strides in examples _(by Athan Reines)_ - [`1375823`](https://github.com/stdlib-js/stdlib/commit/1375823f58c93aeac8c687147f40e78d52adec04) - **fix:** use computed order and fix strides in examples _(by Athan Reines)_ diff --git a/CONTRIBUTORS b/CONTRIBUTORS index f05b39ca..57d1184a 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -46,6 +46,7 @@ Marcus Fantham Matt Cochrane Mihir Pandit <129577900+MSP20086@users.noreply.github.com> Milan Raj +Mohammad Kaif <98884589+Kaif987@users.noreply.github.com> Momtchil Momtchev Muhammad Haris Naresh Jagadeesan diff --git a/base/map/README.md b/base/map/README.md new file mode 100644 index 00000000..6e7b4756 --- /dev/null +++ b/base/map/README.md @@ -0,0 +1,185 @@ + + +# map + +> Apply a callback function to elements in an input ndarray and assign results to elements in an output ndarray. + +
+ +
+ + + +
+ +## Usage + +```javascript +var map = require( '@stdlib/ndarray/base/map' ); +``` + +#### map( arrays, fcn\[, thisArg] ) + +Applies a callback function to elements in an input ndarray and assigns results to elements in an output ndarray. + +```javascript +var Float64Array = require( '@stdlib/array/float64' ); + +function scale( x ) { + return x * 10.0; +} + +// Create data buffers: +var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] ); +var ybuf = new Float64Array( 6 ); + +// Define the shape of the input and output arrays: +var shape = [ 3, 2 ]; + +// Define the array strides: +var sx = [ 2, 1 ]; +var sy = [ 2, 1 ]; + +// Define the index offsets: +var ox = 0; +var oy = 0; + +// Create the input and output ndarray-like objects: +var x = { + 'ref': null, + 'dtype': 'float64', + 'data': xbuf, + 'shape': shape, + 'strides': sx, + 'offset': ox, + 'order': 'row-major' +}; +var y = { + 'dtype': 'float64', + 'data': ybuf, + 'shape': shape, + 'strides': sy, + 'offset': oy, + 'order': 'row-major' +}; + +// Apply the map function: +map( [ x, y ], scale ); + +console.log( y.data ); +// => [ 10.0, 20.0, 30.0, 40.0, 50.0, 60.0 ] +``` + +The function accepts the following arguments: + +- **arrays**: array-like object containing one input ndarray and one output ndarray. +- **fcn**: callback to apply. +- **thisArg**: callback execution context. + +The callback function is provided the following arguments: + +- **values**: current array element. +- **indices**: current array element indices. +- **arr**: the input ndarray. + +
+ + + +
+ +## Notes + +- Each provided ndarray should be an object with the following properties: + + - **dtype**: data type. + - **data**: data buffer. + - **shape**: dimensions. + - **strides**: stride lengths. + - **offset**: index offset. + - **order**: specifies whether an ndarray is row-major (C-style) or column major (Fortran-style). + +- For very high-dimensional ndarrays which are non-contiguous, one should consider copying the underlying data to contiguous memory before applying a callback function in order to achieve better performance. + +
+ + + +
+ +## Examples + + + +```javascript +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ).factory; +var filledarray = require( '@stdlib/array/filled' ); +var filledarrayBy = require( '@stdlib/array/filled-by' ); +var abs = require( '@stdlib/math/base/special/abs' ); +var shape2strides = require( '@stdlib/ndarray/base/shape2strides' ); +var ndarray2array = require( '@stdlib/ndarray/base/to-array' ); +var naryFunction = require( '@stdlib/utils/nary-function' ); +var map = require( '@stdlib/ndarray/base/map' ); + +var N = 10; +var x = { + 'dtype': 'generic', + 'data': filledarrayBy( N, 'generic', discreteUniform( -100, 100 ) ), + 'shape': [ 5, 2 ], + 'strides': [ 2, 1 ], + 'offset': 0, + 'order': 'row-major' +}; +var y = { + 'dtype': 'generic', + 'data': filledarray( 0, N, 'generic' ), + 'shape': x.shape.slice(), + 'strides': shape2strides( x.shape, 'column-major' ), + 'offset': 0, + 'order': 'column-major' +}; + +map( [ x, y ], naryFunction( abs, 1 ) ); +console.log( ndarray2array( x.data, x.shape, x.strides, x.offset, x.order ) ); +console.log( ndarray2array( y.data, y.shape, y.strides, y.offset, y.order ) ); +``` + +
+ + + + + + + + + + + + diff --git a/base/map/benchmark/benchmark.10d_blocked_columnmajor.js b/base/map/benchmark/benchmark.10d_blocked_columnmajor.js new file mode 100644 index 00000000..35ff7e40 --- /dev/null +++ b/base/map/benchmark/benchmark.10d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/10d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/10.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 9 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.10d_blocked_rowmajor.js b/base/map/benchmark/benchmark.10d_blocked_rowmajor.js new file mode 100644 index 00000000..5140a500 --- /dev/null +++ b/base/map/benchmark/benchmark.10d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/10d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/10.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 9 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.10d_columnmajor.js b/base/map/benchmark/benchmark.10d_columnmajor.js new file mode 100644 index 00000000..e5f277d9 --- /dev/null +++ b/base/map/benchmark/benchmark.10d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/10d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/10.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 9 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.10d_rowmajor.js b/base/map/benchmark/benchmark.10d_rowmajor.js new file mode 100644 index 00000000..4f92a66d --- /dev/null +++ b/base/map/benchmark/benchmark.10d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/10d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/10.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 9 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.11d_columnmajor.js b/base/map/benchmark/benchmark.11d_columnmajor.js new file mode 100644 index 00000000..806d4511 --- /dev/null +++ b/base/map/benchmark/benchmark.11d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/nd.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/11.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 10 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.11d_rowmajor.js b/base/map/benchmark/benchmark.11d_rowmajor.js new file mode 100644 index 00000000..91cb4acd --- /dev/null +++ b/base/map/benchmark/benchmark.11d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/nd.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/11.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 10 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.1d_columnmajor.js b/base/map/benchmark/benchmark.1d_columnmajor.js new file mode 100644 index 00000000..9827a0c8 --- /dev/null +++ b/base/map/benchmark/benchmark.1d_columnmajor.js @@ -0,0 +1,141 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( [ x, y ], identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.1d_rowmajor.js b/base/map/benchmark/benchmark.1d_rowmajor.js new file mode 100644 index 00000000..c52e8888 --- /dev/null +++ b/base/map/benchmark/benchmark.1d_rowmajor.js @@ -0,0 +1,141 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( [ x, y ], identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_blocked_columnmajor.js b/base/map/benchmark/benchmark.2d_blocked_columnmajor.js new file mode 100644 index 00000000..eff28d2a --- /dev/null +++ b/base/map/benchmark/benchmark.2d_blocked_columnmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_blocked_rowmajor.js b/base/map/benchmark/benchmark.2d_blocked_rowmajor.js new file mode 100644 index 00000000..c44eaf70 --- /dev/null +++ b/base/map/benchmark/benchmark.2d_blocked_rowmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_columnmajor.js b/base/map/benchmark/benchmark.2d_columnmajor.js new file mode 100644 index 00000000..38daaf88 --- /dev/null +++ b/base/map/benchmark/benchmark.2d_columnmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_rowmajor.js b/base/map/benchmark/benchmark.2d_rowmajor.js new file mode 100644 index 00000000..c218f31b --- /dev/null +++ b/base/map/benchmark/benchmark.2d_rowmajor.js @@ -0,0 +1,154 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_rowmajor_accessors.js b/base/map/benchmark/benchmark.2d_rowmajor_accessors.js new file mode 100644 index 00000000..71b7ae33 --- /dev/null +++ b/base/map/benchmark/benchmark.2d_rowmajor_accessors.js @@ -0,0 +1,181 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d_accessors.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Returns an array data buffer element. +* +* @private +* @param {Collection} buf - data buffer +* @param {NonNegativeInteger} idx - element index +* @returns {*} element +*/ +function get( buf, idx ) { + return buf[ idx ]; +} + +/** +* Sets an array data buffer element. +* +* @private +* @param {Collection} buf - data buffer +* @param {NonNegativeInteger} idx - element index +* @param {*} value - value to set +*/ +function set( buf, idx, value ) { + buf[ idx ] = value; +} + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order, + 'accessorProtocol': true, + 'accessors': [ get, set ] + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order, + 'accessorProtocol': true, + 'accessors': [ get, set ] + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.2d_rowmajor_accessors_complex.js b/base/map/benchmark/benchmark.2d_rowmajor_accessors_complex.js new file mode 100644 index 00000000..29b58f37 --- /dev/null +++ b/base/map/benchmark/benchmark.2d_rowmajor_accessors_complex.js @@ -0,0 +1,188 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var ctors = require( '@stdlib/array/typed-complex-ctors' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/2d_accessors.js' ); + + +// VARIABLES // + +var types = [ 'complex64' ]; +var order = 'row-major'; +var abtype = { + 'complex64': 'float32', + 'complex128': 'float64' +}; + + +// FUNCTIONS // + +/** +* Returns an array data buffer element. +* +* @private +* @param {Collection} buf - data buffer +* @param {NonNegativeInteger} idx - element index +* @returns {*} element +*/ +function get( buf, idx ) { + return buf.get( idx ); +} + +/** +* Sets an array data buffer element. +* +* @private +* @param {Collection} buf - data buffer +* @param {NonNegativeInteger} idx - element index +* @param {*} value - value to set +*/ +function set( buf, idx, value ) { + buf.set( value, idx ); +} + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var xbuf; + var ybuf; + var x; + var y; + var i; + + xbuf = filledarray( 0.0, len*2, abtype[ xtype ] ); + ybuf = filledarray( 0.0, len*2, abtype[ ytype ] ); + for ( i = 0; i < len*2; i++ ) { + xbuf[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': new ( ctors( xtype ) )( xbuf.buffer ), + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order, + 'accessorProtocol': true, + 'accessors': [ get, set ] + }; + y = { + 'dtype': ytype, + 'data': new ( ctors( ytype ) )( ybuf.buffer ), + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order, + 'accessorProtocol': true, + 'accessors': [ get, set ] + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( ybuf[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( ybuf[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 5; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( sqrt( len ) ); + sh = [ len, len ]; + len *= len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::accessors:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.3d_blocked_columnmajor.js b/base/map/benchmark/benchmark.3d_blocked_columnmajor.js new file mode 100644 index 00000000..1df66e7e --- /dev/null +++ b/base/map/benchmark/benchmark.3d_blocked_columnmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var cbrt = require( '@stdlib/math/base/special/cbrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/3d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( cbrt( len ) ); + sh = [ len, len, len ]; + len *= len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.3d_blocked_rowmajor.js b/base/map/benchmark/benchmark.3d_blocked_rowmajor.js new file mode 100644 index 00000000..9e48737d --- /dev/null +++ b/base/map/benchmark/benchmark.3d_blocked_rowmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var cbrt = require( '@stdlib/math/base/special/cbrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/3d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( cbrt( len ) ); + sh = [ len, len, len ]; + len *= len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.3d_columnmajor.js b/base/map/benchmark/benchmark.3d_columnmajor.js new file mode 100644 index 00000000..2ef91e2e --- /dev/null +++ b/base/map/benchmark/benchmark.3d_columnmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var cbrt = require( '@stdlib/math/base/special/cbrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/3d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( cbrt( len ) ); + sh = [ len, len, len ]; + len *= len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.3d_rowmajor.js b/base/map/benchmark/benchmark.3d_rowmajor.js new file mode 100644 index 00000000..c6a7e051 --- /dev/null +++ b/base/map/benchmark/benchmark.3d_rowmajor.js @@ -0,0 +1,153 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var cbrt = require( '@stdlib/math/base/special/cbrt' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/3d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( cbrt( len ) ); + sh = [ len, len, len ]; + len *= len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.4d_blocked_columnmajor.js b/base/map/benchmark/benchmark.4d_blocked_columnmajor.js new file mode 100644 index 00000000..24d13ea1 --- /dev/null +++ b/base/map/benchmark/benchmark.4d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/4d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/4.0 ) ); + sh = [ len, len, len, len ]; + len *= len * len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.4d_blocked_rowmajor.js b/base/map/benchmark/benchmark.4d_blocked_rowmajor.js new file mode 100644 index 00000000..75036b82 --- /dev/null +++ b/base/map/benchmark/benchmark.4d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/4d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/4.0 ) ); + sh = [ len, len, len, len ]; + len *= len * len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.4d_columnmajor.js b/base/map/benchmark/benchmark.4d_columnmajor.js new file mode 100644 index 00000000..a7f9a40d --- /dev/null +++ b/base/map/benchmark/benchmark.4d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/4d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/4.0 ) ); + sh = [ len, len, len, len ]; + len *= len * len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.4d_rowmajor.js b/base/map/benchmark/benchmark.4d_rowmajor.js new file mode 100644 index 00000000..551ac0ad --- /dev/null +++ b/base/map/benchmark/benchmark.4d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/4d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/4.0 ) ); + sh = [ len, len, len, len ]; + len *= len * len * len; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.5d_blocked_columnmajor.js b/base/map/benchmark/benchmark.5d_blocked_columnmajor.js new file mode 100644 index 00000000..87699496 --- /dev/null +++ b/base/map/benchmark/benchmark.5d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/5d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/5.0 ) ); + sh = [ len, len, len, len, len ]; + len *= pow( len, 4 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.5d_blocked_rowmajor.js b/base/map/benchmark/benchmark.5d_blocked_rowmajor.js new file mode 100644 index 00000000..5e605c97 --- /dev/null +++ b/base/map/benchmark/benchmark.5d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/5d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/5.0 ) ); + sh = [ len, len, len, len, len ]; + len *= pow( len, 4 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.5d_columnmajor.js b/base/map/benchmark/benchmark.5d_columnmajor.js new file mode 100644 index 00000000..4b7a01f1 --- /dev/null +++ b/base/map/benchmark/benchmark.5d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/5d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/5.0 ) ); + sh = [ len, len, len, len, len ]; + len *= pow( len, 4 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.5d_rowmajor.js b/base/map/benchmark/benchmark.5d_rowmajor.js new file mode 100644 index 00000000..42360350 --- /dev/null +++ b/base/map/benchmark/benchmark.5d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/5d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/5.0 ) ); + sh = [ len, len, len, len, len ]; + len *= pow( len, 4 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.6d_blocked_columnmajor.js b/base/map/benchmark/benchmark.6d_blocked_columnmajor.js new file mode 100644 index 00000000..51528b7d --- /dev/null +++ b/base/map/benchmark/benchmark.6d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/6d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/6.0 ) ); + sh = [ len, len, len, len, len, len ]; + len *= pow( len, 5 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.6d_blocked_rowmajor.js b/base/map/benchmark/benchmark.6d_blocked_rowmajor.js new file mode 100644 index 00000000..baa2cf4e --- /dev/null +++ b/base/map/benchmark/benchmark.6d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/6d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/6.0 ) ); + sh = [ len, len, len, len, len, len ]; + len *= pow( len, 5 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.6d_columnmajor.js b/base/map/benchmark/benchmark.6d_columnmajor.js new file mode 100644 index 00000000..9cd50fbf --- /dev/null +++ b/base/map/benchmark/benchmark.6d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/6d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/6.0 ) ); + sh = [ len, len, len, len, len, len ]; + len *= pow( len, 5 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.6d_rowmajor.js b/base/map/benchmark/benchmark.6d_rowmajor.js new file mode 100644 index 00000000..587ab0fc --- /dev/null +++ b/base/map/benchmark/benchmark.6d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/6d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/6.0 ) ); + sh = [ len, len, len, len, len, len ]; + len *= pow( len, 5 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.7d_blocked_columnmajor.js b/base/map/benchmark/benchmark.7d_blocked_columnmajor.js new file mode 100644 index 00000000..b7fcfbac --- /dev/null +++ b/base/map/benchmark/benchmark.7d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/7d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/7.0 ) ); + sh = [ len, len, len, len, len, len, len ]; + len *= pow( len, 6 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.7d_blocked_rowmajor.js b/base/map/benchmark/benchmark.7d_blocked_rowmajor.js new file mode 100644 index 00000000..5ed2941d --- /dev/null +++ b/base/map/benchmark/benchmark.7d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/7d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/7.0 ) ); + sh = [ len, len, len, len, len, len, len ]; + len *= pow( len, 6 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.7d_columnmajor.js b/base/map/benchmark/benchmark.7d_columnmajor.js new file mode 100644 index 00000000..8fab7425 --- /dev/null +++ b/base/map/benchmark/benchmark.7d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/7d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/7.0 ) ); + sh = [ len, len, len, len, len, len, len ]; + len *= pow( len, 6 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.7d_rowmajor.js b/base/map/benchmark/benchmark.7d_rowmajor.js new file mode 100644 index 00000000..0093f8dc --- /dev/null +++ b/base/map/benchmark/benchmark.7d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/7d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/7.0 ) ); + sh = [ len, len, len, len, len, len, len ]; + len *= pow( len, 6 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.8d_blocked_columnmajor.js b/base/map/benchmark/benchmark.8d_blocked_columnmajor.js new file mode 100644 index 00000000..efeb08f5 --- /dev/null +++ b/base/map/benchmark/benchmark.8d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/8d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/8.0 ) ); + sh = [ len, len, len, len, len, len, len, len ]; + len *= pow( len, 7 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.8d_blocked_rowmajor.js b/base/map/benchmark/benchmark.8d_blocked_rowmajor.js new file mode 100644 index 00000000..637d20de --- /dev/null +++ b/base/map/benchmark/benchmark.8d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/8d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/8.0 ) ); + sh = [ len, len, len, len, len, len, len, len ]; + len *= pow( len, 7 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.8d_columnmajor.js b/base/map/benchmark/benchmark.8d_columnmajor.js new file mode 100644 index 00000000..59a59825 --- /dev/null +++ b/base/map/benchmark/benchmark.8d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/8d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/8.0 ) ); + sh = [ len, len, len, len, len, len, len, len ]; + len *= pow( len, 7 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.8d_rowmajor.js b/base/map/benchmark/benchmark.8d_rowmajor.js new file mode 100644 index 00000000..e576fe2d --- /dev/null +++ b/base/map/benchmark/benchmark.8d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/8d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/8.0 ) ); + sh = [ len, len, len, len, len, len, len, len ]; + len *= pow( len, 7 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.9d_blocked_columnmajor.js b/base/map/benchmark/benchmark.9d_blocked_columnmajor.js new file mode 100644 index 00000000..e199fcc5 --- /dev/null +++ b/base/map/benchmark/benchmark.9d_blocked_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/9d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/9.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 8 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.9d_blocked_rowmajor.js b/base/map/benchmark/benchmark.9d_blocked_rowmajor.js new file mode 100644 index 00000000..2650b0a9 --- /dev/null +++ b/base/map/benchmark/benchmark.9d_blocked_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/9d_blocked.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/9.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 8 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+'::blocked:ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.9d_columnmajor.js b/base/map/benchmark/benchmark.9d_columnmajor.js new file mode 100644 index 00000000..3160dcdb --- /dev/null +++ b/base/map/benchmark/benchmark.9d_columnmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/9d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'column-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/9.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 8 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/benchmark/benchmark.9d_rowmajor.js b/base/map/benchmark/benchmark.9d_rowmajor.js new file mode 100644 index 00000000..07cf6182 --- /dev/null +++ b/base/map/benchmark/benchmark.9d_rowmajor.js @@ -0,0 +1,152 @@ +/** +* @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 randu = require( '@stdlib/random/base/randu' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pow = require( '@stdlib/math/base/special/pow' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var round = require( '@stdlib/math/base/special/round' ); +var identity = require( '@stdlib/math/base/special/identity' ); +var filledarray = require( '@stdlib/array/filled' ); +var shape2strides = require( './../../../base/shape2strides' ); +var pkg = require( './../package.json' ).name; +var map = require( './../lib/9d.js' ); + + +// VARIABLES // + +var types = [ 'float64' ]; +var order = 'row-major'; + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} len - ndarray length +* @param {NonNegativeIntegerArray} shape - ndarray shape +* @param {string} xtype - input ndarray data type +* @param {string} ytype - output ndarray data type +* @returns {Function} benchmark function +*/ +function createBenchmark( len, shape, xtype, ytype ) { + var x; + var y; + var i; + + x = filledarray( 0.0, len, xtype ); + y = filledarray( 0.0, len, ytype ); + for ( i = 0; i < len; i++ ) { + x[ i ] = round( ( randu()*200.0 ) - 100.0 ); + } + x = { + 'dtype': xtype, + 'data': x, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + y = { + 'dtype': ytype, + 'data': y, + 'shape': shape, + 'strides': shape2strides( shape, order ), + 'offset': 0, + 'order': order + }; + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + map( x, y, identity ); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( y.data[ i%len ] ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var len; + var min; + var max; + var sh; + var t1; + var t2; + var f; + var i; + var j; + + min = 1; // 10^min + max = 6; // 10^max + + for ( j = 0; j < types.length; j++ ) { + t1 = types[ j ]; + t2 = types[ j ]; + for ( i = min; i <= max; i++ ) { + len = pow( 10, i ); + + sh = [ len/2, 2, 1, 1, 1, 1, 1, 1, 1 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + sh = [ 1, 1, 1, 1, 1, 1, 1, 2, len/2 ]; + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + + len = floor( pow( len, 1.0/9.0 ) ); + sh = [ len, len, len, len, len, len, len, len, len ]; + len *= pow( len, 8 ); + f = createBenchmark( len, sh, t1, t2 ); + bench( pkg+':ndims='+sh.length+',len='+len+',shape=['+sh.join(',')+'],xorder='+order+',yorder='+order+',xtype='+t1+',ytype='+t2, f ); + } + } +} + +main(); diff --git a/base/map/docs/repl.txt b/base/map/docs/repl.txt new file mode 100644 index 00000000..be30da17 --- /dev/null +++ b/base/map/docs/repl.txt @@ -0,0 +1,78 @@ + +{{alias}}( arrays, fcn[, thisArg] ) + Applies a callback function to elements in an input ndarray and assigns + results to elements in an output ndarray. + + Each provided "ndarray" should be an object with following properties: + + - dtype: data type. + - data: data buffer. + - shape: dimensions. + - strides: stride lengths. + - offset: index offset. + - order: specifies whether an ndarray is row-major (C-style) or column-major + (Fortran-style). + + The callback function is provided the following arguments: + + - value: current array element. + - indices: current array element indices. + - arr: the input ndarray. + + Parameters + ---------- + arrays: ArrayLikeObject + Array-like object containing one input ndarray and one output ndarray. + + fcn: Function + Callback function. + + thisArg: any (optional) + Callback function execution context. + + Examples + -------- + // Define ndarray data and meta data... + > var xbuf = new {{alias:@stdlib/array/float64}}( [ 1.0, 2.0, 3.0, 4.0 ] ); + > var ybuf = new {{alias:@stdlib/array/float64}}( [ 0.0, 0.0, 0.0, 0.0 ] ); + > var dtype = 'float64'; + > var shape = [ 2, 2 ]; + > var sx = [ 2, 1 ]; + > var sy = [ 2, 1 ]; + > var ox = 0; + > var oy = 0; + > var order = 'row-major'; + + // Define a callback function: + > function f( v ) { return v*10.0; }; + + // Using ndarrays... + > var x = {{alias:@stdlib/ndarray/ctor}}( dtype, xbuf, shape, sx, ox, order ); + > var y = {{alias:@stdlib/ndarray/ctor}}( dtype, ybuf, shape, sy, oy, order ); + > {{alias}}( [ x, y ], f ); + > y.data + [ 10.0, 20.0, 30.0, 40.0 ] + + // Using minimal ndarray-like objects... + > x = { + ... 'dtype': dtype, + ... 'data': xbuf, + ... 'shape': shape, + ... 'strides': sx, + ... 'offset': ox, + ... 'order': order + ... }; + > y = { + ... 'dtype': dtype, + ... 'data': ybuf, + ... 'shape': shape, + ... 'strides': sy, + ... 'offset': oy, + ... 'order': order + ... }; + > {{alias}}( [ x, y ], f ); + > y.data + [ 10.0, 20.0, 30.0, 40.0 ] + + See Also + -------- diff --git a/base/map/docs/types/index.d.ts b/base/map/docs/types/index.d.ts new file mode 100644 index 00000000..61ce2f33 --- /dev/null +++ b/base/map/docs/types/index.d.ts @@ -0,0 +1,117 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +import { ArrayLike } from '@stdlib/types/array'; +import { typedndarray } from '@stdlib/types/ndarray'; + +/** +* Callback invoked for each ndarray element. +* +* @returns output value +*/ +type Nullary = ( this: V ) => U; + +/** +* Callback invoked for each ndarray element. +* +* @param value - current array element +* @returns output value +*/ +type Unary = ( this: V, value: T ) => U; + +/** +* Callback invoked for each ndarray element. +* +* @param value - current array element +* @param indices - current array element indices +* @returns output value +*/ +type Binary = ( this: V, value: T, indices: Array ) => U; + +/** +* Callback invoked for each ndarray element. +* +* @param value - current array element +* @param indices - current array element indices +* @param arr - input array +* @returns output value +*/ +type Ternary = ( this: V, value: T, indices: Array, arr: typedndarray ) => U; + +/** +* Callback invoked for each ndarray element. +* +* @param value - current array element +* @param indices - current array element indices +* @param arr - input array +* @returns output value +*/ +type Callback = Nullary | Unary | Binary | Ternary; + +/** +* Applies a callback function to the elements in an input ndarray and assigns results to the elements in an output ndarray. +* +* @param arrays - array-like object containing one input ndarray and one output ndarray +* @param fcn - callback function +* @param thisArg - callback function execution context +* @throws arrays must have the same number of dimensions +* @throws arrays must have the same shape +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* var ndarray = require( '@stdlib/ndarray/ctor' ); +* +* function scale( x ) { +* return x * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarrays: +* var x = ndarray( 'float64', xbuf, shape, sx, ox, 'row-major' ); +* var y = ndarray( 'float64', ybuf, shape, sy, oy, 'row-major' ); +* +* // Apply the map function: +* map( [ x, y ], scale ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +declare function map( arrays: ArrayLike>, fcn: Callback, thisArg?: ThisParameterType> ): void; + + +// EXPORTS // + +export = map; diff --git a/base/map/docs/types/test.ts b/base/map/docs/types/test.ts new file mode 100644 index 00000000..7bc28dd4 --- /dev/null +++ b/base/map/docs/types/test.ts @@ -0,0 +1,128 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/// + +import { ndarray } from '@stdlib/types/ndarray'; +import map = require( './index' ); + +/** +* Mock function to create an ndarray-like object. +* +* @return ndarray-like object +*/ +function array(): ndarray { + const obj: ndarray = { + 'byteLength': 80, + 'BYTES_PER_ELEMENT': 8, + 'data': new Float64Array( 10 ), + 'dtype': 'float64', + 'flags': { + 'ROW_MAJOR_CONTIGUOUS': true, + 'COLUMN_MAJOR_CONTIGUOUS': false + }, + 'length': 10, + 'ndims': 1, + 'offset': 0, + 'order': 'row-major', + 'shape': [ 10 ], + 'strides': [ 1 ], + 'get': (): number => 0, + 'set': (): ndarray => obj + }; + return obj; +} + +/** +* Evaluates the identity function. +* +* @param x - input value +* @returns input value +*/ +function identity( x: number ): number { + return x; +} + +// TESTS // + +// The function returns `undefined`... +{ + const x = array(); + const y = array(); + const arrays = [ x, y ]; + + map( arrays, identity ); // $ExpectType void + map( arrays, identity, {} ); // $ExpectType void +} + +// The compiler throws an error if the function is provided a first argument which is not an array-like object containing ndarray-like objects... +{ + map( 5, identity ); // $ExpectError + map( true, identity ); // $ExpectError + map( false, identity ); // $ExpectError + map( null, identity ); // $ExpectError + map( undefined, identity ); // $ExpectError + map( {}, identity ); // $ExpectError + map( [ 1 ], identity ); // $ExpectError + map( ( x: number ): number => x, identity ); // $ExpectError + + map( 5, identity, {} ); // $ExpectError + map( true, identity, {} ); // $ExpectError + map( false, identity, {} ); // $ExpectError + map( null, identity, {} ); // $ExpectError + map( undefined, identity, {} ); // $ExpectError + map( {}, identity, {} ); // $ExpectError + map( [ 1 ], identity, {} ); // $ExpectError + map( ( x: number ): number => x, identity, {} ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a callback function... +{ + const x = array(); + const y = array(); + const arrays = [ x, y ]; + + map( arrays, '10' ); // $ExpectError + map( arrays, 5 ); // $ExpectError + map( arrays, true ); // $ExpectError + map( arrays, false ); // $ExpectError + map( arrays, null ); // $ExpectError + map( arrays, undefined ); // $ExpectError + map( arrays, [] ); // $ExpectError + map( arrays, {} ); // $ExpectError + + map( arrays, '10', {} ); // $ExpectError + map( arrays, 5, {} ); // $ExpectError + map( arrays, true, {} ); // $ExpectError + map( arrays, false, {} ); // $ExpectError + map( arrays, null, {} ); // $ExpectError + map( arrays, undefined, {} ); // $ExpectError + map( arrays, [], {} ); // $ExpectError + map( arrays, {}, {} ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + const x = array(); + const y = array(); + const arrays = [ x, y ]; + + map(); // $ExpectError + map( arrays ); // $ExpectError{ + map( arrays, identity, {}, {} ); // $ExpectError +} diff --git a/base/map/examples/index.js b/base/map/examples/index.js new file mode 100644 index 00000000..00b16029 --- /dev/null +++ b/base/map/examples/index.js @@ -0,0 +1,50 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ).factory; +var filledarray = require( '@stdlib/array/filled' ); +var filledarrayBy = require( '@stdlib/array/filled-by' ); +var abs = require( '@stdlib/math/base/special/abs' ); +var shape2strides = require( './../../../base/shape2strides' ); +var ndarray2array = require( './../../../base/to-array' ); +var naryFunction = require( '@stdlib/utils/nary-function' ); +var map = require( './../lib' ); + +var N = 10; +var x = { + 'dtype': 'generic', + 'data': filledarrayBy( N, 'generic', discreteUniform( -100, 100 ) ), + 'shape': [ 5, 2 ], + 'strides': [ 2, 1 ], + 'offset': 0, + 'order': 'row-major' +}; +var y = { + 'dtype': 'generic', + 'data': filledarray( 0, N, 'generic' ), + 'shape': x.shape.slice(), + 'strides': shape2strides( x.shape, 'column-major' ), + 'offset': 0, + 'order': 'column-major' +}; + +map( [ x, y ], naryFunction( abs, 1 ) ); +console.log( ndarray2array( x.data, x.shape, x.strides, x.offset, x.order ) ); +console.log( ndarray2array( y.data, y.shape, y.strides, y.offset, y.order ) ); diff --git a/base/map/lib/0d.js b/base/map/lib/0d.js new file mode 100644 index 00000000..ed427bbc --- /dev/null +++ b/base/map/lib/0d.js @@ -0,0 +1,100 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Applies a callback function to elements in a zero-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ){ +* return z * 10.0; +* } +* +* // Create a data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0 ] ); +* var ybuf = new Float64Array( 1 ); +* +* // Define the shape of the input and output arrays: +* var shape = []; +* +* // Define the array strides: +* var sx = [ 0 ]; +* var sy = [ 0 ]; +* +* // Define the index offset: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like object: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* } +* +* // Apply the map function: +* map0d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0 ] +*/ +function map0d( x, y, fcn, thisArg ) { + y.data[ y.offset ] = fcn.call( thisArg, x.data[ x.offset ], [], x.ref ); +} + + +// EXPORTS // + +module.exports = map0d; diff --git a/base/map/lib/0d_accessors.js b/base/map/lib/0d_accessors.js new file mode 100644 index 00000000..46c039e1 --- /dev/null +++ b/base/map/lib/0d_accessors.js @@ -0,0 +1,121 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Applies a callback function to elements in a zero-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Array} x.accessors - data buffer accessors +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Array} y.accessors - data buffer accessors +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0 ] ); +* var ybuf = new Complex64Array( 2 ); +* +* // Define the shape of the input and output arrays: +* var shape = []; +* +* // Define the array strides: +* var sx = [ 0 ]; +* var sy = [ 0 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map0d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 30.0 +* +* var im = imagf( v ); +* // returns 40.0 +*/ +function map0d( x, y, fcn, thisArg ) { + y.accessors[ 1 ]( y.data, y.offset, fcn.call( thisArg, x.accessors[ 0 ]( x.data, x.offset ), [], x.ref ) ); // eslint-disable-line max-len +} + + +// EXPORTS // + +module.exports = map0d; diff --git a/base/map/lib/10d.js b/base/map/lib/10d.js new file mode 100644 index 00000000..33c44ecd --- /dev/null +++ b/base/map/lib/10d.js @@ -0,0 +1,280 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a ten-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map10d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map10d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dx9; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var dy9; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var S9; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var i9; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 9 ]; + S1 = sh[ 8 ]; + S2 = sh[ 7 ]; + S3 = sh[ 6 ]; + S4 = sh[ 5 ]; + S5 = sh[ 4 ]; + S6 = sh[ 3 ]; + S7 = sh[ 2 ]; + S8 = sh[ 1 ]; + S9 = sh[ 0 ]; + dx0 = sx[ 9 ]; // offset increment for innermost loop + dx1 = sx[ 8 ] - ( S0*sx[9] ); + dx2 = sx[ 7 ] - ( S1*sx[8] ); + dx3 = sx[ 6 ] - ( S2*sx[7] ); + dx4 = sx[ 5 ] - ( S3*sx[6] ); + dx5 = sx[ 4 ] - ( S4*sx[5] ); + dx6 = sx[ 3 ] - ( S5*sx[4] ); + dx7 = sx[ 2 ] - ( S6*sx[3] ); + dx8 = sx[ 1 ] - ( S7*sx[2] ); + dx9 = sx[ 0 ] - ( S8*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 9 ]; + dy1 = sy[ 8 ] - ( S0*sy[9] ); + dy2 = sy[ 7 ] - ( S1*sy[8] ); + dy3 = sy[ 6 ] - ( S2*sy[7] ); + dy4 = sy[ 5 ] - ( S3*sy[6] ); + dy5 = sy[ 4 ] - ( S4*sy[5] ); + dy6 = sy[ 3 ] - ( S5*sy[4] ); + dy7 = sy[ 2 ] - ( S6*sy[3] ); + dy8 = sy[ 1 ] - ( S7*sy[2] ); + dy9 = sy[ 0 ] - ( S8*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + S8 = sh[ 8 ]; + S9 = sh[ 9 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); + dx8 = sx[ 8 ] - ( S7*sx[7] ); + dx9 = sx[ 9 ] - ( S8*sx[8] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + dy8 = sy[ 8 ] - ( S7*sy[7] ); + dy9 = sy[ 9 ] - ( S8*sy[8] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i9 = 0; i9 < S9; i9++ ) { + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i9, i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + ix += dx9; + iy += dy9; + } +} + + +// EXPORTS // + +module.exports = map10d; diff --git a/base/map/lib/10d_accessors.js b/base/map/lib/10d_accessors.js new file mode 100644 index 00000000..35e94869 --- /dev/null +++ b/base/map/lib/10d_accessors.js @@ -0,0 +1,305 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a ten-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map10d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map10d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dx9; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var dy9; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var S9; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var i9; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 9 ]; + S1 = sh[ 8 ]; + S2 = sh[ 7 ]; + S3 = sh[ 6 ]; + S4 = sh[ 5 ]; + S5 = sh[ 4 ]; + S6 = sh[ 3 ]; + S7 = sh[ 2 ]; + S8 = sh[ 1 ]; + S9 = sh[ 0 ]; + dx0 = sx[ 9 ]; // offset increment for innermost loop + dx1 = sx[ 8 ] - ( S0*sx[9] ); + dx2 = sx[ 7 ] - ( S1*sx[8] ); + dx3 = sx[ 6 ] - ( S2*sx[7] ); + dx4 = sx[ 5 ] - ( S3*sx[6] ); + dx5 = sx[ 4 ] - ( S4*sx[5] ); + dx6 = sx[ 3 ] - ( S5*sx[4] ); + dx7 = sx[ 2 ] - ( S6*sx[3] ); + dx8 = sx[ 1 ] - ( S7*sx[2] ); + dx9 = sx[ 0 ] - ( S8*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 9 ]; + dy1 = sy[ 8 ] - ( S0*sy[9] ); + dy2 = sy[ 7 ] - ( S1*sy[8] ); + dy3 = sy[ 6 ] - ( S2*sy[7] ); + dy4 = sy[ 5 ] - ( S3*sy[6] ); + dy5 = sy[ 4 ] - ( S4*sy[5] ); + dy6 = sy[ 3 ] - ( S5*sy[4] ); + dy7 = sy[ 2 ] - ( S6*sy[3] ); + dy8 = sy[ 1 ] - ( S7*sy[2] ); + dy9 = sy[ 0 ] - ( S8*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + S8 = sh[ 8 ]; + S9 = sh[ 9 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); + dx8 = sx[ 8 ] - ( S7*sx[7] ); + dx9 = sx[ 9 ] - ( S8*sx[8] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + dy8 = sy[ 8 ] - ( S7*sy[7] ); + dy9 = sy[ 9 ] - ( S8*sy[8] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i9 = 0; i9 < S9; i9++ ) { + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i9, i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + ix += dx9; + iy += dy9; + } +} + + +// EXPORTS // + +module.exports = map10d; diff --git a/base/map/lib/10d_blocked.js b/base/map/lib/10d_blocked.js new file mode 100644 index 00000000..9a3df42b --- /dev/null +++ b/base/map/lib/10d_blocked.js @@ -0,0 +1,389 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a ten-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap10d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap10d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dx9; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var dy9; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var ox8; + var ox9; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var oy8; + var oy9; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var S9; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var i9; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var j8; + var j9; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j9 = sh[9]; j9 > 0; ) { + if ( j9 < bsize ) { + S9 = j9; + j9 = 0; + } else { + S9 = bsize; + j9 -= bsize; + } + ox9 = ox + ( j9*sx[9] ); + oy9 = oy + ( j9*sy[9] ); + for ( j8 = sh[8]; j8 > 0; ) { + if ( j8 < bsize ) { + S8 = j8; + j8 = 0; + } else { + S8 = bsize; + j8 -= bsize; + } + dx9 = sx[9] - ( S8*sx[8] ); + dy9 = sy[9] - ( S8*sy[8] ); + ox8 = ox9 + ( j8*sx[8] ); + oy8 = oy9 + ( j8*sy[8] ); + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + dx8 = sx[8] - ( S7*sx[7] ); + dy8 = sy[8] - ( S7*sy[7] ); + ox7 = ox8 + ( j7*sx[7] ); + oy7 = oy8 + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i9 = 0; i9 < S9; i9++ ) { + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i9, i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + ix += dx9; + iy += dy9; + } + } + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap10d; diff --git a/base/map/lib/10d_blocked_accessors.js b/base/map/lib/10d_blocked_accessors.js new file mode 100644 index 00000000..88d9f7e8 --- /dev/null +++ b/base/map/lib/10d_blocked_accessors.js @@ -0,0 +1,414 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a ten-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap10d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap10d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dx9; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var dy9; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var ox8; + var ox9; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var oy8; + var oy9; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var S9; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var i9; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var j8; + var j9; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j9 = sh[9]; j9 > 0; ) { + if ( j9 < bsize ) { + S9 = j9; + j9 = 0; + } else { + S9 = bsize; + j9 -= bsize; + } + ox9 = ox + ( j9*sx[9] ); + oy9 = oy + ( j9*sy[9] ); + for ( j8 = sh[8]; j8 > 0; ) { + if ( j8 < bsize ) { + S8 = j8; + j8 = 0; + } else { + S8 = bsize; + j8 -= bsize; + } + dx9 = sx[9] - ( S8*sx[8] ); + dy9 = sy[9] - ( S8*sy[8] ); + ox8 = ox9 + ( j8*sx[8] ); + oy8 = oy9 + ( j8*sy[8] ); + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + dx8 = sx[8] - ( S7*sx[7] ); + dy8 = sy[8] - ( S7*sy[7] ); + ox7 = ox8 + ( j7*sx[7] ); + oy7 = oy8 + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i9 = 0; i9 < S9; i9++ ) { + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i9, i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + ix += dx9; + iy += dy9; + } + } + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap10d; diff --git a/base/map/lib/1d.js b/base/map/lib/1d.js new file mode 100644 index 00000000..e73a9510 --- /dev/null +++ b/base/map/lib/1d.js @@ -0,0 +1,129 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Applies a callback function to elements in a one-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Float64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 4 ]; +* +* // Define the array strides: +* var sx = [ 2 ]; +* var sy = [ 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map1d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 40.0, 60.0, 80.0 ] +*/ +function map1d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dy0; + var S0; + var ix; + var iy; + var i0; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables: dimensions and loop offset (pointer) increments... + S0 = x.shape[ 0 ]; + dx0 = x.strides[ 0 ]; + dy0 = y.strides[ 0 ]; + + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], [ i0 ], x.ref ); + ix += dx0; + iy += dy0; + } +} + + +// EXPORTS // + +module.exports = map1d; diff --git a/base/map/lib/1d_accessors.js b/base/map/lib/1d_accessors.js new file mode 100644 index 00000000..55dc3bef --- /dev/null +++ b/base/map/lib/1d_accessors.js @@ -0,0 +1,154 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MAIN // + +/** +* Applies a callback function to elements in a one-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 4 ]; +* +* // Define the array strides: +* var sx = [ 1 ]; +* var sy = [ 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map1d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map1d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dy0; + var S0; + var ix; + var iy; + var i0; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables: dimensions and loop offset (pointer) increments... + S0 = x.shape[ 0 ]; + dx0 = x.strides[ 0 ]; + dy0 = y.strides[ 0 ]; + + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), [ i0 ], x.ref ) ); + ix += dx0; + iy += dy0; + } +} + + +// EXPORTS // + +module.exports = map1d; diff --git a/base/map/lib/2d.js b/base/map/lib/2d.js new file mode 100644 index 00000000..1ef6dcd0 --- /dev/null +++ b/base/map/lib/2d.js @@ -0,0 +1,166 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a two-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Float64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map2d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0 ] +*/ +function map2d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dy0; + var dy1; + var idx; + var sh; + var S0; + var S1; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 1 ]; + S1 = sh[ 0 ]; + dx0 = sx[ 1 ]; // offset increment for the outermost loop + dx1 = sx[ 0 ] - ( S0*sx[1] ); // offset increment for innermost loop + dy0 = sy[ 1 ]; + dy1 = sy[ 0 ] - ( S0*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + dx0 = sx[ 0 ]; // offset increment for outermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); // offset increment for innermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sx[0] ); + idx = reverse( idx ); + } + // Set the pointer to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache the references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } +} + + +// EXPORTS // + +module.exports = map2d; diff --git a/base/map/lib/2d_accessors.js b/base/map/lib/2d_accessors.js new file mode 100644 index 00000000..a5f7716f --- /dev/null +++ b/base/map/lib/2d_accessors.js @@ -0,0 +1,191 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a two-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 2, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map2d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map2d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dy0; + var dy1; + var idx; + var sh; + var S0; + var S1; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 1 ]; + S1 = sh[ 0 ]; + dx0 = sx[ 1 ]; // offset increment for the outermost loop + dx1 = sx[ 0 ] - ( S0*sx[1] ); // offset increment for innermost loop + dy0 = sy[ 1 ]; + dy1 = sy[ 0 ] - ( S0*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + dx0 = sx[ 0 ]; // offset increment for outermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); // offset increment for innermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sx[0] ); + idx = reverse( idx ); + } + // Set the pointer to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache the references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } +} + + +// EXPORTS // + +module.exports = map2d; diff --git a/base/map/lib/2d_blocked.js b/base/map/lib/2d_blocked.js new file mode 100644 index 00000000..a0c121e4 --- /dev/null +++ b/base/map/lib/2d_blocked.js @@ -0,0 +1,195 @@ +/** +* @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 loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a two-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Float64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap2d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0 ] +*/ +function blockedmap2d( x, y, fcn, thisArg ) { + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dy0; + var dy1; + var ox1; + var oy1; + var idx; + var sh; + var s0; + var s1; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var j0; + var j1; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache the references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + s1 = j1; + j1 = 0; + } else { + s1 = bsize; + j1 -= bsize; + } + ox1 = ox + ( j1*sx[1] ); + oy1 = oy + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + s0 = j0; + j0 = 0; + } else { + s0 = bsize; + j0 -= bsize; + } + // Compute the index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + (j0*sx[0]); + iy = oy1 + (j0*sy[0]); + + // Compute the loop offset increments... + dx1 = sx[1] - (s0*sx[0]); + dy1 = sy[1] - (s0*sy[0]); + + // Iterate over the ndarray dimensions... + for ( i1 = 0; i1 < s1; i1++ ) { + for ( i0 = 0; i0 < s0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap2d; diff --git a/base/map/lib/2d_blocked_accessors.js b/base/map/lib/2d_blocked_accessors.js new file mode 100644 index 00000000..970accab --- /dev/null +++ b/base/map/lib/2d_blocked_accessors.js @@ -0,0 +1,220 @@ +/** +* @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 loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a two-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 2, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap2d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap2d( x, y, fcn, thisArg ) { + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dy0; + var dy1; + var ox1; + var oy1; + var idx; + var get; + var set; + var sh; + var s0; + var s1; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var j0; + var j1; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache the references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + s1 = j1; + j1 = 0; + } else { + s1 = bsize; + j1 -= bsize; + } + ox1 = ox + ( j1*sx[1] ); + oy1 = oy + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + s0 = j0; + j0 = 0; + } else { + s0 = bsize; + j0 -= bsize; + } + // Compute the index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + (j0*sx[0]); + iy = oy1 + (j0*sy[0]); + + // Compute the loop offset increments... + dx1 = sx[1] - (s0*sx[0]); + dy1 = sy[1] - (s0*sy[0]); + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over the ndarray dimensions... + for ( i1 = 0; i1 < s1; i1++ ) { + for ( i0 = 0; i0 < s0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap2d; diff --git a/base/map/lib/3d.js b/base/map/lib/3d.js new file mode 100644 index 00000000..45d810f9 --- /dev/null +++ b/base/map/lib/3d.js @@ -0,0 +1,180 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a three-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map3d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map3d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dy0; + var dy1; + var dy2; + var idx; + var sh; + var S0; + var S1; + var S2; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 2 ]; + S1 = sh[ 1 ]; + S2 = sh[ 0 ]; + dx0 = sx[ 2 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[2] ); + dx2 = sx[ 0 ] - ( S1*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 2 ]; + dy1 = sy[ 1 ] - ( S0*sy[2] ); + dy2 = sy[ 0 ] - ( S1*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } +} + + +// EXPORTS // + +module.exports = map3d; diff --git a/base/map/lib/3d_accessors.js b/base/map/lib/3d_accessors.js new file mode 100644 index 00000000..070474df --- /dev/null +++ b/base/map/lib/3d_accessors.js @@ -0,0 +1,205 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a three-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 2, 1 ]; +* var sy = [ 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map3d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map3d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dy0; + var dy1; + var dy2; + var idx; + var get; + var set; + var sh; + var S0; + var S1; + var S2; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 2 ]; + S1 = sh[ 1 ]; + S2 = sh[ 0 ]; + dx0 = sx[ 2 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[2] ); + dx2 = sx[ 0 ] - ( S1*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 2 ]; + dy1 = sy[ 1 ] - ( S0*sy[2] ); + dy2 = sy[ 0 ] - ( S1*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } +} + + +// EXPORTS // + +module.exports = map3d; diff --git a/base/map/lib/3d_blocked.js b/base/map/lib/3d_blocked.js new file mode 100644 index 00000000..ba20f351 --- /dev/null +++ b/base/map/lib/3d_blocked.js @@ -0,0 +1,221 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a three-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( x ) { +* return x * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap3d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap3d( x, y, fcn, thisArg ) { + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dy0; + var dy1; + var dy2; + var ox1; + var ox2; + var oy1; + var oy2; + var idx; + var sh; + var s0; + var s1; + var s2; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var j0; + var j1; + var j2; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + s2 = j2; + j2 = 0; + } else { + s2 = bsize; + j2 -= bsize; + } + ox2 = ox + ( j2*sx[2] ); + oy2 = oy + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + s1 = j1; + j1 = 0; + } else { + s1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( s1*sx[1] ); + dy2 = sy[2] - ( s1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + s0 = j0; + j0 = 0; + } else { + s0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( s0*sx[0] ); + dy1 = sy[1] - ( s0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i2 = 0; i2 < s2; i2++ ) { + for ( i1 = 0; i1 < s1; i1++ ) { + for ( i0 = 0; i0 < s0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap3d; diff --git a/base/map/lib/3d_blocked_accessors.js b/base/map/lib/3d_blocked_accessors.js new file mode 100644 index 00000000..6d87e658 --- /dev/null +++ b/base/map/lib/3d_blocked_accessors.js @@ -0,0 +1,246 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a three-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 2, 2, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap3d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap3d( x, y, fcn, thisArg ) { + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dy0; + var dy1; + var dy2; + var ox1; + var ox2; + var oy1; + var oy2; + var idx; + var get; + var set; + var sh; + var s0; + var s1; + var s2; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var j0; + var j1; + var j2; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + s2 = j2; + j2 = 0; + } else { + s2 = bsize; + j2 -= bsize; + } + ox2 = ox + ( j2*sx[2] ); + oy2 = oy + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + s1 = j1; + j1 = 0; + } else { + s1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( s1*sx[1] ); + dy2 = sy[2] - ( s1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + s0 = j0; + j0 = 0; + } else { + s0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( s0*sx[0] ); + dy1 = sy[1] - ( s0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i2 = 0; i2 < s2; i2++ ) { + for ( i1 = 0; i1 < s1; i1++ ) { + for ( i0 = 0; i0 < s0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap3d; diff --git a/base/map/lib/4d.js b/base/map/lib/4d.js new file mode 100644 index 00000000..12548b36 --- /dev/null +++ b/base/map/lib/4d.js @@ -0,0 +1,194 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a four-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 4, 4, 1 ]; +* var sy = [ 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map4d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map4d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dy0; + var dy1; + var dy2; + var dy3; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 3 ]; + S1 = sh[ 2 ]; + S2 = sh[ 1 ]; + S3 = sh[ 0 ]; + dx0 = sx[ 3 ]; // offset increment for innermost loop + dx1 = sx[ 2 ] - ( S0*sx[3] ); + dx2 = sx[ 1 ] - ( S1*sx[2] ); + dx3 = sx[ 0 ] - ( S2*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 3 ]; + dy1 = sy[ 2 ] - ( S0*sy[3] ); + dy2 = sy[ 1 ] - ( S1*sy[2] ); + dy3 = sy[ 0 ] - ( S2*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } +} + + +// EXPORTS // + +module.exports = map4d; diff --git a/base/map/lib/4d_accessors.js b/base/map/lib/4d_accessors.js new file mode 100644 index 00000000..421a1ff2 --- /dev/null +++ b/base/map/lib/4d_accessors.js @@ -0,0 +1,219 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a four-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map4d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map4d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dy0; + var dy1; + var dy2; + var dy3; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 3 ]; + S1 = sh[ 2 ]; + S2 = sh[ 1 ]; + S3 = sh[ 0 ]; + dx0 = sx[ 3 ]; // offset increment for innermost loop + dx1 = sx[ 2 ] - ( S0*sx[3] ); + dx2 = sx[ 1 ] - ( S1*sx[2] ); + dx3 = sx[ 0 ] - ( S2*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 3 ]; + dy1 = sy[ 2 ] - ( S0*sy[3] ); + dy2 = sy[ 1 ] - ( S1*sy[2] ); + dy3 = sy[ 0 ] - ( S2*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } +} + + +// EXPORTS // + +module.exports = map4d; diff --git a/base/map/lib/4d_blocked.js b/base/map/lib/4d_blocked.js new file mode 100644 index 00000000..d956e015 --- /dev/null +++ b/base/map/lib/4d_blocked.js @@ -0,0 +1,245 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a four-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( x ) { +* return x * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 4, 4, 1 ]; +* var sy = [ 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap4d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap4d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dy0; + var dy1; + var dy2; + var dy3; + var ox1; + var ox2; + var ox3; + var idx; + var oy1; + var oy2; + var oy3; + var sh; + var S0; + var S1; + var S2; + var S3; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var j0; + var j1; + var j2; + var j3; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + ox3 = ox + ( j3*sx[3] ); + oy3 = oy + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap4d; diff --git a/base/map/lib/4d_blocked_accessors.js b/base/map/lib/4d_blocked_accessors.js new file mode 100644 index 00000000..26854967 --- /dev/null +++ b/base/map/lib/4d_blocked_accessors.js @@ -0,0 +1,270 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a four-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap4d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap4d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dy0; + var dy1; + var dy2; + var dy3; + var ox1; + var ox2; + var ox3; + var idx; + var oy1; + var oy2; + var oy3; + var sh; + var S0; + var S1; + var S2; + var S3; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var j0; + var j1; + var j2; + var j3; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + ox3 = ox + ( j3*sx[3] ); + oy3 = oy + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap4d; diff --git a/base/map/lib/5d.js b/base/map/lib/5d.js new file mode 100644 index 00000000..023b34f5 --- /dev/null +++ b/base/map/lib/5d.js @@ -0,0 +1,208 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a five-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map5d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map5d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 4 ]; + S1 = sh[ 3 ]; + S2 = sh[ 2 ]; + S3 = sh[ 1 ]; + S4 = sh[ 0 ]; + dx0 = sx[ 4 ]; // offset increment for innermost loop + dx1 = sx[ 3 ] - ( S0*sx[4] ); + dx2 = sx[ 2 ] - ( S1*sx[3] ); + dx3 = sx[ 1 ] - ( S2*sx[2] ); + dx4 = sx[ 0 ] - ( S3*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 4 ]; + dy1 = sy[ 3 ] - ( S0*sy[4] ); + dy2 = sy[ 2 ] - ( S1*sy[3] ); + dy3 = sy[ 1 ] - ( S2*sy[2] ); + dy4 = sy[ 0 ] - ( S3*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } +} + + +// EXPORTS // + +module.exports = map5d; diff --git a/base/map/lib/5d_accessors.js b/base/map/lib/5d_accessors.js new file mode 100644 index 00000000..e63ce107 --- /dev/null +++ b/base/map/lib/5d_accessors.js @@ -0,0 +1,233 @@ +/** +* @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 zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a five-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map5d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map5d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 4 ]; + S1 = sh[ 3 ]; + S2 = sh[ 2 ]; + S3 = sh[ 1 ]; + S4 = sh[ 0 ]; + dx0 = sx[ 4 ]; // offset increment for innermost loop + dx1 = sx[ 3 ] - ( S0*sx[4] ); + dx2 = sx[ 2 ] - ( S1*sx[3] ); + dx3 = sx[ 1 ] - ( S2*sx[2] ); + dx4 = sx[ 0 ] - ( S3*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 4 ]; + dy1 = sy[ 3 ] - ( S0*sy[4] ); + dy2 = sy[ 2 ] - ( S1*sy[3] ); + dy3 = sy[ 1 ] - ( S2*sy[2] ); + dy4 = sy[ 0 ] - ( S3*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } +} + + +// EXPORTS // + +module.exports = map5d; diff --git a/base/map/lib/5d_blocked.js b/base/map/lib/5d_blocked.js new file mode 100644 index 00000000..634851c6 --- /dev/null +++ b/base/map/lib/5d_blocked.js @@ -0,0 +1,269 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a five-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap5d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap5d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var ox1; + var ox2; + var ox3; + var ox4; + var idx; + var oy1; + var oy2; + var oy3; + var oy4; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var j0; + var j1; + var j2; + var j3; + var j4; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + ox4 = ox + ( j4*sx[4] ); + oy4 = oy + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap5d; diff --git a/base/map/lib/5d_blocked_accessors.js b/base/map/lib/5d_blocked_accessors.js new file mode 100644 index 00000000..cce943fa --- /dev/null +++ b/base/map/lib/5d_blocked_accessors.js @@ -0,0 +1,294 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a five-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap5d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap5d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var ox1; + var ox2; + var ox3; + var ox4; + var idx; + var oy1; + var oy2; + var oy3; + var oy4; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var j0; + var j1; + var j2; + var j3; + var j4; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + ox4 = ox + ( j4*sx[4] ); + oy4 = oy + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap5d; diff --git a/base/map/lib/6d.js b/base/map/lib/6d.js new file mode 100644 index 00000000..db66a085 --- /dev/null +++ b/base/map/lib/6d.js @@ -0,0 +1,224 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a six-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map6d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map6d( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 5 ]; + S1 = sh[ 4 ]; + S2 = sh[ 3 ]; + S3 = sh[ 2 ]; + S4 = sh[ 1 ]; + S5 = sh[ 0 ]; + dx0 = sx[ 5 ]; // offset increment for innermost loop + dx1 = sx[ 4 ] - ( S0*sx[5] ); + dx2 = sx[ 3 ] - ( S1*sx[4] ); + dx3 = sx[ 2 ] - ( S2*sx[3] ); + dx4 = sx[ 1 ] - ( S3*sx[2] ); + dx5 = sx[ 0 ] - ( S4*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 5 ]; + dy1 = sy[ 4 ] - ( S0*sy[5] ); + dy2 = sy[ 3 ] - ( S1*sy[4] ); + dy3 = sy[ 2 ] - ( S2*sy[3] ); + dy4 = sy[ 1 ] - ( S3*sy[2] ); + dy5 = sy[ 0 ] - ( S4*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } +} + + +// EXPORTS // + +module.exports = map6d; diff --git a/base/map/lib/6d_accessors.js b/base/map/lib/6d_accessors.js new file mode 100644 index 00000000..9d3d4f91 --- /dev/null +++ b/base/map/lib/6d_accessors.js @@ -0,0 +1,249 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a six-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map6d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map6d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 5 ]; + S1 = sh[ 4 ]; + S2 = sh[ 3 ]; + S3 = sh[ 2 ]; + S4 = sh[ 1 ]; + S5 = sh[ 0 ]; + dx0 = sx[ 5 ]; // offset increment for innermost loop + dx1 = sx[ 4 ] - ( S0*sx[5] ); + dx2 = sx[ 3 ] - ( S1*sx[4] ); + dx3 = sx[ 2 ] - ( S2*sx[3] ); + dx4 = sx[ 1 ] - ( S3*sx[2] ); + dx5 = sx[ 0 ] - ( S4*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 5 ]; + dy1 = sy[ 4 ] - ( S0*sy[5] ); + dy2 = sy[ 3 ] - ( S1*sy[4] ); + dy3 = sy[ 2 ] - ( S2*sy[3] ); + dy4 = sy[ 1 ] - ( S3*sy[2] ); + dy5 = sy[ 0 ] - ( S4*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } +} + + +// EXPORTS // + +module.exports = map6d; diff --git a/base/map/lib/6d_blocked.js b/base/map/lib/6d_blocked.js new file mode 100644 index 00000000..9502c712 --- /dev/null +++ b/base/map/lib/6d_blocked.js @@ -0,0 +1,293 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a six-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap6d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap6d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + ox5 = ox + ( j5*sx[5] ); + oy5 = oy + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap6d; diff --git a/base/map/lib/6d_blocked_accessors.js b/base/map/lib/6d_blocked_accessors.js new file mode 100644 index 00000000..2f7c590a --- /dev/null +++ b/base/map/lib/6d_blocked_accessors.js @@ -0,0 +1,318 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a six-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap6d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap6d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var set; + var get; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + ox5 = ox + ( j5*sx[5] ); + oy5 = oy + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap6d; diff --git a/base/map/lib/7d.js b/base/map/lib/7d.js new file mode 100644 index 00000000..017250bf --- /dev/null +++ b/base/map/lib/7d.js @@ -0,0 +1,238 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a seven-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map7d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map7d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 6 ]; + S1 = sh[ 5 ]; + S2 = sh[ 4 ]; + S3 = sh[ 3 ]; + S4 = sh[ 2 ]; + S5 = sh[ 1 ]; + S6 = sh[ 0 ]; + dx0 = sx[ 6 ]; // offset increment for innermost loop + dx1 = sx[ 5 ] - ( S0*sx[6] ); + dx2 = sx[ 4 ] - ( S1*sx[5] ); + dx3 = sx[ 3 ] - ( S2*sx[4] ); + dx4 = sx[ 2 ] - ( S3*sx[3] ); + dx5 = sx[ 1 ] - ( S4*sx[2] ); + dx6 = sx[ 0 ] - ( S5*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 6 ]; + dy1 = sy[ 5 ] - ( S0*sy[6] ); + dy2 = sy[ 4 ] - ( S1*sy[5] ); + dy3 = sy[ 3 ] - ( S2*sy[4] ); + dy4 = sy[ 2 ] - ( S3*sy[3] ); + dy5 = sy[ 1 ] - ( S4*sy[2] ); + dy6 = sy[ 0 ] - ( S5*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } +} + + +// EXPORTS // + +module.exports = map7d; diff --git a/base/map/lib/7d_accessors.js b/base/map/lib/7d_accessors.js new file mode 100644 index 00000000..08bd0eeb --- /dev/null +++ b/base/map/lib/7d_accessors.js @@ -0,0 +1,263 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a seven-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map7d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map7d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 6 ]; + S1 = sh[ 5 ]; + S2 = sh[ 4 ]; + S3 = sh[ 3 ]; + S4 = sh[ 2 ]; + S5 = sh[ 1 ]; + S6 = sh[ 0 ]; + dx0 = sx[ 6 ]; // offset increment for innermost loop + dx1 = sx[ 5 ] - ( S0*sx[6] ); + dx2 = sx[ 4 ] - ( S1*sx[5] ); + dx3 = sx[ 3 ] - ( S2*sx[4] ); + dx4 = sx[ 2 ] - ( S3*sx[3] ); + dx5 = sx[ 1 ] - ( S4*sx[2] ); + dx6 = sx[ 0 ] - ( S5*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 6 ]; + dy1 = sy[ 5 ] - ( S0*sy[6] ); + dy2 = sy[ 4 ] - ( S1*sy[5] ); + dy3 = sy[ 3 ] - ( S2*sy[4] ); + dy4 = sy[ 2 ] - ( S3*sy[3] ); + dy5 = sy[ 1 ] - ( S4*sy[2] ); + dy6 = sy[ 0 ] - ( S5*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } +} + + +// EXPORTS // + +module.exports = map7d; diff --git a/base/map/lib/7d_blocked.js b/base/map/lib/7d_blocked.js new file mode 100644 index 00000000..13bccddb --- /dev/null +++ b/base/map/lib/7d_blocked.js @@ -0,0 +1,317 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a seven-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap7d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap7d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + ox6 = ox + ( j6*sx[6] ); + oy6 = oy + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap7d; diff --git a/base/map/lib/7d_blocked_accessors.js b/base/map/lib/7d_blocked_accessors.js new file mode 100644 index 00000000..18f24f08 --- /dev/null +++ b/base/map/lib/7d_blocked_accessors.js @@ -0,0 +1,342 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a seven-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap7d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap7d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + ox6 = ox + ( j6*sx[6] ); + oy6 = oy + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap7d; diff --git a/base/map/lib/8d.js b/base/map/lib/8d.js new file mode 100644 index 00000000..d7cf1210 --- /dev/null +++ b/base/map/lib/8d.js @@ -0,0 +1,252 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in an eight-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map8d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map8d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 7 ]; + S1 = sh[ 6 ]; + S2 = sh[ 5 ]; + S3 = sh[ 4 ]; + S4 = sh[ 3 ]; + S5 = sh[ 2 ]; + S6 = sh[ 1 ]; + S7 = sh[ 0 ]; + dx0 = sx[ 7 ]; // offset increment for innermost loop + dx1 = sx[ 6 ] - ( S0*sx[7] ); + dx2 = sx[ 5 ] - ( S1*sx[6] ); + dx3 = sx[ 4 ] - ( S2*sx[5] ); + dx4 = sx[ 3 ] - ( S3*sx[4] ); + dx5 = sx[ 2 ] - ( S4*sx[3] ); + dx6 = sx[ 1 ] - ( S5*sx[2] ); + dx7 = sx[ 0 ] - ( S6*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 7 ]; + dy1 = sy[ 6 ] - ( S0*sy[7] ); + dy2 = sy[ 5 ] - ( S1*sy[6] ); + dy3 = sy[ 4 ] - ( S2*sy[5] ); + dy4 = sy[ 3 ] - ( S3*sy[4] ); + dy5 = sy[ 2 ] - ( S4*sy[3] ); + dy6 = sy[ 1 ] - ( S5*sy[2] ); + dy7 = sy[ 0 ] - ( S6*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } +} + + +// EXPORTS // + +module.exports = map8d; diff --git a/base/map/lib/8d_accessors.js b/base/map/lib/8d_accessors.js new file mode 100644 index 00000000..606afa92 --- /dev/null +++ b/base/map/lib/8d_accessors.js @@ -0,0 +1,277 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in an eight-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map8d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map8d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 7 ]; + S1 = sh[ 6 ]; + S2 = sh[ 5 ]; + S3 = sh[ 4 ]; + S4 = sh[ 3 ]; + S5 = sh[ 2 ]; + S6 = sh[ 1 ]; + S7 = sh[ 0 ]; + dx0 = sx[ 7 ]; // offset increment for innermost loop + dx1 = sx[ 6 ] - ( S0*sx[7] ); + dx2 = sx[ 5 ] - ( S1*sx[6] ); + dx3 = sx[ 4 ] - ( S2*sx[5] ); + dx4 = sx[ 3 ] - ( S3*sx[4] ); + dx5 = sx[ 2 ] - ( S4*sx[3] ); + dx6 = sx[ 1 ] - ( S5*sx[2] ); + dx7 = sx[ 0 ] - ( S6*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 7 ]; + dy1 = sy[ 6 ] - ( S0*sy[7] ); + dy2 = sy[ 5 ] - ( S1*sy[6] ); + dy3 = sy[ 4 ] - ( S2*sy[5] ); + dy4 = sy[ 3 ] - ( S3*sy[4] ); + dy5 = sy[ 2 ] - ( S4*sy[3] ); + dy6 = sy[ 1 ] - ( S5*sy[2] ); + dy7 = sy[ 0 ] - ( S6*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } +} + + +// EXPORTS // + +module.exports = map8d; diff --git a/base/map/lib/8d_blocked.js b/base/map/lib/8d_blocked.js new file mode 100644 index 00000000..21763d70 --- /dev/null +++ b/base/map/lib/8d_blocked.js @@ -0,0 +1,341 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in an eight-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap8d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap8d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + ox7 = ox + ( j7*sx[7] ); + oy7 = oy + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap8d; diff --git a/base/map/lib/8d_blocked_accessors.js b/base/map/lib/8d_blocked_accessors.js new file mode 100644 index 00000000..e1bfa6ff --- /dev/null +++ b/base/map/lib/8d_blocked_accessors.js @@ -0,0 +1,366 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in an eight-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap8d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap8d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + ox7 = ox + ( j7*sx[7] ); + oy7 = oy + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap8d; diff --git a/base/map/lib/9d.js b/base/map/lib/9d.js new file mode 100644 index 00000000..a062d0fb --- /dev/null +++ b/base/map/lib/9d.js @@ -0,0 +1,266 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a nine-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map9d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map9d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 8 ]; + S1 = sh[ 7 ]; + S2 = sh[ 6 ]; + S3 = sh[ 5 ]; + S4 = sh[ 4 ]; + S5 = sh[ 3 ]; + S6 = sh[ 2 ]; + S7 = sh[ 1 ]; + S8 = sh[ 0 ]; + dx0 = sx[ 8 ]; // offset increment for innermost loop + dx1 = sx[ 7 ] - ( S0*sx[8] ); + dx2 = sx[ 6 ] - ( S1*sx[7] ); + dx3 = sx[ 5 ] - ( S2*sx[6] ); + dx4 = sx[ 4 ] - ( S3*sx[5] ); + dx5 = sx[ 3 ] - ( S4*sx[4] ); + dx6 = sx[ 2 ] - ( S5*sx[3] ); + dx7 = sx[ 1 ] - ( S6*sx[2] ); + dx8 = sx[ 0 ] - ( S7*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 8 ]; + dy1 = sy[ 7 ] - ( S0*sy[8] ); + dy2 = sy[ 6 ] - ( S1*sy[7] ); + dy3 = sy[ 5 ] - ( S2*sy[6] ); + dy4 = sy[ 4 ] - ( S3*sy[5] ); + dy5 = sy[ 3 ] - ( S4*sy[4] ); + dy6 = sy[ 2 ] - ( S5*sy[3] ); + dy7 = sy[ 1 ] - ( S6*sy[2] ); + dy8 = sy[ 0 ] - ( S7*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + S8 = sh[ 8 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); + dx8 = sx[ 8 ] - ( S7*sx[7] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + dy8 = sy[ 8 ] - ( S7*sy[7] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Iterate over the ndarray dimensions... + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } +} + + +// EXPORTS // + +module.exports = map9d; diff --git a/base/map/lib/9d_accessors.js b/base/map/lib/9d_accessors.js new file mode 100644 index 00000000..e08eefdc --- /dev/null +++ b/base/map/lib/9d_accessors.js @@ -0,0 +1,291 @@ +/** +* @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-depth */ + +'use strict'; + +// MODULES // + +var zeroTo = require( '@stdlib/array/base/zero-to' ); +var reverse = require( '@stdlib/array/base/reverse' ); +var take = require( '@stdlib/array/base/take-indexed' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a nine-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* map9d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function map9d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var sx; + var sy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + + // Note on variable naming convention: S#, dx#, dy#, i# where # corresponds to the loop number, with `0` being the innermost loop... + + // Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... + sh = x.shape; + sx = x.strides; + sy = y.strides; + idx = zeroTo( sh.length ); + if ( x.order === 'row-major' ) { + // For row-major ndarrays, the last dimensions have the fastest changing indices... + S0 = sh[ 8 ]; + S1 = sh[ 7 ]; + S2 = sh[ 6 ]; + S3 = sh[ 5 ]; + S4 = sh[ 4 ]; + S5 = sh[ 3 ]; + S6 = sh[ 2 ]; + S7 = sh[ 1 ]; + S8 = sh[ 0 ]; + dx0 = sx[ 8 ]; // offset increment for innermost loop + dx1 = sx[ 7 ] - ( S0*sx[8] ); + dx2 = sx[ 6 ] - ( S1*sx[7] ); + dx3 = sx[ 5 ] - ( S2*sx[6] ); + dx4 = sx[ 4 ] - ( S3*sx[5] ); + dx5 = sx[ 3 ] - ( S4*sx[4] ); + dx6 = sx[ 2 ] - ( S5*sx[3] ); + dx7 = sx[ 1 ] - ( S6*sx[2] ); + dx8 = sx[ 0 ] - ( S7*sx[1] ); // offset increment for outermost loop + dy0 = sy[ 8 ]; + dy1 = sy[ 7 ] - ( S0*sy[8] ); + dy2 = sy[ 6 ] - ( S1*sy[7] ); + dy3 = sy[ 5 ] - ( S2*sy[6] ); + dy4 = sy[ 4 ] - ( S3*sy[5] ); + dy5 = sy[ 3 ] - ( S4*sy[4] ); + dy6 = sy[ 2 ] - ( S5*sy[3] ); + dy7 = sy[ 1 ] - ( S6*sy[2] ); + dy8 = sy[ 0 ] - ( S7*sy[1] ); + } else { // order === 'column-major' + // For column-major ndarrays, the first dimensions have the fastest changing indices... + S0 = sh[ 0 ]; + S1 = sh[ 1 ]; + S2 = sh[ 2 ]; + S3 = sh[ 3 ]; + S4 = sh[ 4 ]; + S5 = sh[ 5 ]; + S6 = sh[ 6 ]; + S7 = sh[ 7 ]; + S8 = sh[ 8 ]; + dx0 = sx[ 0 ]; // offset increment for innermost loop + dx1 = sx[ 1 ] - ( S0*sx[0] ); + dx2 = sx[ 2 ] - ( S1*sx[1] ); + dx3 = sx[ 3 ] - ( S2*sx[2] ); + dx4 = sx[ 4 ] - ( S3*sx[3] ); + dx5 = sx[ 5 ] - ( S4*sx[4] ); + dx6 = sx[ 6 ] - ( S5*sx[5] ); + dx7 = sx[ 7 ] - ( S6*sx[6] ); + dx8 = sx[ 8 ] - ( S7*sx[7] ); // offset increment for outermost loop + dy0 = sy[ 0 ]; + dy1 = sy[ 1 ] - ( S0*sy[0] ); + dy2 = sy[ 2 ] - ( S1*sy[1] ); + dy3 = sy[ 3 ] - ( S2*sy[2] ); + dy4 = sy[ 4 ] - ( S3*sy[3] ); + dy5 = sy[ 5 ] - ( S4*sy[4] ); + dy6 = sy[ 6 ] - ( S5*sy[5] ); + dy7 = sy[ 7 ] - ( S6*sy[6] ); + dy8 = sy[ 8 ] - ( S7*sy[7] ); + idx = reverse( idx ); + } + // Set the pointers to the first indexed elements in the respective ndarrays... + ix = x.offset; + iy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over the ndarray dimensions... + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); // eslint-disable-line max-len + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } +} + + +// EXPORTS // + +module.exports = map9d; diff --git a/base/map/lib/9d_blocked.js b/base/map/lib/9d_blocked.js new file mode 100644 index 00000000..2063dd77 --- /dev/null +++ b/base/map/lib/9d_blocked.js @@ -0,0 +1,365 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a nine-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 12, 12, 12, 12, 12, 12, 4, 4, 1 ]; +* var sy = [ 6, 6, 6, 6, 6, 6, 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* blockedmap9d( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function blockedmap9d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var ox8; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var oy8; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var j8; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Iterate over blocks... + for ( j8 = sh[8]; j8 > 0; ) { + if ( j8 < bsize ) { + S8 = j8; + j8 = 0; + } else { + S8 = bsize; + j8 -= bsize; + } + ox8 = ox + ( j8*sx[8] ); + oy8 = oy + ( j8*sy[8] ); + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + dx8 = sx[8] - ( S7*sx[7] ); + dy8 = sy[8] - ( S7*sy[7] ); + ox7 = ox8 + ( j7*sx[7] ); + oy7 = oy8 + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], take( [ i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap9d; diff --git a/base/map/lib/9d_blocked_accessors.js b/base/map/lib/9d_blocked_accessors.js new file mode 100644 index 00000000..3e7f23d9 --- /dev/null +++ b/base/map/lib/9d_blocked_accessors.js @@ -0,0 +1,390 @@ +/** +* @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-depth, max-len */ + +'use strict'; + +// MODULES // + +var loopOrder = require( './../../../base/unary-loop-interchange-order' ); +var blockSize = require( './../../../base/unary-tiling-block-size' ); +var take = require( '@stdlib/array/base/take-indexed' ); +var reverse = require( '@stdlib/array/base/reverse' ); + + +// MAIN // + +/** +* Applies a callback function to elements in a nine-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray via loop blocking. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 1, 1, 1, 1, 1, 1, 1, 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* var sy = [ 4, 4, 4, 4, 4, 4, 4, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* blockedmap9d( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function blockedmap9d( x, y, fcn, thisArg ) { // eslint-disable-line max-statements, max-lines-per-function + var bsize; + var xbuf; + var ybuf; + var get; + var set; + var dx0; + var dx1; + var dx2; + var dx3; + var dx4; + var dx5; + var dx6; + var dx7; + var dx8; + var dy0; + var dy1; + var dy2; + var dy3; + var dy4; + var dy5; + var dy6; + var dy7; + var dy8; + var ox1; + var ox2; + var ox3; + var ox4; + var ox5; + var ox6; + var ox7; + var ox8; + var oy1; + var oy2; + var oy3; + var oy4; + var oy5; + var oy6; + var oy7; + var oy8; + var idx; + var sh; + var S0; + var S1; + var S2; + var S3; + var S4; + var S5; + var S6; + var S7; + var S8; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i0; + var i1; + var i2; + var i3; + var i4; + var i5; + var i6; + var i7; + var i8; + var j0; + var j1; + var j2; + var j3; + var j4; + var j5; + var j6; + var j7; + var j8; + var o; + + // Note on variable naming convention: s#, dx#, dy#, i#, j# where # corresponds to the loop number, with `0` being the innermost loop... + + // Resolve the loop interchange order: + o = loopOrder( x.shape, x.strides, y.strides ); + sh = o.sh; + sx = o.sx; + sy = o.sy; + idx = reverse( o.idx ); + + // Determine the block size: + bsize = blockSize( x.dtype, y.dtype ); + + // Cache the indices of the first indexed elements in the respective ndarrays... + ox = x.offset; + oy = y.offset; + + // Cache references to the input and output ndarray buffers... + xbuf = x.data; + ybuf = y.data; + + // Cache offset increments for the innermost loop... + dx0 = sx[0]; + dy0 = sy[0]; + + // Cache accessors: + get = x.accessors[0]; + set = y.accessors[1]; + + // Iterate over blocks... + for ( j8 = sh[8]; j8 > 0; ) { + if ( j8 < bsize ) { + S8 = j8; + j8 = 0; + } else { + S8 = bsize; + j8 -= bsize; + } + ox8 = ox + ( j8*sx[8] ); + oy8 = oy + ( j8*sy[8] ); + for ( j7 = sh[7]; j7 > 0; ) { + if ( j7 < bsize ) { + S7 = j7; + j7 = 0; + } else { + S7 = bsize; + j7 -= bsize; + } + dx8 = sx[8] - ( S7*sx[7] ); + dy8 = sy[8] - ( S7*sy[7] ); + ox7 = ox8 + ( j7*sx[7] ); + oy7 = oy8 + ( j7*sy[7] ); + for ( j6 = sh[6]; j6 > 0; ) { + if ( j6 < bsize ) { + S6 = j6; + j6 = 0; + } else { + S6 = bsize; + j6 -= bsize; + } + dx7 = sx[7] - ( S6*sx[6] ); + dy7 = sy[7] - ( S6*sy[6] ); + ox6 = ox7 + ( j6*sx[6] ); + oy6 = oy7 + ( j6*sy[6] ); + for ( j5 = sh[5]; j5 > 0; ) { + if ( j5 < bsize ) { + S5 = j5; + j5 = 0; + } else { + S5 = bsize; + j5 -= bsize; + } + dx6 = sx[6] - ( S5*sx[5] ); + dy6 = sy[6] - ( S5*sy[5] ); + ox5 = ox6 + ( j5*sx[5] ); + oy5 = oy6 + ( j5*sy[5] ); + for ( j4 = sh[4]; j4 > 0; ) { + if ( j4 < bsize ) { + S4 = j4; + j4 = 0; + } else { + S4 = bsize; + j4 -= bsize; + } + dx5 = sx[5] - ( S4*sx[4] ); + dy5 = sy[5] - ( S4*sy[4] ); + ox4 = ox5 + ( j4*sx[4] ); + oy4 = oy5 + ( j4*sy[4] ); + for ( j3 = sh[3]; j3 > 0; ) { + if ( j3 < bsize ) { + S3 = j3; + j3 = 0; + } else { + S3 = bsize; + j3 -= bsize; + } + dx4 = sx[4] - ( S3*sx[3] ); + dy4 = sy[4] - ( S3*sy[3] ); + ox3 = ox4 + ( j3*sx[3] ); + oy3 = oy4 + ( j3*sy[3] ); + for ( j2 = sh[2]; j2 > 0; ) { + if ( j2 < bsize ) { + S2 = j2; + j2 = 0; + } else { + S2 = bsize; + j2 -= bsize; + } + dx3 = sx[3] - ( S2*sx[2] ); + dy3 = sy[3] - ( S2*sy[2] ); + ox2 = ox3 + ( j2*sx[2] ); + oy2 = oy3 + ( j2*sy[2] ); + for ( j1 = sh[1]; j1 > 0; ) { + if ( j1 < bsize ) { + S1 = j1; + j1 = 0; + } else { + S1 = bsize; + j1 -= bsize; + } + dx2 = sx[2] - ( S1*sx[1] ); + dy2 = sy[2] - ( S1*sy[1] ); + ox1 = ox2 + ( j1*sx[1] ); + oy1 = oy2 + ( j1*sy[1] ); + for ( j0 = sh[0]; j0 > 0; ) { + if ( j0 < bsize ) { + S0 = j0; + j0 = 0; + } else { + S0 = bsize; + j0 -= bsize; + } + // Compute index offsets for the first input and output ndarray elements in the current block... + ix = ox1 + ( j0*sx[0] ); + iy = oy1 + ( j0*sy[0] ); + + // Compute loop offset increments... + dx1 = sx[1] - ( S0*sx[0] ); + dy1 = sy[1] - ( S0*sy[0] ); + + // Iterate over the ndarray dimensions... + for ( i8 = 0; i8 < S8; i8++ ) { + for ( i7 = 0; i7 < S7; i7++ ) { + for ( i6 = 0; i6 < S6; i6++ ) { + for ( i5 = 0; i5 < S5; i5++ ) { + for ( i4 = 0; i4 < S4; i4++ ) { + for ( i3 = 0; i3 < S3; i3++ ) { + for ( i2 = 0; i2 < S2; i2++ ) { + for ( i1 = 0; i1 < S1; i1++ ) { + for ( i0 = 0; i0 < S0; i0++ ) { + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), take( [ i8, i7, i6, i5, i4, i3, i2, i1, i0 ], idx ), x.ref ) ); + ix += dx0; + iy += dy0; + } + ix += dx1; + iy += dy1; + } + ix += dx2; + iy += dy2; + } + ix += dx3; + iy += dy3; + } + ix += dx4; + iy += dy4; + } + ix += dx5; + iy += dy5; + } + ix += dx6; + iy += dy6; + } + ix += dx7; + iy += dy7; + } + ix += dx8; + iy += dy8; + } + } + } + } + } + } + } + } + } + } +} + + +// EXPORTS // + +module.exports = blockedmap9d; diff --git a/base/map/lib/index.js b/base/map/lib/index.js new file mode 100644 index 00000000..c1368019 --- /dev/null +++ b/base/map/lib/index.js @@ -0,0 +1,81 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2024 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Apply a callback function to the elements in an input ndarray and assign results to the elements in an output ndarray. +* +* @module @stdlib/ndarray/base/map +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* var map = require( '@stdlib/ndarray/base/map' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map( [ x, y ], scale ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/base/map/lib/main.js b/base/map/lib/main.js new file mode 100644 index 00000000..c85de172 --- /dev/null +++ b/base/map/lib/main.js @@ -0,0 +1,342 @@ +/** +* @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 iterationOrder = require( './../../../base/iteration-order' ); +var minmaxViewBufferIndex = require( './../../../base/minmax-view-buffer-index' ); +var ndarray2object = require( './../../../base/ndarraylike2object' ); +var blockedaccessormap2d = require( './2d_blocked_accessors.js' ); +var blockedaccessormap3d = require( './3d_blocked_accessors.js' ); +var blockedaccessormap4d = require( './4d_blocked_accessors.js' ); +var blockedaccessormap5d = require( './5d_blocked_accessors.js' ); +var blockedaccessormap6d = require( './6d_blocked_accessors.js' ); +var blockedaccessormap7d = require( './7d_blocked_accessors.js' ); +var blockedaccessormap8d = require( './8d_blocked_accessors.js' ); +var blockedaccessormap9d = require( './9d_blocked_accessors.js' ); +var blockedaccessormap10d = require( './10d_blocked_accessors.js' ); +var blockedmap2d = require( './2d_blocked.js' ); +var blockedmap3d = require( './3d_blocked.js' ); +var blockedmap4d = require( './4d_blocked.js' ); +var blockedmap5d = require( './5d_blocked.js' ); +var blockedmap6d = require( './6d_blocked.js' ); +var blockedmap7d = require( './7d_blocked.js' ); +var blockedmap8d = require( './8d_blocked.js' ); +var blockedmap9d = require( './9d_blocked.js' ); +var blockedmap10d = require( './10d_blocked.js' ); +var accessormap0d = require( './0d_accessors.js' ); +var accessormap1d = require( './1d_accessors.js' ); +var accessormap2d = require( './2d_accessors.js' ); +var accessormap3d = require( './3d_accessors.js' ); +var accessormap4d = require( './4d_accessors.js' ); +var accessormap5d = require( './5d_accessors.js' ); +var accessormap6d = require( './6d_accessors.js' ); +var accessormap7d = require( './7d_accessors.js' ); +var accessormap8d = require( './8d_accessors.js' ); +var accessormap9d = require( './9d_accessors.js' ); +var accessormap10d = require( './10d_accessors.js' ); +var accessormapnd = require( './nd_accessors.js' ); +var map0d = require( './0d.js' ); +var map1d = require( './1d.js' ); +var map2d = require( './2d.js' ); +var map3d = require( './3d.js' ); +var map4d = require( './4d.js' ); +var map5d = require( './5d.js' ); +var map6d = require( './6d.js' ); +var map7d = require( './7d.js' ); +var map8d = require( './8d.js' ); +var map9d = require( './9d.js' ); +var map10d = require( './10d.js' ); +var mapnd = require( './nd.js' ); + + +// VARIABLES // + +var MAP = [ + map0d, + map1d, + map2d, + map3d, + map4d, + map5d, + map6d, + map7d, + map8d, + map9d, + map10d +]; +var ACCESSOR_MAP = [ + accessormap0d, + accessormap1d, + accessormap2d, + accessormap3d, + accessormap4d, + accessormap5d, + accessormap6d, + accessormap7d, + accessormap8d, + accessormap9d, + accessormap10d +]; +var BLOCKED_MAP = [ + blockedmap2d, // 0 + blockedmap3d, + blockedmap4d, + blockedmap5d, + blockedmap6d, + blockedmap7d, + blockedmap8d, + blockedmap9d, + blockedmap10d // 8 +]; +var BLOCKED_ACCESSOR_MAP = [ + blockedaccessormap2d, // 0 + blockedaccessormap3d, + blockedaccessormap4d, + blockedaccessormap5d, + blockedaccessormap6d, + blockedaccessormap7d, + blockedaccessormap8d, + blockedaccessormap9d, + blockedaccessormap10d // 8 +]; +var MAX_DIMS = MAP.length -1; + + +// MAIN // + +/** +* Applies a callback function to the elements in an input ndarray and assigns results to the elements in an output ndarray. +* +* ## Notes +* +* - Each provided ndarray should be an `object` with the following properties: +* +* - **dtype**: data type. +* - **data**: data buffer. +* - **shape**: dimensions. +* - **strides**: stride lengths. +* - **offset**: index offset. +* - **order**: specifies whether an ndarray is row-major (C-style) or column major (Fortran-style). +* +* @param {ArrayLikeObject} arrays - array-like object containing one input array and one output array +* @param {Callback} fcn - callback function +* @param {*} [thisArg] - callback execution context +* @throws {Error} arrays must have the same number of dimensions +* @throws {Error} arrays must have the same shape +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( z ) { +* return z * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] ); +* var ybuf = new Float64Array( 6 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 3, 1, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 4, 1 ]; +* var sy = [ 2, 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* map( [ x, y ], scale ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0, 100.0, 110.0 ] +*/ +function map( arrays, fcn, thisArg ) { + var ndims; + var xmmv; + var ymmv; + var shx; + var shy; + var iox; + var ioy; + var len; + var sx; + var sy; + var ox; + var oy; + var ns; + var x; + var y; + var i; + var d; + + // Unpack the ndarrays and standardize ndarray meta data: + x = ndarray2object( arrays[ 0 ] ); + y = ndarray2object( arrays[ 1 ] ); + + // Verify that the input and output arrays have the same number of dimensions... + shx = x.shape; + shy = y.shape; + ndims = shx.length; + if ( ndims !== shy.length ) { + throw new Error( 'invalid arguments. Arrays must have the same number of dimensions (i.e., same rank). ndims(x) == '+ndims+'. ndims(y) == '+shy.length+'.' ); + } + // Determine whether we can avoid iteration altogether... + if ( ndims === 0 ) { + if ( x.accessorProtocol || y.accessorProtocol ) { + return ACCESSOR_MAP[ ndims ]( x, y, fcn, thisArg ); + } + return MAP[ ndims ]( x, y, fcn, thisArg ); + } + // Verify that the input and output arrays have the same dimensions... + len = 1; // number of elements + ns = 0; // number of singleton dimensions + for ( i = 0; i < ndims; i++ ) { + d = shx[ i ]; + if ( d !== shy[ i ] ) { + throw new Error( 'invalid arguments. Array must have the same shape.' ); + } + // Note that, if one of the dimensions is `0`, the length will be `0`... + len *= d; + + // Check whether the current dimension is a singleton dimension... + if ( d === 1 ) { + ns += 1; + } + } + // Check whether we were provided empty ndarrays... + if ( len === 0 ) { + return; + } + // Determine whether the ndarrays are one-dimensional and thus readily translate to one-dimensional strided arrays... + if ( ndims === 1 ) { + if ( x.accessorProtocol || y.accessorProtocol ) { + return ACCESSOR_MAP[ ndims ]( x, y, fcn, thisArg ); + } + return MAP[ ndims ]( x, y, fcn, thisArg ); + } + + sx = x.strides; + sy = y.strides; + + // Determine whether the ndarray has only **one** non-singleton dimension (e.g., ndims=4, shape=[10,1,1,1]) so that we can treat the ndarrays as being equivalent to one-dimensional strided arrays... + if ( ns === ndims-1 ) { + // Get the index of the non-singleton dimension... + for ( i = 0; i < ndims; i++ ) { + if ( shx[ i ] !== 1 ) { + break; + } + } + x.shape = [ shx[i] ]; + y.shape = x.shape; + x.strides = [ sx[i] ]; + y.strides = [ sy[i] ]; + if ( x.accessorProtocol || y.accessorProtocol ) { + return ACCESSOR_MAP[ 1 ]( x, y, fcn, thisArg ); + } + return MAP[ 1 ]( x, y, fcn, thisArg ); + } + + iox = iterationOrder( sx ); // +/-1 + ioy = iterationOrder( sy ); // +/-1 + + // Determine whether we can avoid blocked iteration... + if ( iox !== 0 && ioy !== 0 && iox === ioy ) { + // Determine the minimum and maximum linear indices which are accessible by the array views: + xmmv = minmaxViewBufferIndex( shx, sx, x.offset ); + ymmv = minmaxViewBufferIndex( shy, sy, y.offset ); + + // Determine whether we can ignore shape (and strides) and treat the ndarrays as linear one-dimensional strided arrays... + if ( len === ( xmmv[1]-xmmv[0]+1 ) && len === ( ymmv[1]-ymmv[0]+1 ) ) { + // Note: the above is equivalent to @stdlib/ndarray/base/assert/is-contiguous, but in-lined so we can retain computed values... + if ( iox === 1 ) { + ox = xmmv[ 0 ]; + } else { + ox = xmmv[ 1 ]; + } + if ( ioy === 1 ) { + oy = ymmv[ 0 ]; + } else { + oy = ymmv[ 1 ]; + } + x.shape = [ len ]; + y.shape = x.shape; + x.strides = [ iox ]; + y.strides = [ ioy ]; + x.offset = ox; + y.offset = oy; + if ( x.accessorProtocol || y.accessorProtocol ) { + return ACCESSOR_MAP[ 1 ]( x, y, fcn, thisArg ); + } + return MAP[ 1 ]( x, y, fcn, thisArg ); + } + // At least one ndarray is non-contiguous, so we cannot directly use one-dimensional array functionality... + + // Determine whether we can use simple nested loops... + if ( ndims <= MAX_DIMS ) { + // So long as iteration for each respective array always moves in the same direction (i.e., no mixed sign strides), we can leverage cache-optimal (i.e., normal) nested loops without resorting to blocked iteration... + if ( x.accessorProtocol || y.accessorProtocol ) { + return ACCESSOR_MAP[ ndims ]( x, y, fcn, thisArg ); + } + return MAP[ ndims ]( x, y, fcn, thisArg ); + } + // Fall-through to blocked iteration... + } + // At this point, we're either dealing with non-contiguous n-dimensional arrays, high dimensional n-dimensional arrays, and/or arrays having differing memory layouts, so our only hope is that we can still perform blocked iteration... + + // Determine whether we can perform blocked iteration... + if ( ndims <= MAX_DIMS ) { + if ( x.accessorProtocol || y.accessorProtocol ) { + return BLOCKED_ACCESSOR_MAP[ ndims-2 ]( x, y, fcn, thisArg ); + } + return BLOCKED_MAP[ ndims-2 ]( x, y, fcn, thisArg ); + } + // Fall-through to linear view iteration without regard for how data is stored in memory (i.e., take the slow path)... + if ( x.accessorProtocol || y.accessorProtocol ) { + return accessormapnd( x, y, fcn, thisArg ); + } + mapnd( x, y, fcn, thisArg ); +} + + +// EXPORTS // + +module.exports = map; diff --git a/base/map/lib/nd.js b/base/map/lib/nd.js new file mode 100644 index 00000000..30cef7c3 --- /dev/null +++ b/base/map/lib/nd.js @@ -0,0 +1,154 @@ +/** +* @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 numel = require( './../../../base/numel' ); +var vind2bind = require( './../../../base/vind2bind' ); +var ind2sub = require( './../../../base/ind2sub' ); + + +// VARIABLES // + +var MODE = 'throw'; + + +// MAIN // + +/** +* Applies a callback function to elements in an n-dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Float64Array = require( '@stdlib/array/float64' ); +* +* function scale( x ) { +* return x * 10.0; +* } +* +* // Create data buffers: +* var xbuf = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Float64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 4, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 1; +* var oy = 0; +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'float64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major' +* }; +* var y = { +* 'dtype': 'float64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major' +* }; +* +* // Apply the map function: +* mapnd( x, y, scale, {} ); +* +* console.log( y.data ); +* // => [ 20.0, 30.0, 60.0, 70.0 ] +*/ +function mapnd( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var ordx; + var ordy; + var len; + var idx; + var sh; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i; + + sh = x.shape; + + // Compute the total number of elements over which to iterate: + len = numel( sh ); + + // Cache references to the input and output ndarray data buffers: + xbuf = x.data; + ybuf = y.data; + + // Cache references to the respective stride arrays: + sx = x.strides; + sy = y.strides; + + // Cache the indices of the first indexed elements in the respective ndarrays: + ox = x.offset; + oy = y.offset; + + // Cache the respective array orders: + ordx = x.order; + ordy = y.order; + + // Iterate over each element based on the linear **view** index, regardless as to how the data is stored in memory... + for ( i = 0; i < len; i++ ) { + ix = vind2bind( sh, sx, ox, ordx, i, MODE ); + iy = vind2bind( sh, sy, oy, ordy, i, MODE ); + idx = ind2sub( sh, sx, 0, ordx, i, MODE ); // return subscripts from the perspective of the ndarray view + ybuf[ iy ] = fcn.call( thisArg, xbuf[ ix ], idx, x.ref ); + } +} + + +// EXPORTS // + +module.exports = mapnd; diff --git a/base/map/lib/nd_accessors.js b/base/map/lib/nd_accessors.js new file mode 100644 index 00000000..d0765458 --- /dev/null +++ b/base/map/lib/nd_accessors.js @@ -0,0 +1,179 @@ +/** +* @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 numel = require( './../../../base/numel' ); +var vind2bind = require( './../../../base/vind2bind' ); +var ind2sub = require( './../../../base/ind2sub' ); + + +// VARIABLES // + +var MODE = 'throw'; + + +// MAIN // + +/** +* Applies a callback function to elements in an -dimensional input ndarray and assigns results to elements in an equivalently shaped output ndarray. +* +* @private +* @param {Object} x - object containing ndarray meta data +* @param {ndarrayLike} x.ref - reference to the original ndarray-like object +* @param {string} x.dtype - data type +* @param {Collection} x.data - data buffer +* @param {NonNegativeIntegerArray} x.shape - dimensions +* @param {IntegerArray} x.strides - stride lengths +* @param {NonNegativeInteger} x.offset - index offset +* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style) +* @param {Object} y - object containing output ndarray meta data +* @param {string} y.dtype - data type +* @param {Collection} y.data - data buffer +* @param {NonNegativeIntegerArray} y.shape - dimensions +* @param {IntegerArray} y.strides - stride lengths +* @param {NonNegativeInteger} y.offset - index offset +* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style) +* @param {Callback} fcn - callback function +* @param {*} thisArg - callback execution context +* @returns {void} +* +* @example +* var Complex64Array = require( '@stdlib/array/complex64' ); +* var Complex64 = require( '@stdlib/complex/float32/ctor' ); +* var realf = require( '@stdlib/complex/float32/real' ); +* var imagf = require( '@stdlib/complex/float32/imag' ); +* +* function scale( z ) { +* return new Complex64( realf(z)*10.0, imagf(z)*10.0 ); +* } +* +* // Create data buffers: +* var xbuf = new Complex64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] ); +* var ybuf = new Complex64Array( 4 ); +* +* // Define the shape of the input and output arrays: +* var shape = [ 2, 2 ]; +* +* // Define the array strides: +* var sx = [ 2, 1 ]; +* var sy = [ 2, 1 ]; +* +* // Define the index offsets: +* var ox = 0; +* var oy = 0; +* +* // Define getters and setters: +* function getter( buf, idx ) { +* return buf.get( idx ); +* } +* +* function setter( buf, idx, value ) { +* buf.set( value, idx ); +* } +* +* // Create the input and output ndarray-like objects: +* var x = { +* 'ref': null, +* 'dtype': 'complex64', +* 'data': xbuf, +* 'shape': shape, +* 'strides': sx, +* 'offset': ox, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* var y = { +* 'dtype': 'complex64', +* 'data': ybuf, +* 'shape': shape, +* 'strides': sy, +* 'offset': oy, +* 'order': 'row-major', +* 'accessors': [ getter, setter ] +* }; +* +* // Apply the map function: +* mapnd( x, y, scale, {} ); +* +* var v = y.data.get( 0 ); +* +* var re = realf( v ); +* // returns 10.0 +* +* var im = imagf( v ); +* // returns 20.0 +*/ +function mapnd( x, y, fcn, thisArg ) { + var xbuf; + var ybuf; + var ordx; + var ordy; + var len; + var get; + var set; + var idx; + var sh; + var sx; + var sy; + var ox; + var oy; + var ix; + var iy; + var i; + + sh = x.shape; + + // Compute the total number of elements over which to iterate: + len = numel( sh ); + + // Cache references to the input and output ndarray data buffers: + xbuf = x.data; + ybuf = y.data; + + // Cache references to the respective stride arrays: + sx = x.strides; + sy = y.strides; + + // Cache the indices of the first indexed elements in the respective ndarrays: + ox = x.offset; + oy = y.offset; + + // Cache the respective array orders: + ordx = x.order; + ordy = y.order; + + // Cache accessors: + get = x.accessors[ 0 ]; + set = y.accessors[ 1 ]; + + // Iterate over each element based on the linear **view** index, regardless as to how the data is stored in memory... + for ( i = 0; i < len; i++ ) { + ix = vind2bind( sh, sx, ox, ordx, i, MODE ); + iy = vind2bind( sh, sy, oy, ordy, i, MODE ); + idx = ind2sub( sh, sx, 0, ordx, i, MODE ); // return subscripts from the perspective of the ndarray view + set( ybuf, iy, fcn.call( thisArg, get( xbuf, ix ), idx, x.ref ) ); + } +} + + +// EXPORTS // + +module.exports = mapnd; diff --git a/base/map/package.json b/base/map/package.json new file mode 100644 index 00000000..14c43db2 --- /dev/null +++ b/base/map/package.json @@ -0,0 +1,65 @@ +{ + "name": "@stdlib/ndarray/base/map", + "version": "0.0.0", + "description": "Apply a callback to elements in an input ndarray and assign results to elements in an output ndarray.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "lib": "./lib", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "base", + "strided", + "array", + "ndarray", + "map", + "apply", + "unary", + "foreach", + "transform", + "for-each" + ], + "__stdlib__": {} +} diff --git a/base/map/test/test.js b/base/map/test/test.js new file mode 100644 index 00000000..bf08d19a --- /dev/null +++ b/base/map/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 map = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof map, 'function', 'main export is a function' ); + t.end(); +}); + +// FIXME: add tests