From c1747c0f383d54afbb23be22167e9535d85c238e Mon Sep 17 00:00:00 2001 From: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> Date: Mon, 11 Aug 2025 06:46:16 +0000 Subject: [PATCH 1/8] feat: add ndarray/base/broadcast-array-except-dimensions --- 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 --- --- .../README.md | 177 ++++ .../benchmark/benchmark.js | 161 ++++ .../docs/repl.txt | 58 ++ .../docs/types/index.d.ts | 83 ++ .../docs/types/test.ts | 126 +++ .../examples/index.js | 49 + .../lib/index.js | 68 ++ .../lib/main.js | 159 ++++ .../package.json | 68 ++ .../test/test.js | 882 ++++++++++++++++++ 10 files changed, 1831 insertions(+) create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json create mode 100644 lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md new file mode 100644 index 000000000000..cf1b8824cba0 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md @@ -0,0 +1,177 @@ + + +# broadcastArrayExceptDimensions + +> Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged. + + + +
+ +
+ + + + + +
+ +## Usage + + + +```javascript +var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); +``` + +#### broadcastArrayExceptDimensions( arr, shape\[, dims] ) + +Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged. + +```javascript +var array = require( '@stdlib/ndarray/array' ); + +// Create a 2x2 ndarray: +var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +// returns + +// Perform broadcasting: +var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ] ); +// returns + +var ysh = y.shape; +// returns [ 3, 2, 2 ] +``` + +The function accepts the following arguments: + +- **arr**: input ndarray. +- **shape**: target shape. +- **dims**: list of dimensions which are exculded from broadcasting. Default: `[ -1 ]` (_optional_). + +To exclude specific dimensions from broadcasting, provide a `dims` parameter. + +```javascript +var array = require( '@stdlib/ndarray/array' ); + +// Create a 2x2 ndarray: +var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); +// returns + +// Perform broadcasting: +var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ], [ -2 ] ); +// returns + +var ysh = y.shape; +// returns [ 3, 2, 2 ] +``` + +
+ + + + + +
+ +## Notes + +- The function throws an error if a provided [ndarray][@stdlib/ndarray/base/ctor] is [incompatible][@stdlib/ndarray/base/broadcast-shapes] with a provided shape. +- The returned [ndarray][@stdlib/ndarray/base/ctor] is a "base" [ndarray][@stdlib/ndarray/base/ctor], and, thus, the returned [ndarray][@stdlib/ndarray/base/ctor] does not perform bounds checking or afford any of the guarantees of the non-base [ndarray][@stdlib/ndarray/ctor] constructor. The primary intent of this function is to broadcast an ndarray-like object within internal implementations and to do so with minimal overhead. +- The function always returns a new [ndarray][@stdlib/ndarray/base/ctor] instance even if the input [ndarray][@stdlib/ndarray/base/ctor] shape and the desired shape are the same. + +
+ + + + + +
+ +## Examples + + + +```javascript +var array = require( '@stdlib/ndarray/array' ); +var numel = require( '@stdlib/ndarray/base/numel' ); +var ind2sub = require( '@stdlib/ndarray/ind2sub' ); +var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); + +// Create a 1x3 array: +var x = array( [ [ 1, 2, 3 ] ] ); +// returns + +// Broadcast the array to 3x2x2: +var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +// returns + +// Retrieve the shape: +var sh = y.shape; +// returns [ 2, 1, 3 ] + +// Retrieve the number of elements: +var N = numel( sh ); + +// Loop through the array elements... +var sub; +var v; +var i; +for ( i = 0; i < N; i++ ) { + v = y.iget( i ); + sub = ind2sub( sh, i ); + console.log( 'Y[%s] = %d', sub.join( ', ' ), v ); +} +``` + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js new file mode 100644 index 000000000000..1933c79e81a0 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js @@ -0,0 +1,161 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 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 pkg = require( './../package.json' ).name; +var broadcastArrayExceptDimensions = require( './../lib' ); + + +// MAIN // + +bench( pkg+'::base_ndarray,2d', 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 = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 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( pkg+'::ndarray,2d', 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 = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 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( pkg+'::ndarray_like,2d', function benchmark( b ) { + var strides; + var values; + var buffer; + var offset; + var dtype; + var shape; + var order; + var out; + var obj; + var i; + + dtype = 'float64'; + buffer = new Float64Array( 4 ); + shape = [ 2, 2 ]; + strides = [ 2, 1 ]; + offset = 0; + order = 'row-major'; + + values = []; + for ( i = 0; i < 5; i++ ) { + obj = { + 'dtype': dtype, + 'data': buffer, + 'shape': shape, + 'strides': strides, + 'offset': offset, + 'order': order + }; + values.push( obj ); + } + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 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/broadcast-array-except-dimensions/docs/repl.txt b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt new file mode 100644 index 000000000000..077e2307d25e --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt @@ -0,0 +1,58 @@ + +{{alias}}( arr, shape[, dims] ) + Broadcasts an input ndarray to a target shape keeping the specified + dimensions unchanged. + + The returned array is a "base" ndarray, and, thus, the returned array does + not perform bounds checking or afford any of the guarantees of the non-base + ndarray constructor. The primary intent of this function is to broadcast an + ndarray-like object within internal implementations and to do so with + minimal overhead. + + The function always returns a new ndarray instance even if the input ndarray + shape and the desired shape are the same. + + The function throws an error if a provided ndarray is incompatible with a + provided shape. + + Parameters + ---------- + arr: ndarray + Input array. + + shape: ArrayLikeObject + Desired shape. + + dims: Array (optional) + List of dimensions to exclude from broadcasting. + + Returns + ------- + out: ndarray + Broadcasted array. + + Examples + -------- + > var x = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2, 3 ] ] ) + + > var sh = x.shape + [ 1, 3 ] + > var y = {{alias}}( x, [ 2, 2, 3 ], [ -2 ] ) + + > sh = y.shape + [ 2, 1, 3 ] + > var v = y.get( 0, 0, 0 ) + 1 + > v = y.get( 0, 0, 1 ) + 2 + > v = y.get( 0, 0, 2 ) + 3 + > v = y.get( 1, 0, 0 ) + 1 + > v = y.get( 1, 0, 1 ) + 2 + > v = y.get( 1, 0, 2 ) + 3 + + See Also + -------- diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts new file mode 100644 index 000000000000..fd6062082898 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts @@ -0,0 +1,83 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2025 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'; + +/** +* Broadcasts an input ndarray to a target shape keeping the specified dimension unchanged. +* +* ## Notes +* +* - The function throws an error if a provided ndarray is incompatible with a provided shape. +* - The returned array is a view on the input array data buffer. The view is typically **not** contiguous. As more than one element of a returned view may refer to the same memory location, writing to the view may affect multiple elements. If you need to write to the returned array, copy the array before performing operations which may mutate elements. +* - The returned array is a "base" ndarray, and, thus, the returned array does not perform bounds checking or afford any of the guarantees of the non-base ndarray constructor. The primary intent of this function is to broadcast an ndarray-like object within internal implementations and to do so with minimal overhead. +* - The function always returns a new ndarray instance even if the input ndarray shape and the desired shape are the same. +* +* @param arr - input array +* @param shape - desired shape +* @param dims - list of dimensions to exclude +* @throws input array cannot have more dimensions than the desired shape +* @throws input array and desired shape must be broadcast compatible +* @throws dimension indices must not exceed desired shape bounds +* @throws must provide unique dimension indices +* @returns broadcasted array +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1, 2, 3 ] ] ); +* // returns +* +* var shx = x.shape; +* // returns [ 1, 3 ] +* +* var y = broadcastArrayExceptDimensionsExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +* // returns +* +* var shy = y.shape; +* // returns [ 2, 1, 3 ] +* +* var v = y.get( 0, 0, 0 ); +* // returns 1 +* +* v = y.get( 0, 0, 1 ); +* // returns 2 +* +* v = y.get( 0, 0, 2 ); +* // returns 3 +* +* v = y.get( 1, 0, 0 ); +* // returns 1 +* +* v = y.get( 1, 0, 1 ); +* // returns 2 +* +* v = y.get( 1, 0, 2 ); +* // returns 3 +*/ +declare function broadcastArrayExceptDimensions( arr: ndarray, shape: ArrayLike, dims?: ArrayLike ): ndarray; + + +// EXPORTS // + +export = broadcastArrayExceptDimensions; diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts new file mode 100644 index 000000000000..07b82ebf48d3 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts @@ -0,0 +1,126 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2025 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 broadcastArrayExceptDimensions = 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(); + + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); // $ExpectType ndarray + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); // $ExpectType ndarray +} + +// The compiler throws an error if the function is not provided a first argument which is an ndarray... +{ + broadcastArrayExceptDimensions( '5', [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( 5, [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( true, [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( false, [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( null, [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( {}, [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( [ '5' ], [ 2, 2, 2 ] ); // $ExpectError + broadcastArrayExceptDimensions( ( x: number ): number => x, [ 2, 2, 2 ] ); // $ExpectError + + broadcastArrayExceptDimensions( '5', [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( 5, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( true, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( false, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( null, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( {}, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( [ '5' ], [ 2, 2, 2 ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( ( x: number ): number => x, [ 2, 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(); + + broadcastArrayExceptDimensions( x, '5' ); // $ExpectError + broadcastArrayExceptDimensions( x, 5 ); // $ExpectError + broadcastArrayExceptDimensions( x, true ); // $ExpectError + broadcastArrayExceptDimensions( x, false ); // $ExpectError + broadcastArrayExceptDimensions( x, null ); // $ExpectError + broadcastArrayExceptDimensions( x, {} ); // $ExpectError + broadcastArrayExceptDimensions( x, [ '5' ] ); // $ExpectError + broadcastArrayExceptDimensions( x, ( x: number ): number => x ); // $ExpectError + + broadcastArrayExceptDimensions( x, '5', [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, 5, [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, true, [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, false, [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, null, [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, {}, [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, [ '5' ], [ -2 ] ); // $ExpectError + broadcastArrayExceptDimensions( x, ( x: number ): number => x, [ -2 ] ); // $ExpectError +} + +// The compiler throws an error if the function is not provided a third argument which is not an array-like object containing numbers... +{ + const x = array(); + + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], '5' ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], 5 ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], true ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], false ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], null ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ '5' ] ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an unsupported number of arguments... +{ + const x = array(); + + broadcastArrayExceptDimensions(); // $ExpectError + broadcastArrayExceptDimensions( x ); // $ExpectError + broadcastArrayExceptDimensions( x, [ 1, 2, 3 ], [ -2 ], {} ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js new file mode 100644 index 000000000000..e47cf7dd89ff --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js @@ -0,0 +1,49 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 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 numel = require( '@stdlib/ndarray/base/numel' ); +var ind2sub = require( '@stdlib/ndarray/ind2sub' ); +var broadcastArrayExceptDimensions = require( './../lib' ); + +// Create a 1x3 array: +var x = array( [ [ 1, 2, 3 ] ] ); +// returns + +// Broadcast the array to 2x1x3: +var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +// returns + +// Retrieve the shape: +var sh = y.shape; +// returns [ 2, 1, 3 ] + +// Retrieve the number of elements: +var N = numel( sh ); + +// Loop through the array elements... +var sub; +var v; +var i; +for ( i = 0; i < N; i++ ) { + v = y.iget( i ); + sub = ind2sub( sh, i ); + console.log( 'Y[%s] = %d', sub.join( ', ' ), v ); +} diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js new file mode 100644 index 000000000000..237b0f99d235 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js @@ -0,0 +1,68 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 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'; + +/** +* Broadcast an input ndarray to a target shape keeping the specified dimensions unchanged. +* +* @module @stdlib/ndarray/base/broadcast-array-except-dimensions +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); +* +* var x = array( [ [ 1, 2, 3 ] ] ); +* // returns +* +* var shx = x.shape; +* // returns [ 1, 3 ] +* +* var y = broadcastArrayExceptDimensionsExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +* // returns +* +* var shy = y.shape; +* // returns [ 2, 1, 3 ] +* +* var v = y.get( 0, 0, 0 ); +* // returns 1 +* +* v = y.get( 0, 0, 1 ); +* // returns 2 +* +* v = y.get( 0, 0, 2 ); +* // returns 3 +* +* v = y.get( 1, 0, 0 ); +* // returns 1 +* +* v = y.get( 1, 0, 1 ); +* // returns 2 +* +* v = y.get( 1, 0, 2 ); +* // returns 3 +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js new file mode 100644 index 000000000000..7fa58838aa4f --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js @@ -0,0 +1,159 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2025 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 copy = require( '@stdlib/array/base/copy-indexed' ); +var ndarray = require( '@stdlib/ndarray/base/ctor' ); +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 normalizeIndices = require( '@stdlib/ndarray/base/normalize-indices' ); +var format = require( '@stdlib/string/format' ); +var join = require( '@stdlib/array/base/join' ); + + +// MAIN // + +/** +* Broadcasts an input ndarray to a target shape keeping the specified dimensions unchanged. +* +* @param {ndarray} arr - input array +* @param {NonNegativeIntegerArray} shape - desired shape +* @param {IntegerArray} [dims] - list of dimensions to exclude +* @throws {Error} input array cannot have more dimensions than the desired shape +* @throws {Error} input array and desired shape must be broadcast compatible +* @throws {RangeError} dimension indices must not exceed desired shape bounds +* @throws {Error} must provide unique dimension indices +* @returns {ndarray} broadcasted array +* +* @example +* var array = require( '@stdlib/ndarray/array' ); +* +* var x = array( [ [ 1, 2, 3 ] ] ); +* // returns +* +* var shx = x.shape; +* // returns [ 1, 3 ] +* +* var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +* // returns +* +* var shy = y.shape; +* // returns [ 2, 1, 3 ] +* +* var v = y.get( 0, 0, 0 ); +* // returns 1 +* +* v = y.get( 0, 0, 1 ); +* // returns 2 +* +* v = y.get( 0, 0, 2 ); +* // returns 3 +* +* v = y.get( 1, 0, 0 ); +* // returns 1 +* +* v = y.get( 1, 0, 1 ); +* // returns 2 +* +* v = y.get( 1, 0, 2 ); +* // returns 3 +*/ +function broadcastArrayExceptDimensions( arr, shape, dims ) { + var strides; + var dim; + var sh; + var st; + var dl; + var di; + var N; + var M; + var d; + var i; + var j; + + N = shape.length; + sh = getShape( arr, false ); + M = sh.length; + if ( N < M ) { + throw new Error( 'invalid argument. Cannot broadcast an array to a shape having fewer dimensions. Arrays can only be broadcasted to shapes having the same or more dimensions.' ); + } + // Initialize a strides array... + strides = []; + for ( i = 0; i < N; i++ ) { + strides.push( 0 ); + } + // Determine the output array strides... + st = getStrides( arr, false ); + + if ( !dims ) { + dims = [ -1 ]; + } + // Verify that we've been provided a list of unique dimension indices... + dl = dims.length; + dims = normalizeIndices( dims, N - 1 ); + if ( dims === null ) { + throw new RangeError( format( 'invalid argument. Third argument contains an out-of-bounds dimension index. Value: [%s].', join( dims, ',' ) ) ); + } + dims.sort(); + if ( dims.length !== dl ) { + throw new Error( format( 'invalid argument. Third argument must contain a list of unique dimension indices. Value: [%s].', join( dims, ',' ) ) ); + } + di = dims.length - 1; + for ( i = N-1; i >= 0; i-- ) { + j = M - N + i; + if ( di >= 0 && dims[ di ] === i ) { + if (j >= 0) { + shape[ i ] = sh[ j ]; + strides[ i ] = st[ j ]; + } + di -= 1; + continue; + } + if ( j < 0 ) { + // Prepended singleton dimension; stride is zero... + continue; + } + d = sh[ j ]; + dim = shape[ i ]; + if ( dim !== 0 && dim < d ) { + throw new Error( format( 'invalid argument. Input array cannot be broadcast to the specified shape, as the specified shape has a dimension whose size is less than the size of the corresponding dimension in the input array. Array shape: (%s). Desired shape: (%s). Dimension: %u.', copy( sh ).join( ', ' ), copy( shape ).join( ', ' ), i ) ); + } + if ( d === dim ) { + strides[ i ] = st[ j ]; + } else if ( d === 1 ) { + // In order to broadcast dimensions, we set the stride for that dimension to zero... + strides[ i ] = 0; + } else { + // At this point, we know that `dim > d` and that `d` does not equal `1` (e.g., `dim=3` and `d=2`); in which case, the shapes are considered incompatible (even for desired shapes which are multiples of array dimensions, as might be desired when "tiling" an array; e.g., `dim=4` and `d=2`)... + throw new Error( format( 'invalid argument. Input array and the specified shape are broadcast incompatible. Array shape: (%s). Desired shape: (%s). Dimension: %u.', copy( sh ).join( ', ' ), copy( shape ).join( ', ' ), i ) ); + } + } + return ndarray( getDType( arr ), getData( arr ), copy( shape ), strides, getOffset( arr ), getOrder( arr ) ); // eslint-disable-line max-len +} + + +// EXPORTS // + +module.exports = broadcastArrayExceptDimensions; diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json new file mode 100644 index 000000000000..45866e8db369 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json @@ -0,0 +1,68 @@ +{ + "name": "@stdlib/ndarray/base/broadcast-array-except-dimensions", + "version": "0.0.0", + "description": "Broadcast an input ndarray to a target shape keeping the specified dimensions unchanged.", + "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", + "broadcast", + "broadcasting", + "reshape", + "multidimensional", + "array", + "utilities", + "utility", + "utils", + "util" + ], + "__stdlib__": {} +} diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js new file mode 100644 index 000000000000..c8a7ba6240e0 --- /dev/null +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js @@ -0,0 +1,882 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2021 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/base/ctor' ); +var broadcastArrayExceptDimensions = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof broadcastArrayExceptDimensions, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if provided a desired shape which has fewer dimensions than input array', function test( t ) { + var values; + var x; + var i; + + x = array({ + 'shape': [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ] + }); + + values = [ + [], + [ 2 ], + [ 2, 2 ], + [ 2, 2, 2 ], + [ 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided a shape with '+values[ i ].length+' dimension' ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + broadcastArrayExceptDimensions( x, value ); + }; + } +}); + +tape( 'the function throws an error if provided a desired shape which has fewer dimensions than input array (dims)', function test( t ) { + var values; + var x; + var i; + + x = array({ + 'shape': [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ] + }); + + values = [ + [], + [ 2 ], + [ 2, 2 ], + [ 2, 2, 2 ], + [ 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2, 2 ], + [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided a shape with '+values[ i ].length+' dimension' ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + broadcastArrayExceptDimensions( x, value, [ -2 ] ); + }; + } +}); + +tape( 'the function throws an error if provided a desired shape having a dimension whose size is less than the corresponding dimension in the input array', function test( t ) { + var values; + var x; + var i; + + x = array({ + 'shape': [ 10, 10 ] + }); + + values = [ + [ 10, 10, 1 ], + [ 10, 10, 2 ], + [ 10, 10, 9 ], + [ 10, 1, 10 ], + [ 10, 2, 10 ], + [ 10, 9, 10 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided shape ('+values[ i ].join( ',')+')' ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + broadcastArrayExceptDimensions( x, value, [ -3 ] ); + }; + } +}); + +tape( 'the function throws an error if provided a desired shape and an input array shape are broadcast-incompatible', function test( t ) { + var values; + var x; + var i; + + x = array({ + 'shape': [ 10, 10 ] + }); + + values = [ + [ 10, 20, 10 ], + [ 10, 100, 10 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided shape ('+values[ i ].join( ',')+')' ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + broadcastArrayExceptDimensions( x, value ); + }; + } +}); + +tape( 'the function throws an error if provided a desired shape and an input array shape are broadcast-incompatible (dims)', function test( t ) { + var values; + var x; + var i; + + x = array({ + 'shape': [ 10, 10 ] + }); + + values = [ + [ 10, 10, 20 ], + [ 10, 100, 10 ] + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[ i ] ), Error, 'throws an error when provided shape ('+values[ i ].join( ',')+')' ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + broadcastArrayExceptDimensions( x, value, [ -3 ] ); + }; + } +}); + +tape( 'the function returns a "base" ndarray instance', function test( t ) { + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); + + t.notEqual( y, x, 'returns new instance' ); + t.strictEqual( y instanceof ndarray, true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns a "base" ndarray instance (dims)', function test( t ) { + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); + + t.notEqual( y, x, 'returns new instance' ); + t.strictEqual( y instanceof ndarray, true, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns a view over the input array data buffer', function test( t ) { + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); + + t.strictEqual( y.data, x.data, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function returns a view over the input array data buffer (dims)', function test( t ) { + var x; + var y; + + x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); + + t.strictEqual( y.data, x.data, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2 ], + 'order': 'row-major' + }); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2 ], + 'order': 'row-major' + }); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, strides)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, strides, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, strides)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ -2, 1 ], 2, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, strides, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ -2, 1 ], 2, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, non-contiguous)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 5 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 7 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (row-major, non-contiguous, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; + x = ndarray( 'generic', data, [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 5 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 7 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (column-major)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2 ], + 'order': 'column-major' + }); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (column-major, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2 ], + 'order': 'column-major' + }); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (same shape)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2, 2 ], + 'order': 'row-major' + }); + + expected = [ 2, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, x.get( i, 1, 0 ), 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, x.get( i, 1, 1 ), 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (same shape, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 2, 2 ], + 'order': 'row-major' + }); + + expected = [ 2, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, x.get( i, 1, 0 ), 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, x.get( i, 1, 1 ), 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (same number of dimensions)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 1, 2 ], + 'order': 'row-major' + }); + + expected = [ 2, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (same number of dimensions, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2, 3, 4 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 2, 1, 2 ], + 'order': 'row-major' + }); + + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); + expected = [ 2, 1, 2 ]; + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 0, 0 ); + t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (singleton dimension)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 1, 2 ], + 'order': 'row-major' + }); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (singleton dimension, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1, 2 ]; + x = array( data, { + 'dtype': 'generic', + 'shape': [ 1, 2 ], + 'order': 'row-major' + }); + + y = broadcastArrayExceptDimensions( x, [ 5, 2, 2 ], [ -2 ] ); + expected = [ 5, 1, 2 ]; + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (0-dimensional array)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1 ]; + x = ndarray( 'generic', data, [], [ 0 ], 0, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); + +tape( 'the function broadcasts an input array (0-dimensional array, dims)', function test( t ) { + var expected; + var actual; + var data; + var x; + var y; + var v; + var i; + + data = [ 1 ]; + x = ndarray( 'generic', data, [], [ 0 ], 0, 'row-major' ); + + expected = [ 5, 2, 2 ]; + y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + + actual = y.shape; + t.deepEqual( actual, expected, 'returns expected shape' ); + + for ( i = 0; i < expected[ 0 ]; i++ ) { + v = y.get( i, 0, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); + + v = y.get( i, 0, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,1)' ); + + v = y.get( i, 1, 0 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); + + v = y.get( i, 1, 1 ); + t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); + } + t.end(); +}); From 8a1214ad6386b620ea585bb45886a11d25a0ba15 Mon Sep 17 00:00:00 2001 From: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> Date: Mon, 11 Aug 2025 11:53:25 +0500 Subject: [PATCH 2/8] docs: fix copyright year Signed-off-by: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> --- .../ndarray/base/broadcast-array-except-dimensions/test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js index c8a7ba6240e0..80618a87e2c4 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2021 The Stdlib Authors. +* Copyright (c) 2025 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. From df378b7aebe652d6132fcb83df61974bd11ceb98 Mon Sep 17 00:00:00 2001 From: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> Date: Wed, 13 Aug 2025 01:04:27 +0500 Subject: [PATCH 3/8] fix: apply suggestions from code review Co-authored-by: Athan Signed-off-by: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> --- .../ndarray/base/broadcast-array-except-dimensions/lib/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js index 7fa58838aa4f..4b68ab0f0935 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js @@ -124,7 +124,7 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { for ( i = N-1; i >= 0; i-- ) { j = M - N + i; if ( di >= 0 && dims[ di ] === i ) { - if (j >= 0) { + if ( j >= 0 ) { shape[ i ] = sh[ j ]; strides[ i ] = st[ j ]; } From a4ab7d6baa4f70a9b95a7acdc4a222a7b4a8c0f4 Mon Sep 17 00:00:00 2001 From: Athan Date: Fri, 29 Aug 2025 05:14:42 -0700 Subject: [PATCH 4/8] fix: avoid input argument mutation --- 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: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../lib/index.js | 4 +-- .../lib/main.js | 32 +++++++++---------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js index 237b0f99d235..62a75e19b709 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js @@ -19,7 +19,7 @@ 'use strict'; /** -* Broadcast an input ndarray to a target shape keeping the specified dimensions unchanged. +* Broadcast an input ndarray to a target shape while keeping a list of specified dimensions unchanged. * * @module @stdlib/ndarray/base/broadcast-array-except-dimensions * @@ -33,7 +33,7 @@ * var shx = x.shape; * // returns [ 1, 3 ] * -* var y = broadcastArrayExceptDimensionsExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); +* var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); * // returns * * var shy = y.shape; diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js index 4b68ab0f0935..fa731060cd45 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js @@ -20,7 +20,7 @@ // MODULES // -var copy = require( '@stdlib/array/base/copy-indexed' ); +var copy = require( '@stdlib/array/base/copy' ); var ndarray = require( '@stdlib/ndarray/base/ctor' ); var getShape = require( '@stdlib/ndarray/base/shape' ); var getStrides = require( '@stdlib/ndarray/base/strides' ); @@ -29,18 +29,19 @@ var getOrder = require( '@stdlib/ndarray/base/order' ); var getDType = require( '@stdlib/ndarray/base/dtype' ); var getData = require( '@stdlib/ndarray/base/data-buffer' ); var normalizeIndices = require( '@stdlib/ndarray/base/normalize-indices' ); -var format = require( '@stdlib/string/format' ); var join = require( '@stdlib/array/base/join' ); +var zeros = require( '@stdlib/array/base/zeros' ); +var format = require( '@stdlib/string/format' ); // MAIN // /** -* Broadcasts an input ndarray to a target shape keeping the specified dimensions unchanged. +* Broadcasts an input ndarray to a target shape while keeping a list of specified dimensions unchanged. * * @param {ndarray} arr - input array * @param {NonNegativeIntegerArray} shape - desired shape -* @param {IntegerArray} [dims] - list of dimensions to exclude +* @param {IntegerArray} dims - list of dimensions to exclude from broadcasting * @throws {Error} input array cannot have more dimensions than the desired shape * @throws {Error} input array and desired shape must be broadcast compatible * @throws {RangeError} dimension indices must not exceed desired shape bounds @@ -80,7 +81,7 @@ var join = require( '@stdlib/array/base/join' ); * v = y.get( 1, 0, 2 ); * // returns 3 */ -function broadcastArrayExceptDimensions( arr, shape, dims ) { +function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable-line id-length var strides; var dim; var sh; @@ -93,26 +94,20 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { var i; var j; + shape = copy( shape ); // perform a copy to avoid unintended mutation N = shape.length; + sh = getShape( arr, false ); M = sh.length; if ( N < M ) { throw new Error( 'invalid argument. Cannot broadcast an array to a shape having fewer dimensions. Arrays can only be broadcasted to shapes having the same or more dimensions.' ); } - // Initialize a strides array... - strides = []; - for ( i = 0; i < N; i++ ) { - strides.push( 0 ); - } - // Determine the output array strides... - st = getStrides( arr, false ); + // Initialize a strides array: + strides = zeros( N ); - if ( !dims ) { - dims = [ -1 ]; - } // Verify that we've been provided a list of unique dimension indices... dl = dims.length; - dims = normalizeIndices( dims, N - 1 ); + dims = normalizeIndices( dims, N-1 ); if ( dims === null ) { throw new RangeError( format( 'invalid argument. Third argument contains an out-of-bounds dimension index. Value: [%s].', join( dims, ',' ) ) ); } @@ -121,6 +116,9 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { throw new Error( format( 'invalid argument. Third argument must contain a list of unique dimension indices. Value: [%s].', join( dims, ',' ) ) ); } di = dims.length - 1; + + // Determine the output array strides... + st = getStrides( arr, false ); for ( i = N-1; i >= 0; i-- ) { j = M - N + i; if ( di >= 0 && dims[ di ] === i ) { @@ -150,7 +148,7 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { throw new Error( format( 'invalid argument. Input array and the specified shape are broadcast incompatible. Array shape: (%s). Desired shape: (%s). Dimension: %u.', copy( sh ).join( ', ' ), copy( shape ).join( ', ' ), i ) ); } } - return ndarray( getDType( arr ), getData( arr ), copy( shape ), strides, getOffset( arr ), getOrder( arr ) ); // eslint-disable-line max-len + return ndarray( getDType( arr ), getData( arr ), shape, strides, getOffset( arr ), getOrder( arr ) ); // eslint-disable-line max-len } From 028683a01fd9c59d16b18b810b2c288308b8afc0 Mon Sep 17 00:00:00 2001 From: Muhammad Haris <101793258+headlessNode@users.noreply.github.com> Date: Tue, 2 Sep 2025 05:15:33 +0000 Subject: [PATCH 5/8] refactor: 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: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - 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 --- --- .../README.md | 23 +- .../benchmark/benchmark.js | 6 +- .../docs/repl.txt | 4 +- .../docs/types/index.d.ts | 2 +- .../docs/types/test.ts | 19 - .../test/test.js | 409 ------------------ 6 files changed, 9 insertions(+), 454 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md index cf1b8824cba0..7b89492afec2 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md @@ -42,7 +42,7 @@ limitations under the License. var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); ``` -#### broadcastArrayExceptDimensions( arr, shape\[, dims] ) +#### broadcastArrayExceptDimensions( arr, shape, dims ) Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged. @@ -54,7 +54,7 @@ var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); // returns // Perform broadcasting: -var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ] ); +var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ], [ -1 ] ); // returns var ysh = y.shape; @@ -65,24 +65,7 @@ The function accepts the following arguments: - **arr**: input ndarray. - **shape**: target shape. -- **dims**: list of dimensions which are exculded from broadcasting. Default: `[ -1 ]` (_optional_). - -To exclude specific dimensions from broadcasting, provide a `dims` parameter. - -```javascript -var array = require( '@stdlib/ndarray/array' ); - -// Create a 2x2 ndarray: -var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); -// returns - -// Perform broadcasting: -var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ], [ -2 ] ); -// returns - -var ysh = y.shape; -// returns [ 3, 2, 2 ] -``` +- **dims**: list of dimensions which are exculded from broadcasting. diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js index 1933c79e81a0..f9aad9027efc 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js @@ -59,7 +59,7 @@ bench( pkg+'::base_ndarray,2d', function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] ); + out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ], [ -1 ] ); if ( typeof out !== 'object' ) { b.fail( 'should return an object' ); } @@ -100,7 +100,7 @@ bench( pkg+'::ndarray,2d', function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] ); + out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ], [ -1 ] ); if ( typeof out !== 'object' ) { b.fail( 'should return an object' ); } @@ -147,7 +147,7 @@ bench( pkg+'::ndarray_like,2d', function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] ); + out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ], [ -2 ] ); if ( typeof out !== 'object' ) { b.fail( 'should return an object' ); } diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt index 077e2307d25e..13788aa148d7 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt @@ -1,5 +1,5 @@ -{{alias}}( arr, shape[, dims] ) +{{alias}}( arr, shape, dims ) Broadcasts an input ndarray to a target shape keeping the specified dimensions unchanged. @@ -23,7 +23,7 @@ shape: ArrayLikeObject Desired shape. - dims: Array (optional) + dims: Array List of dimensions to exclude from broadcasting. Returns diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts index fd6062082898..5afededff93e 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts @@ -75,7 +75,7 @@ import { ndarray } from '@stdlib/types/ndarray'; * v = y.get( 1, 0, 2 ); * // returns 3 */ -declare function broadcastArrayExceptDimensions( arr: ndarray, shape: ArrayLike, dims?: ArrayLike ): ndarray; +declare function broadcastArrayExceptDimensions( arr: ndarray, shape: ArrayLike, dims: ArrayLike ): ndarray; // EXPORTS // diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts index 07b82ebf48d3..ff4e5e8a8355 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts @@ -55,21 +55,11 @@ function array(): ndarray { { const x = array(); - broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); // $ExpectType ndarray broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); // $ExpectType ndarray } // The compiler throws an error if the function is not provided a first argument which is an ndarray... { - broadcastArrayExceptDimensions( '5', [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( 5, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( true, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( false, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( null, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( {}, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( [ '5' ], [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( ( x: number ): number => x, [ 2, 2, 2 ] ); // $ExpectError - broadcastArrayExceptDimensions( '5', [ 2, 2, 2 ], [ -2 ] ); // $ExpectError broadcastArrayExceptDimensions( 5, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError broadcastArrayExceptDimensions( true, [ 2, 2, 2 ], [ -2 ] ); // $ExpectError @@ -84,15 +74,6 @@ function array(): ndarray { { const x = array(); - broadcastArrayExceptDimensions( x, '5' ); // $ExpectError - broadcastArrayExceptDimensions( x, 5 ); // $ExpectError - broadcastArrayExceptDimensions( x, true ); // $ExpectError - broadcastArrayExceptDimensions( x, false ); // $ExpectError - broadcastArrayExceptDimensions( x, null ); // $ExpectError - broadcastArrayExceptDimensions( x, {} ); // $ExpectError - broadcastArrayExceptDimensions( x, [ '5' ] ); // $ExpectError - broadcastArrayExceptDimensions( x, ( x: number ): number => x ); // $ExpectError - broadcastArrayExceptDimensions( x, '5', [ -2 ] ); // $ExpectError broadcastArrayExceptDimensions( x, 5, [ -2 ] ); // $ExpectError broadcastArrayExceptDimensions( x, true, [ -2 ] ); // $ExpectError diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js index 80618a87e2c4..3f39f316d083 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js @@ -60,39 +60,6 @@ tape( 'the function throws an error if provided a desired shape which has fewer } t.end(); - function badValue( value ) { - return function badValue() { - broadcastArrayExceptDimensions( x, value ); - }; - } -}); - -tape( 'the function throws an error if provided a desired shape which has fewer dimensions than input array (dims)', function test( t ) { - var values; - var x; - var i; - - x = array({ - 'shape': [ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 ] - }); - - values = [ - [], - [ 2 ], - [ 2, 2 ], - [ 2, 2, 2 ], - [ 2, 2, 2, 2 ], - [ 2, 2, 2, 2, 2 ], - [ 2, 2, 2, 2, 2, 2 ], - [ 2, 2, 2, 2, 2, 2, 2 ], - [ 2, 2, 2, 2, 2, 2, 2, 2 ], - [ 2, 2, 2, 2, 2, 2, 2, 2, 2 ] - ]; - for ( i = 0; i < values.length; i++ ) { - t.throws( badValue( values[ i ] ), Error, 'throws an error when provided a shape with '+values[ i ].length+' dimension' ); - } - t.end(); - function badValue( value ) { return function badValue() { broadcastArrayExceptDimensions( x, value, [ -2 ] ); @@ -138,31 +105,6 @@ tape( 'the function throws an error if provided a desired shape and an input arr 'shape': [ 10, 10 ] }); - values = [ - [ 10, 20, 10 ], - [ 10, 100, 10 ] - ]; - for ( i = 0; i < values.length; i++ ) { - t.throws( badValue( values[ i ] ), Error, 'throws an error when provided shape ('+values[ i ].join( ',')+')' ); - } - t.end(); - - function badValue( value ) { - return function badValue() { - broadcastArrayExceptDimensions( x, value ); - }; - } -}); - -tape( 'the function throws an error if provided a desired shape and an input array shape are broadcast-incompatible (dims)', function test( t ) { - var values; - var x; - var i; - - x = array({ - 'shape': [ 10, 10 ] - }); - values = [ [ 10, 10, 20 ], [ 10, 100, 10 ] @@ -183,19 +125,6 @@ tape( 'the function returns a "base" ndarray instance', function test( t ) { var x; var y; - x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); - y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); - - t.notEqual( y, x, 'returns new instance' ); - t.strictEqual( y instanceof ndarray, true, 'returns expected value' ); - - t.end(); -}); - -tape( 'the function returns a "base" ndarray instance (dims)', function test( t ) { - var x; - var y; - x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); @@ -209,18 +138,6 @@ tape( 'the function returns a view over the input array data buffer', function t var x; var y; - x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); - y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ] ); - - t.strictEqual( y.data, x.data, 'returns expected value' ); - - t.end(); -}); - -tape( 'the function returns a view over the input array data buffer (dims)', function test( t ) { - var x; - var y; - x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); @@ -245,44 +162,6 @@ tape( 'the function broadcasts an input array (row-major)', function test( t ) { 'order': 'row-major' }); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (row-major, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4 ]; - x = array( data, { - 'dtype': 'generic', - 'shape': [ 2, 2 ], - 'order': 'row-major' - }); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -317,40 +196,6 @@ tape( 'the function broadcasts an input array (row-major, strides)', function te data = [ 1, 2, 3, 4 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (row-major, strides, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4 ]; - x = ndarray( 'generic', data, [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -385,40 +230,6 @@ tape( 'the function broadcasts an input array (row-major, strides)', function te data = [ 1, 2, 3, 4 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ -2, 1 ], 2, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (row-major, strides, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4 ]; - x = ndarray( 'generic', data, [ 2, 2 ], [ -2, 1 ], 2, 'row-major' ); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -453,40 +264,6 @@ tape( 'the function broadcasts an input array (row-major, non-contiguous)', func data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 5 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 7 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (row-major, non-contiguous, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; - x = ndarray( 'generic', data, [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -525,44 +302,6 @@ tape( 'the function broadcasts an input array (column-major)', function test( t 'order': 'column-major' }); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 2 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 3 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (column-major, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4 ]; - x = array( data, { - 'dtype': 'generic', - 'shape': [ 2, 2 ], - 'order': 'column-major' - }); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -601,44 +340,6 @@ tape( 'the function broadcasts an input array (same shape)', function test( t ) 'order': 'row-major' }); - expected = [ 2, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, x.get( i, 1, 0 ), 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, x.get( i, 1, 1 ), 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (same shape, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; - x = array( data, { - 'dtype': 'generic', - 'shape': [ 2, 2, 2 ], - 'order': 'row-major' - }); - expected = [ 2, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); @@ -677,44 +378,6 @@ tape( 'the function broadcasts an input array (same number of dimensions)', func 'order': 'row-major' }); - expected = [ 2, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, x.get( i, 0, 0 ), 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, x.get( i, 0, 1 ), 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (same number of dimensions, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2, 3, 4 ]; - x = array( data, { - 'dtype': 'generic', - 'shape': [ 2, 1, 2 ], - 'order': 'row-major' - }); - y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); expected = [ 2, 1, 2 ]; @@ -753,44 +416,6 @@ tape( 'the function broadcasts an input array (singleton dimension)', function t 'order': 'row-major' }); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 1 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (singleton dimension, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1, 2 ]; - x = array( data, { - 'dtype': 'generic', - 'shape': [ 1, 2 ], - 'order': 'row-major' - }); - y = broadcastArrayExceptDimensions( x, [ 5, 2, 2 ], [ -2 ] ); expected = [ 5, 1, 2 ]; @@ -825,40 +450,6 @@ tape( 'the function broadcasts an input array (0-dimensional array)', function t data = [ 1 ]; x = ndarray( 'generic', data, [], [ 0 ], 0, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected ); - - actual = y.shape; - t.deepEqual( actual, expected, 'returns expected shape' ); - - for ( i = 0; i < expected[ 0 ]; i++ ) { - v = y.get( i, 0, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,0)' ); - - v = y.get( i, 0, 1 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',0,1)' ); - - v = y.get( i, 1, 0 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,0)' ); - - v = y.get( i, 1, 1 ); - t.strictEqual( v, data[ 0 ], 'returns expected value for element ('+i+',1,1)' ); - } - t.end(); -}); - -tape( 'the function broadcasts an input array (0-dimensional array, dims)', function test( t ) { - var expected; - var actual; - var data; - var x; - var y; - var v; - var i; - - data = [ 1 ]; - x = ndarray( 'generic', data, [], [ 0 ], 0, 'row-major' ); - expected = [ 5, 2, 2 ]; y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); From 16c9908ab00555de7a0e56b7951156370df4712a Mon Sep 17 00:00:00 2001 From: Athan Date: Sat, 6 Sep 2025 03:57:54 -0700 Subject: [PATCH 6/8] fix: perform explicit copy to avoid unintended argument mutation --- 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: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../lib/main.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js index fa731060cd45..a784bfb3ed5a 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js @@ -83,6 +83,7 @@ var format = require( '@stdlib/string/format' ); */ function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable-line id-length var strides; + var idx; var dim; var sh; var st; @@ -94,10 +95,14 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable- var i; var j; - shape = copy( shape ); // perform a copy to avoid unintended mutation - N = shape.length; + // Copy input arguments to avoid unintended mutation: + shape = copy( shape ); + idx = copy( dims ); + // Resolve the shape of the input array: sh = getShape( arr, false ); + + N = shape.length; M = sh.length; if ( N < M ) { throw new Error( 'invalid argument. Cannot broadcast an array to a shape having fewer dimensions. Arrays can only be broadcasted to shapes having the same or more dimensions.' ); @@ -106,22 +111,22 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable- strides = zeros( N ); // Verify that we've been provided a list of unique dimension indices... - dl = dims.length; - dims = normalizeIndices( dims, N-1 ); - if ( dims === null ) { + dl = idx.length; + idx = normalizeIndices( idx, N-1 ); + if ( idx === null ) { throw new RangeError( format( 'invalid argument. Third argument contains an out-of-bounds dimension index. Value: [%s].', join( dims, ',' ) ) ); } - dims.sort(); - if ( dims.length !== dl ) { + idx.sort(); + if ( idx.length !== dl ) { throw new Error( format( 'invalid argument. Third argument must contain a list of unique dimension indices. Value: [%s].', join( dims, ',' ) ) ); } - di = dims.length - 1; + di = idx.length - 1; // Determine the output array strides... st = getStrides( arr, false ); for ( i = N-1; i >= 0; i-- ) { j = M - N + i; - if ( di >= 0 && dims[ di ] === i ) { + if ( di >= 0 && idx[ di ] === i ) { if ( j >= 0 ) { shape[ i ] = sh[ j ]; strides[ i ] = st[ j ]; From 4e8e2fd150da54f422db65daa3b661a75686afd3 Mon Sep 17 00:00:00 2001 From: Athan Date: Sat, 6 Sep 2025 18:05:57 -0700 Subject: [PATCH 7/8] chore: clean-up --- 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 --- --- .../README.md | 12 ++-- .../benchmark/benchmark.js | 6 +- .../docs/repl.txt | 11 +-- .../docs/types/index.d.ts | 13 ++-- .../docs/types/test.ts | 41 ++--------- .../examples/index.js | 5 +- .../lib/index.js | 5 +- .../lib/main.js | 41 ++++++----- .../package.json | 2 +- .../test/test.js | 72 ++++++++++--------- 10 files changed, 98 insertions(+), 110 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md index 7b89492afec2..f3889a4860cc 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/README.md @@ -20,7 +20,7 @@ limitations under the License. # broadcastArrayExceptDimensions -> Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged. +> Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape while keeping a list of specified dimensions unchanged. @@ -44,10 +44,11 @@ var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-ar #### broadcastArrayExceptDimensions( arr, shape, dims ) -Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged. +Broadcasts an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape while keeping a list of specified dimensions unchanged. ```javascript var array = require( '@stdlib/ndarray/array' ); +var getShape = require( '@stdlib/ndarray/shape' ); // Create a 2x2 ndarray: var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); @@ -57,7 +58,7 @@ var x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ], [ -1 ] ); // returns -var ysh = y.shape; +var ysh = getShape( y ); // returns [ 3, 2, 2 ] ``` @@ -65,7 +66,7 @@ The function accepts the following arguments: - **arr**: input ndarray. - **shape**: target shape. -- **dims**: list of dimensions which are exculded from broadcasting. +- **dims**: list of dimensions to exclude from broadcasting. Should be a list of negative integers. @@ -97,6 +98,7 @@ The function accepts the following arguments: var array = require( '@stdlib/ndarray/array' ); var numel = require( '@stdlib/ndarray/base/numel' ); var ind2sub = require( '@stdlib/ndarray/ind2sub' ); +var getShape = require( '@stdlib/ndarray/shape' ); var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); // Create a 1x3 array: @@ -108,7 +110,7 @@ var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); // returns // Retrieve the shape: -var sh = y.shape; +var sh = getShape( y ); // returns [ 2, 1, 3 ] // Retrieve the number of elements: diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js index f9aad9027efc..5b15b7e4137b 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/benchmark/benchmark.js @@ -16,6 +16,8 @@ * limitations under the License. */ +/* eslint-disable max-len */ + 'use strict'; // MODULES // @@ -26,7 +28,7 @@ var ndarrayBase = require( '@stdlib/ndarray/base/ctor' ); var ndarray = require( '@stdlib/ndarray/ctor' ); var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' ); var pkg = require( './../package.json' ).name; -var broadcastArrayExceptDimensions = require( './../lib' ); +var broadcastArrayExceptDimensions = require( './../lib' ); // eslint-disable-line id-length // MAIN // @@ -147,7 +149,7 @@ bench( pkg+'::ndarray_like,2d', function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ], [ -2 ] ); + out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ], [ -1 ] ); if ( typeof out !== 'object' ) { b.fail( 'should return an object' ); } diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt index 13788aa148d7..6d550b3d5f45 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/repl.txt @@ -1,7 +1,7 @@ {{alias}}( arr, shape, dims ) - Broadcasts an input ndarray to a target shape keeping the specified - dimensions unchanged. + Broadcasts an input ndarray to a target shape while keeping a list of + specified dimensions unchanged. The returned array is a "base" ndarray, and, thus, the returned array does not perform bounds checking or afford any of the guarantees of the non-base @@ -24,7 +24,8 @@ Desired shape. dims: Array - List of dimensions to exclude from broadcasting. + List of dimensions to exclude from broadcasting. Should be a list of + negative integers. Returns ------- @@ -35,11 +36,11 @@ -------- > var x = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2, 3 ] ] ) - > var sh = x.shape + > {{alias:@stdlib/ndarray/shape}}( x ) [ 1, 3 ] > var y = {{alias}}( x, [ 2, 2, 3 ], [ -2 ] ) - > sh = y.shape + > {{alias:@stdlib/ndarray/shape}}( y ) [ 2, 1, 3 ] > var v = y.get( 0, 0, 0 ) 1 diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts index 5afededff93e..464c34ede2b3 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts @@ -20,14 +20,15 @@ /// -import { ArrayLike } from '@stdlib/types/array'; -import { ndarray } from '@stdlib/types/ndarray'; +import { Collection } from '@stdlib/types/array'; +import { typedndarray } from '@stdlib/types/ndarray'; /** -* Broadcasts an input ndarray to a target shape keeping the specified dimension unchanged. +* Broadcasts an input ndarray to a target shape while keeping a list of specified dimensions unchanged. * * ## Notes * +* - The function expects that each index in the list of dimensions is negative in order to ensure that indices correspond to the same relative position in the output ndarray shape. For example, given an input ndarray shape `[2,X1,X2]` and a desired shape `[6,7,2,Y1,Y2]`, a list of negative dimensions `[-2,-1]` correctly maps the unchanged dimensions `X` in the input ndarray to ignored dimensions `Y` in the provided target shape. Nonnegative indices, however, afford no such mapping. For example, the list of dimensions `[1,2]` corresponds to `[X1,X2]` in the input ndarray shape, but to `[7,2]` in the target shape, which is not desired. By expecting negative indices, we avoid confusion and ensure that users always refer to dimensions relative to the last broadcasted dimension. * - The function throws an error if a provided ndarray is incompatible with a provided shape. * - The returned array is a view on the input array data buffer. The view is typically **not** contiguous. As more than one element of a returned view may refer to the same memory location, writing to the view may affect multiple elements. If you need to write to the returned array, copy the array before performing operations which may mutate elements. * - The returned array is a "base" ndarray, and, thus, the returned array does not perform bounds checking or afford any of the guarantees of the non-base ndarray constructor. The primary intent of this function is to broadcast an ndarray-like object within internal implementations and to do so with minimal overhead. @@ -35,9 +36,9 @@ import { ndarray } from '@stdlib/types/ndarray'; * * @param arr - input array * @param shape - desired shape -* @param dims - list of dimensions to exclude +* @param dims - list of dimensions to exclude from broadcasting * @throws input array cannot have more dimensions than the desired shape -* @throws input array and desired shape must be broadcast compatible +* @throws broadcasted dimensions in the input array and desired shape must be broadcast compatible * @throws dimension indices must not exceed desired shape bounds * @throws must provide unique dimension indices * @returns broadcasted array @@ -75,7 +76,7 @@ import { ndarray } from '@stdlib/types/ndarray'; * v = y.get( 1, 0, 2 ); * // returns 3 */ -declare function broadcastArrayExceptDimensions( arr: ndarray, shape: ArrayLike, dims: ArrayLike ): ndarray; +declare function broadcastArrayExceptDimensions = typedndarray>( arr: U, shape: Collection, dims: Collection ): U; // EXPORTS // diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts index ff4e5e8a8355..b1a35683fc5f 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/test.ts @@ -16,46 +16,17 @@ * limitations under the License. */ -/// - -import { ndarray } from '@stdlib/types/ndarray'; +import zeros = require( '@stdlib/ndarray/zeros' ); import broadcastArrayExceptDimensions = 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(); + const x = zeros( [ 2, 2 ] ); - broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); // $ExpectType ndarray + broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); // $ExpectType float64ndarray } // The compiler throws an error if the function is not provided a first argument which is an ndarray... @@ -72,7 +43,7 @@ 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 ] ); broadcastArrayExceptDimensions( x, '5', [ -2 ] ); // $ExpectError broadcastArrayExceptDimensions( x, 5, [ -2 ] ); // $ExpectError @@ -86,7 +57,7 @@ function array(): ndarray { // The compiler throws an error if the function is not provided a third argument which is not an array-like object containing numbers... { - const x = array(); + const x = zeros( [ 2, 2 ] ); broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], '5' ); // $ExpectError broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], 5 ); // $ExpectError @@ -99,7 +70,7 @@ 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 ] ); broadcastArrayExceptDimensions(); // $ExpectError broadcastArrayExceptDimensions( x ); // $ExpectError diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js index e47cf7dd89ff..361b04f20ee8 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/examples/index.js @@ -21,7 +21,8 @@ var array = require( '@stdlib/ndarray/array' ); var numel = require( '@stdlib/ndarray/base/numel' ); var ind2sub = require( '@stdlib/ndarray/ind2sub' ); -var broadcastArrayExceptDimensions = require( './../lib' ); +var getShape = require( '@stdlib/ndarray/shape' ); +var broadcastArrayExceptDimensions = require( './../lib' ); // eslint-disable-line id-length // Create a 1x3 array: var x = array( [ [ 1, 2, 3 ] ] ); @@ -32,7 +33,7 @@ var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); // returns // Retrieve the shape: -var sh = y.shape; +var sh = getShape( y ); // returns [ 2, 1, 3 ] // Retrieve the number of elements: diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js index 62a75e19b709..8d08dd2ee484 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/index.js @@ -25,18 +25,19 @@ * * @example * var array = require( '@stdlib/ndarray/array' ); +* var getShape = require( '@stdlib/ndarray/shape' ); * var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' ); * * var x = array( [ [ 1, 2, 3 ] ] ); * // returns * -* var shx = x.shape; +* var shx = getShape( x ); * // returns [ 1, 3 ] * * var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); * // returns * -* var shy = y.shape; +* var shy = getShape( y ); * // returns [ 2, 1, 3 ] * * var v = y.get( 0, 0, 0 ); diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js index a784bfb3ed5a..54efd3264c28 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/lib/main.js @@ -39,28 +39,33 @@ var format = require( '@stdlib/string/format' ); /** * Broadcasts an input ndarray to a target shape while keeping a list of specified dimensions unchanged. * +* ## Notes +* +* - The function expects that each index in the list of dimensions is negative in order to ensure that indices correspond to the same relative position in the output ndarray shape. For example, given an input ndarray shape `[2,X1,X2]` and a desired shape `[6,7,2,Y1,Y2]`, a list of negative dimensions `[-2,-1]` correctly maps the unchanged dimensions `X` in the input ndarray to ignored dimensions `Y` in the provided target shape. Nonnegative indices, however, afford no such mapping. For example, the list of dimensions `[1,2]` corresponds to `[X1,X2]` in the input ndarray shape, but to `[7,2]` in the target shape, which is not desired. By expecting negative indices, we avoid confusion and ensure that users always refer to dimensions relative to the last broadcasted dimension. +* * @param {ndarray} arr - input array * @param {NonNegativeIntegerArray} shape - desired shape -* @param {IntegerArray} dims - list of dimensions to exclude from broadcasting +* @param {NegativeIntegerArray} dims - list of dimensions to exclude from broadcasting * @throws {Error} input array cannot have more dimensions than the desired shape -* @throws {Error} input array and desired shape must be broadcast compatible +* @throws {Error} broadcasted dimensions in the input array and desired shape must be broadcast compatible * @throws {RangeError} dimension indices must not exceed desired shape bounds * @throws {Error} must provide unique dimension indices * @returns {ndarray} broadcasted array * * @example * var array = require( '@stdlib/ndarray/array' ); +* var getShape = require( '@stdlib/ndarray/shape' ); * * var x = array( [ [ 1, 2, 3 ] ] ); * // returns * -* var shx = x.shape; +* var shx = getShape( x ); * // returns [ 1, 3 ] * * var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); * // returns * -* var shy = y.shape; +* var shy = getShape( y ); * // returns [ 2, 1, 3 ] * * var v = y.get( 0, 0, 0 ); @@ -88,12 +93,12 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable- var sh; var st; var dl; - var di; var N; var M; var d; var i; var j; + var k; // Copy input arguments to avoid unintended mutation: shape = copy( shape ); @@ -112,32 +117,34 @@ function broadcastArrayExceptDimensions( arr, shape, dims ) { // eslint-disable- // Verify that we've been provided a list of unique dimension indices... dl = idx.length; - idx = normalizeIndices( idx, N-1 ); + idx = normalizeIndices( idx, M-1 ); if ( idx === null ) { throw new RangeError( format( 'invalid argument. Third argument contains an out-of-bounds dimension index. Value: [%s].', join( dims, ',' ) ) ); } - idx.sort(); + idx.sort(); // sort in ascending order if ( idx.length !== dl ) { throw new Error( format( 'invalid argument. Third argument must contain a list of unique dimension indices. Value: [%s].', join( dims, ',' ) ) ); } - di = idx.length - 1; + k = idx.length - 1; // Determine the output array strides... st = getStrides( arr, false ); for ( i = N-1; i >= 0; i-- ) { - j = M - N + i; - if ( di >= 0 && idx[ di ] === i ) { - if ( j >= 0 ) { - shape[ i ] = sh[ j ]; - strides[ i ] = st[ j ]; - } - di -= 1; + // Moving from right-to-left, resolve an index into the input array shape: + j = M - N + i; // M-1, M-2, M-3, ..., M-M, ..., M-N with N >= M + + // For prepended singleton dimensions, the stride is zero... + if ( j < 0 ) { continue; } - if ( j < 0 ) { - // Prepended singleton dimension; stride is zero... + // Check for a dimension being held constant... + if ( k >= 0 && idx[ k ] === j ) { + shape[ i ] = sh[ j ]; + strides[ i ] = st[ j ]; + k -= 1; continue; } + // Broadcast the current dimension... d = sh[ j ]; dim = shape[ i ]; if ( dim !== 0 && dim < d ) { diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json index 45866e8db369..629a1e62fabc 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/package.json @@ -1,7 +1,7 @@ { "name": "@stdlib/ndarray/base/broadcast-array-except-dimensions", "version": "0.0.0", - "description": "Broadcast an input ndarray to a target shape keeping the specified dimensions unchanged.", + "description": "Broadcast an input ndarray to a target shape while keeping a list of specified dimensions unchanged.", "license": "Apache-2.0", "author": { "name": "The Stdlib Authors", diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js index 3f39f316d083..4f6105650fa8 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/test/test.js @@ -23,7 +23,9 @@ var tape = require( 'tape' ); var array = require( '@stdlib/ndarray/array' ); var ndarray = require( '@stdlib/ndarray/base/ctor' ); -var broadcastArrayExceptDimensions = require( './../lib' ); +var getData = require( '@stdlib/ndarray/data-buffer' ); +var getShape = require( '@stdlib/ndarray/shape' ); +var broadcastArrayExceptDimensions = require( './../lib' ); // eslint-disable-line id-length // TESTS // @@ -34,7 +36,7 @@ tape( 'main export is a function', function test( t ) { t.end(); }); -tape( 'the function throws an error if provided a desired shape which has fewer dimensions than input array', function test( t ) { +tape( 'the function throws an error if provided a desired shape which has fewer dimensions than the input array', function test( t ) { var values; var x; var i; @@ -73,16 +75,16 @@ tape( 'the function throws an error if provided a desired shape having a dimensi var i; x = array({ - 'shape': [ 10, 10 ] + 'shape': [ 2, 10, 10 ] }); values = [ - [ 10, 10, 1 ], - [ 10, 10, 2 ], - [ 10, 10, 9 ], - [ 10, 1, 10 ], - [ 10, 2, 10 ], - [ 10, 9, 10 ] + [ 10, 10, 10, 1 ], + [ 10, 10, 10, 2 ], + [ 10, 10, 10, 9 ], + [ 10, 10, 1, 10 ], + [ 10, 10, 2, 10 ], + [ 10, 10, 9, 10 ] ]; for ( i = 0; i < values.length; i++ ) { t.throws( badValue( values[ i ] ), Error, 'throws an error when provided shape ('+values[ i ].join( ',')+')' ); @@ -102,7 +104,7 @@ tape( 'the function throws an error if provided a desired shape and an input arr var i; x = array({ - 'shape': [ 10, 10 ] + 'shape': [ 2, 10, 10 ] }); values = [ @@ -141,7 +143,7 @@ tape( 'the function returns a view over the input array data buffer', function t x = array( [ [ 1, 2 ], [ 3, 4 ] ] ); y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); - t.strictEqual( y.data, x.data, 'returns expected value' ); + t.strictEqual( getData( y ), getData( x ), 'returns expected value' ); t.end(); }); @@ -162,10 +164,10 @@ tape( 'the function broadcasts an input array (row-major)', function test( t ) { 'order': 'row-major' }); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 5, 10, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -196,10 +198,10 @@ tape( 'the function broadcasts an input array (row-major, strides)', function te data = [ 1, 2, 3, 4 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ -2, -1 ], 3, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 5, 10, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -230,10 +232,10 @@ tape( 'the function broadcasts an input array (row-major, strides)', function te data = [ 1, 2, 3, 4 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ -2, 1 ], 2, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 5, 10, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -264,10 +266,10 @@ tape( 'the function broadcasts an input array (row-major, non-contiguous)', func data = [ 1, 2, 3, 4, 5, 6, 7, 8 ]; x = ndarray( 'generic', data, [ 2, 2 ], [ 4, 2 ], 1, 'row-major' ); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 5, 10, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -302,10 +304,10 @@ tape( 'the function broadcasts an input array (column-major)', function test( t 'order': 'column-major' }); - expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 5, 10, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -340,10 +342,10 @@ tape( 'the function broadcasts an input array (same shape)', function test( t ) 'order': 'row-major' }); - expected = [ 2, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); - actual = y.shape; + actual = getShape( y ); + expected = [ 2, 2, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -379,9 +381,9 @@ tape( 'the function broadcasts an input array (same number of dimensions)', func }); y = broadcastArrayExceptDimensions( x, [ 2, 2, 2 ], [ -2 ] ); - expected = [ 2, 1, 2 ]; - actual = y.shape; + actual = getShape( y ); + expected = [ 2, 1, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -417,9 +419,9 @@ tape( 'the function broadcasts an input array (singleton dimension)', function t }); y = broadcastArrayExceptDimensions( x, [ 5, 2, 2 ], [ -2 ] ); - expected = [ 5, 1, 2 ]; - actual = y.shape; + actual = getShape( y ); + expected = [ 5, 1, 2 ]; t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { @@ -451,9 +453,9 @@ tape( 'the function broadcasts an input array (0-dimensional array)', function t x = ndarray( 'generic', data, [], [ 0 ], 0, 'row-major' ); expected = [ 5, 2, 2 ]; - y = broadcastArrayExceptDimensions( x, expected, [ -2 ] ); + y = broadcastArrayExceptDimensions( x, expected, [] ); - actual = y.shape; + actual = getShape( y ); t.deepEqual( actual, expected, 'returns expected shape' ); for ( i = 0; i < expected[ 0 ]; i++ ) { From 31ff02ccfafd10734e1c1b90b88b6978bd9d8a85 Mon Sep 17 00:00:00 2001 From: Athan Date: Sat, 6 Sep 2025 18:11:23 -0700 Subject: [PATCH 8/8] docs: update example --- 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: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: na - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../broadcast-array-except-dimensions/docs/types/index.d.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts index 464c34ede2b3..36e4212a829e 100644 --- a/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/ndarray/base/broadcast-array-except-dimensions/docs/types/index.d.ts @@ -45,17 +45,18 @@ import { typedndarray } from '@stdlib/types/ndarray'; * * @example * var array = require( '@stdlib/ndarray/array' ); +* var getShape = require( '@stdlib/ndarray/shape' ); * * var x = array( [ [ 1, 2, 3 ] ] ); * // returns * -* var shx = x.shape; +* var shx = getShape( x ); * // returns [ 1, 3 ] * * var y = broadcastArrayExceptDimensionsExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] ); * // returns * -* var shy = y.shape; +* var shy = getShape( y ); * // returns [ 2, 1, 3 ] * * var v = y.get( 0, 0, 0 );