From a406a5527f3363ffeb6bbe57344abe41244f04eb Mon Sep 17 00:00:00 2001 From: headlessNode Date: Fri, 17 Apr 2026 12:59:32 +0500 Subject: [PATCH 1/4] feat: add ndarray/base/tile --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: passed - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- .../@stdlib/ndarray/base/tile/README.md | 125 +++ .../ndarray/base/tile/benchmark/benchmark.js | 115 +++ .../base/tile/benchmark/benchmark.ndims.js | 106 +++ .../@stdlib/ndarray/base/tile/docs/repl.txt | 40 + .../ndarray/base/tile/docs/types/index.d.ts | 53 ++ .../ndarray/base/tile/docs/types/test.ts | 94 +++ .../ndarray/base/tile/examples/index.js | 31 + .../@stdlib/ndarray/base/tile/lib/index.js | 44 ++ .../@stdlib/ndarray/base/tile/lib/main.js | 146 ++++ .../@stdlib/ndarray/base/tile/package.json | 68 ++ .../@stdlib/ndarray/base/tile/test/test.js | 746 ++++++++++++++++++ 11 files changed, 1568 insertions(+) create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/README.md create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.ndims.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/examples/index.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/lib/index.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/package.json create mode 100644 lib/node_modules/@stdlib/ndarray/base/tile/test/test.js diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/README.md b/lib/node_modules/@stdlib/ndarray/base/tile/README.md new file mode 100644 index 000000000000..417b3f9595d0 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/README.md @@ -0,0 +1,125 @@ + + +# tile + +> Return an [ndarray][@stdlib/ndarray/base/ctor] created by repeating the elements of an input [ndarray][@stdlib/ndarray/base/ctor] a specified number of times along each dimension. + + + +
+ +
+ + + + + +
+ +## Usage + +```javascript +var tile = require( '@stdlib/ndarray/base/tile' ); +``` + +#### tile( x, reps ) + +Returns an [ndarray][@stdlib/ndarray/base/ctor] created by repeating the elements of an input [ndarray][@stdlib/ndarray/base/ctor] a specified number of times along each dimension. + +```javascript +var array = require( '@stdlib/ndarray/array' ); + +var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +// returns [ [ 1, 2 ], [ 3, 4 ] ] + +var y = tile( x, [ 2, 2 ] ); +// returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] +``` + +
+ + + + + +
+ +## Notes + +- When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input [ndarray][@stdlib/ndarray/base/ctor] is treated as if singleton dimensions were prepended. +- The output [ndarray][@stdlib/ndarray/base/ctor] has rank equal to the greater of the input array rank and the number of repetitions. +- The function always returns a new [ndarray][@stdlib/ndarray/base/ctor] having a newly allocated data buffer. + +
+ + + + + +
+ +## Examples + + + +```javascript +var array = require( '@stdlib/ndarray/array' ); +var ndarray2array = require( '@stdlib/ndarray/to-array' ); +var tile = require( '@stdlib/ndarray/base/tile' ); + +// Create a 2x2 array: +var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +console.log( ndarray2array( x ) ); + +// Tile the array to 4x4: +var out = tile( x, [ 2, 2 ] ); +console.log( ndarray2array( out ) ); +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.js b/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.js new file mode 100644 index 000000000000..a0f87fc4c461 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.js @@ -0,0 +1,115 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var Float64Array = require( '@stdlib/array/float64' ); +var ndarrayBase = require( '@stdlib/ndarray/base/ctor' ); +var ndarray = require( '@stdlib/ndarray/ctor' ); +var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); +var format = require( '@stdlib/string/format' ); +var pkg = require( './../package.json' ).name; +var tile = require( './../lib' ); + + +// MAIN // + +bench( format( '%s::ctor=base,ndims=2,order=row-major', pkg ), function benchmark( b ) { + var strides; + var values; + var buffer; + var offset; + var dtype; + var shape; + var order; + var out; + var i; + + dtype = 'float64'; + buffer = new Float64Array( 4 ); + shape = [ 2, 2 ]; + strides = [ 2, 1 ]; + offset = 0; + order = 'row-major'; + + values = [ + ndarrayBase( dtype, buffer, shape, strides, offset, order ), + ndarrayBase( dtype, buffer, shape, strides, offset, order ), + ndarrayBase( dtype, buffer, shape, strides, offset, order ), + ndarrayBase( dtype, buffer, shape, strides, offset, order ), + ndarrayBase( dtype, buffer, shape, strides, offset, order ) + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = tile( values[ i%values.length ], [ 2, 2 ] ); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isndarrayLike( out ) ) { + b.fail( 'should return an ndarray' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( format( '%s::ctor=non-base,ndims=2,order=row-major', pkg ), function benchmark( b ) { + var strides; + var values; + var buffer; + var offset; + var dtype; + var shape; + var order; + var out; + var i; + + dtype = 'float64'; + buffer = new Float64Array( 4 ); + shape = [ 2, 2 ]; + strides = [ 2, 1 ]; + offset = 0; + order = 'row-major'; + + values = [ + ndarray( dtype, buffer, shape, strides, offset, order ), + ndarray( dtype, buffer, shape, strides, offset, order ), + ndarray( dtype, buffer, shape, strides, offset, order ), + ndarray( dtype, buffer, shape, strides, offset, order ), + ndarray( dtype, buffer, shape, strides, offset, order ) + ]; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = tile( values[ i%values.length ], [ 2, 2 ] ); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isndarrayLike( out ) ) { + b.fail( 'should return an ndarray' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.ndims.js b/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.ndims.js new file mode 100644 index 000000000000..6de7285b034e --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/benchmark/benchmark.ndims.js @@ -0,0 +1,106 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 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 array = require( '@stdlib/ndarray/array' ); +var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); +var format = require( '@stdlib/string/format' ); +var pkg = require( './../package.json' ).name; +var tile = require( './../lib' ); + + +// FUNCTIONS // + +/** +* Creates a benchmark function. +* +* @private +* @param {PositiveInteger} ndims - number of output dimensions +* @returns {Function} benchmark function +*/ +function createBenchmark( ndims ) { + var reps; + var x; + var i; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + + reps = []; + for ( i = 0; i < ndims; i++ ) { + reps.push( 1 ); + } + reps[ ndims-1 ] = 2; + if ( ndims >= 2 ) { + reps[ ndims-2 ] = 2; + } + return benchmark; + + /** + * Benchmark function. + * + * @private + * @param {Benchmark} b - benchmark instance + */ + function benchmark( b ) { + var out; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = tile( x, reps ); + if ( typeof out !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isndarrayLike( out ) ) { + b.fail( 'should return an ndarray' ); + } + b.pass( 'benchmark finished' ); + b.end(); + } +} + + +// MAIN // + +/** +* Main execution sequence. +* +* @private +*/ +function main() { + var min; + var max; + var f; + var i; + + min = 2; + max = 10; + + for ( i = min; i <= max; i++ ) { + f = createBenchmark( i ); + bench( format( '%s::ctor=non-base,ndims=%d,order=row-major', pkg, i ), f ); + } +} + +main(); diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt b/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt new file mode 100644 index 000000000000..e77bfc0a74a5 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt @@ -0,0 +1,40 @@ + +{{alias}}( x, reps ) + Returns an ndarray created by repeating the elements of an input ndarray + a specified number of times along each dimension. + + When the number of repetitions is less than the number of input dimensions, + the number of repetitions is left-padded with ones until the number of + repetitions matches the number of input dimensions. When the number of + repetitions exceeds the number of input dimensions, the input array is + treated as if singleton dimensions were prepended. + + The output array has rank equal to the greater of the input array rank and + the number of repetitions. + + The function always returns a new ndarray having a newly allocated data + buffer. + + Parameters + ---------- + x: ndarray + Input array. + + reps: ArrayLikeObject + Number of repetitions along each dimension. + + Returns + ------- + out: ndarray + Output array. + + Examples + -------- + > var x = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2 ], [ 3, 4 ] ] ) + [ [ 1, 2 ], [ 3, 4 ] ] + > var o = {{alias}}( x, [ 2, 2 ] ) + [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts new file mode 100644 index 000000000000..aaa773aa0656 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts @@ -0,0 +1,53 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 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 { ndarray } from '@stdlib/types/ndarray'; + +/** +* Returns an ndarray created by repeating the elements of an input ndarray a specified number of times along each dimension. +* +* ## Notes +* +* - When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. +* - The output array has rank equal to the greater of the input array rank and the number of repetitions. +* - The function always returns a new ndarray having a newly allocated data buffer. +* +* @param x - input array +* @param reps - number of repetitions along each dimension +* @returns output array +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +* // returns [ [ 1, 2 ], [ 3, 4 ] ] +* +* var y = tile( x, [ 2, 2 ] ); +* // returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] +*/ +declare function tile( x: ndarray, reps: ArrayLike ): ndarray; + + +// EXPORTS // + +export = tile; diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts new file mode 100644 index 000000000000..da7c01d3ce55 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts @@ -0,0 +1,94 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 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 tile = require( './index' ); + +/** +* Mock function to create an ndarray-like object. +* +* @returns 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; +} + + +// TESTS // + +// The function returns an ndarray... +{ + const x = array(); + + tile( x, [ 2, 2, 2 ] ); // $ExpectType ndarray +} + +// The compiler throws an error if the function is not provided a first argument which is an ndarray... +{ + tile( '5', [ 2, 2, 2 ] ); // $ExpectError + tile( 5, [ 2, 2, 2 ] ); // $ExpectError + tile( true, [ 2, 2, 2 ] ); // $ExpectError + tile( false, [ 2, 2, 2 ] ); // $ExpectError + tile( null, [ 2, 2, 2 ] ); // $ExpectError + tile( {}, [ 2, 2, 2 ] ); // $ExpectError + tile( [ '5' ], [ 2, 2, 2 ] ); // $ExpectError + tile( ( x: number ): number => x, [ 2, 2, 2 ] ); // $ExpectError +} + +// The compiler throws an error if the function is not provided a second argument which is an array-like object containing numbers... +{ + const x = array(); + + tile( x, '5' ); // $ExpectError + tile( x, 5 ); // $ExpectError + tile( x, true ); // $ExpectError + tile( x, false ); // $ExpectError + tile( x, null ); // $ExpectError + tile( x, {} ); // $ExpectError + tile( x, [ '5' ] ); // $ExpectError + tile( x, ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + const x = array(); + + tile(); // $ExpectError + tile( x ); // $ExpectError + tile( x, [ 1, 2, 3 ], [ 2, 3 ] ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/examples/index.js b/lib/node_modules/@stdlib/ndarray/base/tile/examples/index.js new file mode 100644 index 000000000000..20363b4dceeb --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/examples/index.js @@ -0,0 +1,31 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 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 array = require( '@stdlib/ndarray/array' ); +var ndarray2array = require( '@stdlib/ndarray/to-array' ); +var tile = require( './../lib' ); + +// Create a 2x2 array: +var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +console.log( ndarray2array( x ) ); + +// Tile the array to 4x4: +var out = tile( x, [ 2, 2 ] ); +console.log( ndarray2array( out ) ); diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/lib/index.js b/lib/node_modules/@stdlib/ndarray/base/tile/lib/index.js new file mode 100644 index 000000000000..c8e214297abd --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/lib/index.js @@ -0,0 +1,44 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Return an ndarray created by repeating the elements of an input ndarray a specified number of times along each dimension. +* +* @module @stdlib/ndarray/base/tile +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* var tile = require( '@stdlib/ndarray/base/tile' ); +* +* var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +* // returns [ [ 1, 2 ], [ 3, 4 ] ] +* +* var y = tile( x, [ 2, 2 ] ); +* // returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js new file mode 100644 index 000000000000..46eaae131313 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js @@ -0,0 +1,146 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 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 ndarray = require( '@stdlib/ndarray/base/ctor' ); +var assign = require( '@stdlib/ndarray/base/assign' ); +var buffer = require( '@stdlib/ndarray/base/buffer' ); +var numel = require( '@stdlib/ndarray/base/numel' ); +var shape2strides = require( '@stdlib/ndarray/base/shape2strides' ); +var strides2order = require( '@stdlib/ndarray/base/strides2order' ); +var getShape = require( '@stdlib/ndarray/base/shape' ); +var getStrides = require( '@stdlib/ndarray/base/strides' ); +var getOffset = require( '@stdlib/ndarray/base/offset' ); +var getOrder = require( '@stdlib/ndarray/base/order' ); +var getDType = require( '@stdlib/ndarray/base/dtype' ); +var getData = require( '@stdlib/ndarray/base/data-buffer' ); +var zeros = require( '@stdlib/array/base/zeros' ); + + +// MAIN // + +/** +* Returns an ndarray created by repeating the elements of an input ndarray a specified number of times along each dimension. +* +* ## Notes +* +* - When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. +* - The output array has rank equal to the greater of the input array rank and the number of repetitions. +* - The function always returns a new ndarray having a newly allocated data buffer. +* +* @param {ndarray} x - input array +* @param {NonNegativeIntegerArray} reps - number of repetitions along each dimension +* @returns {ndarray} output array +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +* // returns [ [ 1, 2 ], [ 3, 4 ] ] +* +* var y = tile( x, [ 2, 2 ] ); +* // returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] +*/ +function tile( x, reps ) { + var dtype; + var order; + var shx; + var sho; + var shi; + var sto; + var ord; + var buf; + var out; + var Dr; + var Ds; + var si; + var sx; + var v1; + var v2; + var K; + var L; + var M; + var N; + var r; + var s; + var t; + var i; + + shx = getShape( x, false ); + sx = getStrides( x, false ); + dtype = getDType( x ); + N = reps.length; + M = shx.length; + + // Determine the output rank, which is the greater of the number of input dimensions and the number of repetitions. Compute the implicit left-padding amounts for the repetitions and input shape, respectively... + K = ( N > M ) ? N : M; + Dr = K - N; + Ds = K - M; + + // Infer the storage order from the input strides, falling back to the stated order when the input is non-contiguous... + ord = strides2order( sx ); + if ( ord === 2 ) { + order = 'column-major'; + } else if ( ord === 1 || ord === 3 ) { + order = 'row-major'; + } else { + order = getOrder( x ); + } + // Compute an interleaved 2K-D shape and strides for broadcasting the input, along with the final K-D output shape. By inserting a repetition axis next to each original axis, a contiguous 2K-D buffer can be reinterpreted as the K-D tiled output without an additional copy... + shi = zeros( 2*K ); + si = zeros( 2*K ); + sho = zeros( K ); + for ( i = 0; i < K; i++ ) { + r = ( i < Dr ) ? 1 : reps[ i - Dr ]; + s = ( i < Ds ) ? 1 : shx[ i - Ds ]; + t = ( i < Ds ) ? 0 : sx[ i - Ds ]; + sho[ i ] = r * s; + if ( order === 'row-major' ) { + shi[ 2*i ] = r; + shi[ (2*i)+1 ] = s; + si[ (2*i)+1 ] = t; + } else { + shi[ 2*i ] = s; + shi[ (2*i)+1 ] = r; + si[ 2*i ] = t; + } + } + if ( K > 0 ) { + L = numel( sho ); + sto = shape2strides( sho, order ); + } else { + L = 1; + sto = [ 0 ]; + } + buf = buffer( dtype, L ); + out = new x.constructor( dtype, buf, sho, sto, 0, order ); + + // Assign the broadcasted input to a 2K-D view over the output data buffer... + v1 = ndarray( dtype, getData( x ), shi, si, getOffset( x ), order ); + v2 = ndarray( dtype, buf, shi, shape2strides( shi, order ), 0, order ); + assign( [ v1, v2 ] ); + return out; +} + + +// EXPORTS // + +module.exports = tile; diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/package.json b/lib/node_modules/@stdlib/ndarray/base/tile/package.json new file mode 100644 index 000000000000..1453d1870b67 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/package.json @@ -0,0 +1,68 @@ +{ + "name": "@stdlib/ndarray/base/tile", + "version": "0.0.0", + "description": "Construct a new ndarray by repeating the elements of an input ndarray a specified number of times along each dimension.", + "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", + "stdtypes", + "types", + "base", + "ndarray", + "tile", + "repeat", + "repmat", + "multidimensional", + "array", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js b/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js new file mode 100644 index 000000000000..dd5bb73c387c --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js @@ -0,0 +1,746 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 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 array = require( '@stdlib/ndarray/array' ); +var ndarray = require( '@stdlib/ndarray/ctor' ); +var base = require( '@stdlib/ndarray/base/ctor' ); +var instanceOf = require( '@stdlib/assert/instance-of' ); +var ndarray2array = require( '@stdlib/ndarray/to-array' ); +var getShape = require( '@stdlib/ndarray/shape' ); +var getData = require( '@stdlib/ndarray/data-buffer' ); +var numel = require( '@stdlib/ndarray/base/numel' ); +var tile = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof tile, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function tiles an input array (row-major, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4 ], [ 2, 2 ], [ 2, 1 ], 0, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (row-major, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (column-major, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 3, 2, 4 ], [ 2, 2 ], [ 1, 2 ], 0, 'column-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (column-major, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ], { + 'order': 'column-major' + }); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (negative strides, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4 ], [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 4, 3, 4, 3 ], + [ 2, 1, 2, 1 ], + [ 4, 3, 4, 3 ], + [ 2, 1, 2, 1 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (negative strides, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = ndarray( 'generic', [ 1, 2, 3, 4 ], [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 4, 3, 4, 3 ], + [ 2, 1, 2, 1 ], + [ 4, 3, 4, 3 ], + [ 2, 1, 2, 1 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (non-contiguous, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 2, 4, 2, 4 ], + [ 6, 8, 6, 8 ], + [ 2, 4, 2, 4 ], + [ 6, 8, 6, 8 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array (non-contiguous, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = ndarray( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ 2, 4, 2, 4 ], + [ 6, 8, 6, 8 ], + [ 2, 4, 2, 4 ], + [ 6, 8, 6, 8 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function prepends singleton dimensions when the number of repetitions exceeds the number of input dimensions (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4 ], [ 2, 2 ], [ 2, 1 ], 0, 'row-major' ); + y = tile( x, [ 3, 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 3, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function prepends singleton dimensions when the number of repetitions exceeds the number of input dimensions (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = tile( x, [ 3, 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 3, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function prepends singleton dimensions when the number of repetitions exceeds the number of input dimensions (column-major, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 3, 2, 4 ], [ 2, 2 ], [ 1, 2 ], 0, 'column-major' ); + y = tile( x, [ 3, 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 3, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function prepends singleton dimensions when the number of repetitions exceeds the number of input dimensions (column-major, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ], { + 'order': 'column-major' + }); + y = tile( x, [ 3, 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 3, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 2, 2 ], [ 4, 2, 1 ], 0, 'row-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ], + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ], + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (column-major, base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 5, 3, 7, 2, 6, 4, 8 ], [ 2, 2, 2 ], [ 1, 2, 4 ], 0, 'column-major' ); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ], + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (column-major, non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ], { + 'order': 'column-major' + }); + y = tile( x, [ 2, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ], + [ 1, 2, 1, 2 ], + [ 3, 4, 3, 4 ] + ], + [ + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ], + [ 5, 6, 5, 6 ], + [ 7, 8, 7, 8 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array when all repetitions are equal to one (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 2, 2 ], [ 4, 2, 1 ], 0, 'row-major' ); + y = tile( x, [ 1, 1, 1 ] ); + + expected = [ + [ [ 1, 2 ], [ 3, 4 ] ], + [ [ 5, 6 ], [ 7, 8 ] ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 2, 2 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array when all repetitions are equal to one (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] ); + y = tile( x, [ 1, 1, 1 ] ); + + expected = [ + [ [ 1, 2 ], [ 3, 4 ] ], + [ [ 5, 6 ], [ 7, 8 ] ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 2, 2 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array along singleton dimensions (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2 ], [ 2, 1 ], [ 1, 1 ], 0, 'row-major' ); + y = tile( x, [ 2, 3 ] ); + + expected = [ + [ 1, 1, 1 ], + [ 2, 2, 2 ], + [ 1, 1, 1 ], + [ 2, 2, 2 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 3 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles an input array along singleton dimensions (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ [ 1 ], [ 2 ] ] ); + y = tile( x, [ 2, 3 ] ); + + expected = [ + [ 1, 1, 1 ], + [ 2, 2, 2 ], + [ 1, 1, 1 ], + [ 2, 2, 2 ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 4, 3 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles a zero-dimensional input array (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 5 ], [], [ 0 ], 0, 'row-major' ); + y = tile( x, [ 2, 3, 4 ] ); + + expected = [ + [ [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ] ], + [ [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ] ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 3, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + // Empty repetitions yield a zero-dimensional output: + y = tile( x, [] ); + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [], 'returns expected value' ); + t.strictEqual( y.get(), 5, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles a zero-dimensional input array (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = ndarray( 'generic', [ 5 ], [], [ 0 ], 0, 'row-major' ); + y = tile( x, [ 2, 3, 4 ] ); + + expected = [ + [ [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ] ], + [ [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ], [ 5, 5, 5, 5 ] ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 3, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + // Empty repetitions yield a zero-dimensional output: + y = tile( x, [] ); + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [], 'returns expected value' ); + t.strictEqual( y.get(), 5, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles a one-dimensional input array (base)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3 ], [ 3 ], [ 1 ], 0, 'row-major' ); + y = tile( x, [ 2 ] ); + + expected = [ 1, 2, 3, 1, 2, 3 ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 6 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function tiles a one-dimensional input array (non-base)', function test( t ) { + var expected; + var x; + var y; + + x = array( [ 1, 2, 3 ] ); + y = tile( x, [ 2 ] ); + + expected = [ 1, 2, 3, 1, 2, 3 ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 6 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function infers the output layout from the input strides (non-monotonic strides)', function test( t ) { + var expected; + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], [ 2, 3, 2 ], [ 2, 4, 1 ], 0, 'row-major' ); + y = tile( x, [ 1, 1, 2 ] ); + + expected = [ + [ + [ 1, 2, 1, 2 ], + [ 5, 6, 5, 6 ], + [ 9, 10, 9, 10 ] + ], + [ + [ 3, 4, 3, 4 ], + [ 7, 8, 7, 8 ], + [ 11, 12, 11, 12 ] + ] + ]; + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 2, 3, 4 ], 'returns expected value' ); + t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an empty ndarray when a repetition is zero (base)', function test( t ) { + var x; + var y; + + x = base( 'generic', [ 1, 2, 3, 4 ], [ 2, 2 ], [ 2, 1 ], 0, 'row-major' ); + y = tile( x, [ 0, 2 ] ); + + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 0, 4 ], 'returns expected value' ); + t.strictEqual( numel( getShape( y ) ), 0, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns an empty ndarray when a repetition is zero (non-base)', function test( t ) { + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = tile( x, [ 0, 2 ] ); + + t.notEqual( y, x, 'returns expected value' ); + t.notEqual( getData( y ), getData( x ), 'returns expected value' ); + t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); + t.deepEqual( getShape( y ), [ 0, 4 ], 'returns expected value' ); + t.strictEqual( numel( getShape( y ) ), 0, 'returns expected value' ); + + t.end(); +}); From 3aa1209c814e028641d4737eca7898630b89da2c Mon Sep 17 00:00:00 2001 From: headlessNode Date: Fri, 17 Apr 2026 17:04:07 +0500 Subject: [PATCH 2/4] fix: apply suggestions from code review --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: na - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- .../@stdlib/ndarray/base/tile/README.md | 5 +- .../@stdlib/ndarray/base/tile/docs/repl.txt | 15 +- .../ndarray/base/tile/docs/types/index.d.ts | 7 +- .../ndarray/base/tile/docs/types/test.ts | 56 +++----- .../@stdlib/ndarray/base/tile/lib/main.js | 60 ++++---- .../@stdlib/ndarray/base/tile/test/test.js | 132 ++---------------- 6 files changed, 77 insertions(+), 198 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/README.md b/lib/node_modules/@stdlib/ndarray/base/tile/README.md index 417b3f9595d0..d6b455850869 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/README.md +++ b/lib/node_modules/@stdlib/ndarray/base/tile/README.md @@ -64,9 +64,8 @@ var y = tile( x, [ 2, 2 ] ); ## Notes -- When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input [ndarray][@stdlib/ndarray/base/ctor] is treated as if singleton dimensions were prepended. -- The output [ndarray][@stdlib/ndarray/base/ctor] has rank equal to the greater of the input array rank and the number of repetitions. -- The function always returns a new [ndarray][@stdlib/ndarray/base/ctor] having a newly allocated data buffer. +- The number of repetitions must have at least as many elements as the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input [ndarray][@stdlib/ndarray/base/ctor] is treated as if singleton dimensions were prepended. +- The function always copies data to a new [ndarray][@stdlib/ndarray/base/ctor]. diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt b/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt index e77bfc0a74a5..339b8f8477de 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/repl.txt @@ -3,17 +3,12 @@ Returns an ndarray created by repeating the elements of an input ndarray a specified number of times along each dimension. - When the number of repetitions is less than the number of input dimensions, - the number of repetitions is left-padded with ones until the number of - repetitions matches the number of input dimensions. When the number of - repetitions exceeds the number of input dimensions, the input array is - treated as if singleton dimensions were prepended. + The number of repetitions must have at least as many elements as the number + of input dimensions. When the number of repetitions exceeds the number of + input dimensions, the input array is treated as if singleton dimensions + were prepended. - The output array has rank equal to the greater of the input array rank and - the number of repetitions. - - The function always returns a new ndarray having a newly allocated data - buffer. + The function always copies data to a new ndarray. Parameters ---------- diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts index aaa773aa0656..2e9eb8653434 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/index.d.ts @@ -28,9 +28,8 @@ import { ndarray } from '@stdlib/types/ndarray'; * * ## Notes * -* - When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. -* - The output array has rank equal to the greater of the input array rank and the number of repetitions. -* - The function always returns a new ndarray having a newly allocated data buffer. +* - The number of repetitions must have at least as many elements as the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. +* - The function always copies data to a new ndarray. * * @param x - input array * @param reps - number of repetitions along each dimension @@ -45,7 +44,7 @@ import { ndarray } from '@stdlib/types/ndarray'; * var y = tile( x, [ 2, 2 ] ); * // returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] */ -declare function tile( x: ndarray, reps: ArrayLike ): ndarray; +declare function tile( x: T, reps: ArrayLike ): T; // EXPORTS // diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts index da7c01d3ce55..fa079a85f8e0 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts +++ b/lib/node_modules/@stdlib/ndarray/base/tile/docs/types/test.ts @@ -16,46 +16,30 @@ * limitations under the License. */ +/* eslint-disable space-in-parens */ + /// -import { ndarray } from '@stdlib/types/ndarray'; +import zeros = require( '@stdlib/ndarray/zeros' ); import tile = require( './index' ); -/** -* Mock function to create an ndarray-like object. -* -* @returns 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; -} - // TESTS // -// The function returns an ndarray... +// The function returns an ndarray having the same type as the input ndarray... { - const x = array(); - - tile( x, [ 2, 2, 2 ] ); // $ExpectType ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'float64' } ), [ 2, 2 ] ); // $ExpectType float64ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'float32' } ), [ 2, 2 ] ); // $ExpectType float32ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'complex128' } ), [ 2, 2 ] ); // $ExpectType complex128ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'complex64' } ), [ 2, 2 ] ); // $ExpectType complex64ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'int32' } ), [ 2, 2 ] ); // $ExpectType int32ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'int16' } ), [ 2, 2 ] ); // $ExpectType int16ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'int8' } ), [ 2, 2 ] ); // $ExpectType int8ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'uint32' } ), [ 2, 2 ] ); // $ExpectType uint32ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'uint16' } ), [ 2, 2 ] ); // $ExpectType uint16ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'uint8' } ), [ 2, 2 ] ); // $ExpectType uint8ndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'uint8c' } ), [ 2, 2 ] ); // $ExpectType uint8cndarray + tile( zeros( [ 2, 2 ], { 'dtype': 'generic' } ), [ 2, 2 ] ); // $ExpectType genericndarray } // The compiler throws an error if the function is not provided a first argument which is an ndarray... @@ -72,7 +56,9 @@ function array(): ndarray { // The compiler throws an error if the function is not provided a second argument which is an array-like object containing numbers... { - const x = array(); + const x = zeros( [ 2, 2 ], { + 'dtype': 'float64' + }); tile( x, '5' ); // $ExpectError tile( x, 5 ); // $ExpectError @@ -86,7 +72,9 @@ function array(): ndarray { // The compiler throws an error if the function is provided an unsupported number of arguments... { - const x = array(); + const x = zeros( [ 2, 2 ], { + 'dtype': 'float64' + }); tile(); // $ExpectError tile( x ); // $ExpectError diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js index 46eaae131313..6265141323bb 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js @@ -32,6 +32,7 @@ var getOffset = require( '@stdlib/ndarray/base/offset' ); var getOrder = require( '@stdlib/ndarray/base/order' ); var getDType = require( '@stdlib/ndarray/base/dtype' ); var getData = require( '@stdlib/ndarray/base/data-buffer' ); +var format = require( '@stdlib/string/format' ); var zeros = require( '@stdlib/array/base/zeros' ); @@ -42,12 +43,12 @@ var zeros = require( '@stdlib/array/base/zeros' ); * * ## Notes * -* - When the number of repetitions is less than the number of input dimensions, the number of repetitions is left-padded with ones until the number of repetitions matches the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. -* - The output array has rank equal to the greater of the input array rank and the number of repetitions. -* - The function always returns a new ndarray having a newly allocated data buffer. +* - The number of repetitions must have at least as many elements as the number of input dimensions. When the number of repetitions exceeds the number of input dimensions, the input array is treated as if singleton dimensions were prepended. +* - The function always copies data to a new ndarray. * * @param {ndarray} x - input array * @param {NonNegativeIntegerArray} reps - number of repetitions along each dimension +* @throws {RangeError} second argument must have at least as many elements as the number of input dimensions * @returns {ndarray} output array * * @example @@ -66,23 +67,21 @@ function tile( x, reps ) { var sho; var shi; var sto; - var ord; var buf; var out; - var Dr; var Ds; var si; var sx; var v1; var v2; - var K; var L; var M; var N; - var r; + var o; var s; var t; var i; + var j; shx = getShape( x, false ); sx = getStrides( x, false ); @@ -90,40 +89,41 @@ function tile( x, reps ) { N = reps.length; M = shx.length; - // Determine the output rank, which is the greater of the number of input dimensions and the number of repetitions. Compute the implicit left-padding amounts for the repetitions and input shape, respectively... - K = ( N > M ) ? N : M; - Dr = K - N; - Ds = K - M; + if ( N < M ) { + throw new RangeError( format( 'invalid argument. Second argument must have at least as many elements as the number of dimensions of the first argument. Number of input dimensions: `%u`. Number of repetitions: `%u`.', M, N ) ); + } + // Compute the implicit left-padding amount for the input shape: + Ds = N - M; - // Infer the storage order from the input strides, falling back to the stated order when the input is non-contiguous... - ord = strides2order( sx ); - if ( ord === 2 ) { - order = 'column-major'; - } else if ( ord === 1 || ord === 3 ) { + o = strides2order( sx ); + if ( o === 0 || o === 3 ) { + // Fallback to stated layout when unable to infer the underlying physical layout: + order = getOrder( x ); + } else if ( o === 1 ) { order = 'row-major'; } else { - order = getOrder( x ); + order = 'column-major'; } - // Compute an interleaved 2K-D shape and strides for broadcasting the input, along with the final K-D output shape. By inserting a repetition axis next to each original axis, a contiguous 2K-D buffer can be reinterpreted as the K-D tiled output without an additional copy... - shi = zeros( 2*K ); - si = zeros( 2*K ); - sho = zeros( K ); - for ( i = 0; i < K; i++ ) { - r = ( i < Dr ) ? 1 : reps[ i - Dr ]; - s = ( i < Ds ) ? 1 : shx[ i - Ds ]; - t = ( i < Ds ) ? 0 : sx[ i - Ds ]; - sho[ i ] = r * s; + // Compute an interleaved 2N-D shape and strides for broadcasting the input, along with the final N-D output shape. By inserting a repetition axis next to each original axis, a contiguous 2N-D buffer can be reinterpreted as the N-D tiled output without an additional copy... + shi = zeros( 2*N ); + si = zeros( 2*N ); + sho = zeros( N ); + for ( i = 0; i < N; i++ ) { + j = i - Ds; + s = ( j < 0 ) ? 1 : shx[ j ]; + t = ( j < 0 ) ? 0 : sx[ j ]; + sho[ i ] = reps[ i ] * s; if ( order === 'row-major' ) { - shi[ 2*i ] = r; + shi[ 2*i ] = reps[ i ]; shi[ (2*i)+1 ] = s; si[ (2*i)+1 ] = t; } else { shi[ 2*i ] = s; - shi[ (2*i)+1 ] = r; + shi[ (2*i)+1 ] = reps[ i ]; si[ 2*i ] = t; } } - if ( K > 0 ) { + if ( N > 0 ) { L = numel( sho ); sto = shape2strides( sho, order ); } else { @@ -133,7 +133,7 @@ function tile( x, reps ) { buf = buffer( dtype, L ); out = new x.constructor( dtype, buf, sho, sto, 0, order ); - // Assign the broadcasted input to a 2K-D view over the output data buffer... + // Assign the broadcasted input to a 2N-D view over the output data buffer... v1 = ndarray( dtype, getData( x ), shi, si, getOffset( x ), order ); v2 = ndarray( dtype, buf, shi, shape2strides( shi, order ), 0, order ); assign( [ v1, v2 ] ); diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js b/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js index dd5bb73c387c..67d1403471e1 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js +++ b/lib/node_modules/@stdlib/ndarray/base/tile/test/test.js @@ -376,130 +376,28 @@ tape( 'the function prepends singleton dimensions when the number of repetitions t.end(); }); -tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (base)', function test( t ) { - var expected; +tape( 'the function throws an error if the number of repetitions is less than the number of input dimensions', function test( t ) { + var values; var x; - var y; + var i; x = base( 'generic', [ 1, 2, 3, 4, 5, 6, 7, 8 ], [ 2, 2, 2 ], [ 4, 2, 1 ], 0, 'row-major' ); - y = tile( x, [ 2, 2 ] ); - - expected = [ - [ - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ], - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ] - ], - [ - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ], - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ] - ] - ]; - t.notEqual( y, x, 'returns expected value' ); - t.notEqual( getData( y ), getData( x ), 'returns expected value' ); - t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); - t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); - t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); - - t.end(); -}); - -tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (non-base)', function test( t ) { - var expected; - var x; - var y; - x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ] ); - y = tile( x, [ 2, 2 ] ); - - expected = [ - [ - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ], - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ] - ], - [ - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ], - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ] - ] + values = [ + [], + [ 2 ], + [ 2, 2 ] ]; - t.notEqual( y, x, 'returns expected value' ); - t.notEqual( getData( y ), getData( x ), 'returns expected value' ); - t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); - t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); - t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); - + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), RangeError, 'throws an error when provided ' + values[ i ] ); + } t.end(); -}); -tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (column-major, base)', function test( t ) { - var expected; - var x; - var y; - - x = base( 'generic', [ 1, 5, 3, 7, 2, 6, 4, 8 ], [ 2, 2, 2 ], [ 1, 2, 4 ], 0, 'column-major' ); - y = tile( x, [ 2, 2 ] ); - - expected = [ - [ - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ], - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ] - ], - [ - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ], - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ] - ] - ]; - t.notEqual( y, x, 'returns expected value' ); - t.notEqual( getData( y ), getData( x ), 'returns expected value' ); - t.strictEqual( instanceOf( y, base ), true, 'returns expected value' ); - t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); - t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); - - t.end(); -}); - -tape( 'the function left-pads the number of repetitions with ones when fewer repetitions are provided than the number of input dimensions (column-major, non-base)', function test( t ) { - var expected; - var x; - var y; - - x = array( [ [ [ 1, 2 ], [ 3, 4 ] ], [ [ 5, 6 ], [ 7, 8 ] ] ], { - 'order': 'column-major' - }); - y = tile( x, [ 2, 2 ] ); - - expected = [ - [ - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ], - [ 1, 2, 1, 2 ], - [ 3, 4, 3, 4 ] - ], - [ - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ], - [ 5, 6, 5, 6 ], - [ 7, 8, 7, 8 ] - ] - ]; - t.notEqual( y, x, 'returns expected value' ); - t.notEqual( getData( y ), getData( x ), 'returns expected value' ); - t.strictEqual( instanceOf( y, ndarray ), true, 'returns expected value' ); - t.deepEqual( getShape( y ), [ 2, 4, 4 ], 'returns expected value' ); - t.deepEqual( ndarray2array( y ), expected, 'returns expected value' ); - - t.end(); + function badValue( value ) { + return function badValue() { + tile( x, value ); + }; + } }); tape( 'the function tiles an input array when all repetitions are equal to one (base)', function test( t ) { From 44d09706958fd5f286b9330f39b113865c02fa91 Mon Sep 17 00:00:00 2001 From: Athan Date: Sat, 18 Apr 2026 03:38:07 -0700 Subject: [PATCH 3/4] chore: clean-up Signed-off-by: Athan --- .../@stdlib/ndarray/base/tile/lib/main.js | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js index 6265141323bb..03a13c3af4f3 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/tile/lib/main.js @@ -32,8 +32,8 @@ var getOffset = require( '@stdlib/ndarray/base/offset' ); var getOrder = require( '@stdlib/ndarray/base/order' ); var getDType = require( '@stdlib/ndarray/base/dtype' ); var getData = require( '@stdlib/ndarray/base/data-buffer' ); -var format = require( '@stdlib/string/format' ); var zeros = require( '@stdlib/array/base/zeros' ); +var format = require( '@stdlib/string/format' ); // MAIN // @@ -68,13 +68,13 @@ function tile( x, reps ) { var shi; var sto; var buf; + var len; var out; var Ds; var si; var sx; var v1; var v2; - var L; var M; var N; var o; @@ -82,6 +82,7 @@ function tile( x, reps ) { var t; var i; var j; + var k; shx = getShape( x, false ); sx = getStrides( x, false ); @@ -104,39 +105,44 @@ function tile( x, reps ) { } else { order = 'column-major'; } - // Compute an interleaved 2N-D shape and strides for broadcasting the input, along with the final N-D output shape. By inserting a repetition axis next to each original axis, a contiguous 2N-D buffer can be reinterpreted as the N-D tiled output without an additional copy... + // Compute an interleaved 2N-D shape and strides for "broadcasting" the input, along with the final N-D output shape. By inserting a repetition axis next to each original axis, a contiguous 2N-D buffer can be reinterpreted as the N-D tiled output without an additional copy... shi = zeros( 2*N ); si = zeros( 2*N ); sho = zeros( N ); for ( i = 0; i < N; i++ ) { j = i - Ds; + k = 2 * i; s = ( j < 0 ) ? 1 : shx[ j ]; t = ( j < 0 ) ? 0 : sx[ j ]; sho[ i ] = reps[ i ] * s; if ( order === 'row-major' ) { - shi[ 2*i ] = reps[ i ]; - shi[ (2*i)+1 ] = s; - si[ (2*i)+1 ] = t; - } else { - shi[ 2*i ] = s; - shi[ (2*i)+1 ] = reps[ i ]; - si[ 2*i ] = t; + shi[ k ] = reps[ i ]; + shi[ k+1 ] = s; + si[ k+1 ] = t; + } else { // order === 'column-major' + shi[ k ] = s; + shi[ k+1 ] = reps[ i ]; + si[ k ] = t; } } if ( N > 0 ) { - L = numel( sho ); + len = numel( sho ); sto = shape2strides( sho, order ); } else { - L = 1; + len = 1; sto = [ 0 ]; } - buf = buffer( dtype, L ); + // Allocate an output array: + buf = buffer( dtype, len ); out = new x.constructor( dtype, buf, sho, sto, 0, order ); - // Assign the broadcasted input to a 2N-D view over the output data buffer... + // Create a "broadcasted" input 2N-D view over the data buffers: v1 = ndarray( dtype, getData( x ), shi, si, getOffset( x ), order ); v2 = ndarray( dtype, buf, shi, shape2strides( shi, order ), 0, order ); + + // Copy the elements to the output array: assign( [ v1, v2 ] ); + return out; } From 153e4d747a8b3b195f2f7534636134e2ace66686 Mon Sep 17 00:00:00 2001 From: Athan Date: Sat, 18 Apr 2026 03:46:59 -0700 Subject: [PATCH 4/4] docs: update copy Signed-off-by: Athan --- lib/node_modules/@stdlib/ndarray/base/tile/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/node_modules/@stdlib/ndarray/base/tile/README.md b/lib/node_modules/@stdlib/ndarray/base/tile/README.md index d6b455850869..9fb79806ddd7 100644 --- a/lib/node_modules/@stdlib/ndarray/base/tile/README.md +++ b/lib/node_modules/@stdlib/ndarray/base/tile/README.md @@ -54,6 +54,11 @@ var y = tile( x, [ 2, 2 ] ); // returns [ [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ], [ 1, 2, 1, 2 ], [ 3, 4, 3, 4 ] ] ``` +The function accepts the following arguments: + +- **x**: input [ndarray][@stdlib/ndarray/base/ctor]. +- **reps**: list specifying the number of times to repeat elements of an input [ndarray][@stdlib/ndarray/base/ctor] along each dimension. +