Skip to content

Commit c1747c0

Browse files
committed
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 ---
1 parent 566c748 commit c1747c0

File tree

10 files changed

+1831
-0
lines changed

10 files changed

+1831
-0
lines changed
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2025 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# broadcastArrayExceptDimensions
22+
23+
> Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
</section>
30+
31+
<!-- /.intro -->
32+
33+
<!-- Package usage documentation. -->
34+
35+
<section class="usage">
36+
37+
## Usage
38+
39+
<!-- eslint-disable id-length -->
40+
41+
```javascript
42+
var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' );
43+
```
44+
45+
#### broadcastArrayExceptDimensions( arr, shape\[, dims] )
46+
47+
Broadcast an input [ndarray][@stdlib/ndarray/base/ctor] to a target shape keeping the specified dimensions unchanged.
48+
49+
```javascript
50+
var array = require( '@stdlib/ndarray/array' );
51+
52+
// Create a 2x2 ndarray:
53+
var x = array( [ [ 1, 2 ], [ 3, 4 ] ] );
54+
// returns <ndarray>
55+
56+
// Perform broadcasting:
57+
var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ] );
58+
// returns <ndarray>
59+
60+
var ysh = y.shape;
61+
// returns [ 3, 2, 2 ]
62+
```
63+
64+
The function accepts the following arguments:
65+
66+
- **arr**: input ndarray.
67+
- **shape**: target shape.
68+
- **dims**: list of dimensions which are exculded from broadcasting. Default: `[ -1 ]` (_optional_).
69+
70+
To exclude specific dimensions from broadcasting, provide a `dims` parameter.
71+
72+
```javascript
73+
var array = require( '@stdlib/ndarray/array' );
74+
75+
// Create a 2x2 ndarray:
76+
var x = array( [ [ 1, 2 ], [ 3, 4 ] ] );
77+
// returns <ndarray>
78+
79+
// Perform broadcasting:
80+
var y = broadcastArrayExceptDimensions( x, [ 3, 2, 2 ], [ -2 ] );
81+
// returns <ndarray>
82+
83+
var ysh = y.shape;
84+
// returns [ 3, 2, 2 ]
85+
```
86+
87+
</section>
88+
89+
<!-- /.usage -->
90+
91+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
92+
93+
<section class="notes">
94+
95+
## Notes
96+
97+
- The function throws an error if a provided [ndarray][@stdlib/ndarray/base/ctor] is [incompatible][@stdlib/ndarray/base/broadcast-shapes] with a provided shape.
98+
- 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.
99+
- 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.
100+
101+
</section>
102+
103+
<!-- /.notes -->
104+
105+
<!-- Package usage examples. -->
106+
107+
<section class="examples">
108+
109+
## Examples
110+
111+
<!-- eslint no-undef: "error" -->
112+
113+
```javascript
114+
var array = require( '@stdlib/ndarray/array' );
115+
var numel = require( '@stdlib/ndarray/base/numel' );
116+
var ind2sub = require( '@stdlib/ndarray/ind2sub' );
117+
var broadcastArrayExceptDimensions = require( '@stdlib/ndarray/base/broadcast-array-except-dimensions' );
118+
119+
// Create a 1x3 array:
120+
var x = array( [ [ 1, 2, 3 ] ] );
121+
// returns <ndarray>
122+
123+
// Broadcast the array to 3x2x2:
124+
var y = broadcastArrayExceptDimensions( x, [ 2, 2, 3 ], [ -2 ] );
125+
// returns <ndarray>
126+
127+
// Retrieve the shape:
128+
var sh = y.shape;
129+
// returns [ 2, 1, 3 ]
130+
131+
// Retrieve the number of elements:
132+
var N = numel( sh );
133+
134+
// Loop through the array elements...
135+
var sub;
136+
var v;
137+
var i;
138+
for ( i = 0; i < N; i++ ) {
139+
v = y.iget( i );
140+
sub = ind2sub( sh, i );
141+
console.log( 'Y[%s] = %d', sub.join( ', ' ), v );
142+
}
143+
```
144+
145+
</section>
146+
147+
<!-- /.examples -->
148+
149+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
150+
151+
<section class="references">
152+
153+
</section>
154+
155+
<!-- /.references -->
156+
157+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
158+
159+
<section class="related">
160+
161+
</section>
162+
163+
<!-- /.related -->
164+
165+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
166+
167+
<section class="links">
168+
169+
[@stdlib/ndarray/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/ctor
170+
171+
[@stdlib/ndarray/base/ctor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/ctor
172+
173+
[@stdlib/ndarray/base/broadcast-shapes]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/ndarray/base/broadcast-shapes
174+
175+
</section>
176+
177+
<!-- /.links -->
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var Float64Array = require( '@stdlib/array/float64' );
25+
var ndarrayBase = require( '@stdlib/ndarray/base/ctor' );
26+
var ndarray = require( '@stdlib/ndarray/ctor' );
27+
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
28+
var pkg = require( './../package.json' ).name;
29+
var broadcastArrayExceptDimensions = require( './../lib' );
30+
31+
32+
// MAIN //
33+
34+
bench( pkg+'::base_ndarray,2d', function benchmark( b ) {
35+
var strides;
36+
var values;
37+
var buffer;
38+
var offset;
39+
var dtype;
40+
var shape;
41+
var order;
42+
var out;
43+
var i;
44+
45+
dtype = 'float64';
46+
buffer = new Float64Array( 4 );
47+
shape = [ 2, 2 ];
48+
strides = [ 2, 1 ];
49+
offset = 0;
50+
order = 'row-major';
51+
52+
values = [
53+
ndarrayBase( dtype, buffer, shape, strides, offset, order ),
54+
ndarrayBase( dtype, buffer, shape, strides, offset, order ),
55+
ndarrayBase( dtype, buffer, shape, strides, offset, order ),
56+
ndarrayBase( dtype, buffer, shape, strides, offset, order ),
57+
ndarrayBase( dtype, buffer, shape, strides, offset, order )
58+
];
59+
60+
b.tic();
61+
for ( i = 0; i < b.iterations; i++ ) {
62+
out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] );
63+
if ( typeof out !== 'object' ) {
64+
b.fail( 'should return an object' );
65+
}
66+
}
67+
b.toc();
68+
if ( !isndarrayLike( out ) ) {
69+
b.fail( 'should return an ndarray' );
70+
}
71+
b.pass( 'benchmark finished' );
72+
b.end();
73+
});
74+
75+
bench( pkg+'::ndarray,2d', function benchmark( b ) {
76+
var strides;
77+
var values;
78+
var buffer;
79+
var offset;
80+
var dtype;
81+
var shape;
82+
var order;
83+
var out;
84+
var i;
85+
86+
dtype = 'float64';
87+
buffer = new Float64Array( 4 );
88+
shape = [ 2, 2 ];
89+
strides = [ 2, 1 ];
90+
offset = 0;
91+
order = 'row-major';
92+
93+
values = [
94+
ndarray( dtype, buffer, shape, strides, offset, order ),
95+
ndarray( dtype, buffer, shape, strides, offset, order ),
96+
ndarray( dtype, buffer, shape, strides, offset, order ),
97+
ndarray( dtype, buffer, shape, strides, offset, order ),
98+
ndarray( dtype, buffer, shape, strides, offset, order )
99+
];
100+
101+
b.tic();
102+
for ( i = 0; i < b.iterations; i++ ) {
103+
out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] );
104+
if ( typeof out !== 'object' ) {
105+
b.fail( 'should return an object' );
106+
}
107+
}
108+
b.toc();
109+
if ( !isndarrayLike( out ) ) {
110+
b.fail( 'should return an ndarray' );
111+
}
112+
b.pass( 'benchmark finished' );
113+
b.end();
114+
});
115+
116+
bench( pkg+'::ndarray_like,2d', function benchmark( b ) {
117+
var strides;
118+
var values;
119+
var buffer;
120+
var offset;
121+
var dtype;
122+
var shape;
123+
var order;
124+
var out;
125+
var obj;
126+
var i;
127+
128+
dtype = 'float64';
129+
buffer = new Float64Array( 4 );
130+
shape = [ 2, 2 ];
131+
strides = [ 2, 1 ];
132+
offset = 0;
133+
order = 'row-major';
134+
135+
values = [];
136+
for ( i = 0; i < 5; i++ ) {
137+
obj = {
138+
'dtype': dtype,
139+
'data': buffer,
140+
'shape': shape,
141+
'strides': strides,
142+
'offset': offset,
143+
'order': order
144+
};
145+
values.push( obj );
146+
}
147+
148+
b.tic();
149+
for ( i = 0; i < b.iterations; i++ ) {
150+
out = broadcastArrayExceptDimensions( values[ i%values.length ], [ 2, 2, 2 ] );
151+
if ( typeof out !== 'object' ) {
152+
b.fail( 'should return an object' );
153+
}
154+
}
155+
b.toc();
156+
if ( !isndarrayLike( out ) ) {
157+
b.fail( 'should return an ndarray' );
158+
}
159+
b.pass( 'benchmark finished' );
160+
b.end();
161+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
{{alias}}( arr, shape[, dims] )
3+
Broadcasts an input ndarray to a target shape keeping the specified
4+
dimensions unchanged.
5+
6+
The returned array is a "base" ndarray, and, thus, the returned array does
7+
not perform bounds checking or afford any of the guarantees of the non-base
8+
ndarray constructor. The primary intent of this function is to broadcast an
9+
ndarray-like object within internal implementations and to do so with
10+
minimal overhead.
11+
12+
The function always returns a new ndarray instance even if the input ndarray
13+
shape and the desired shape are the same.
14+
15+
The function throws an error if a provided ndarray is incompatible with a
16+
provided shape.
17+
18+
Parameters
19+
----------
20+
arr: ndarray
21+
Input array.
22+
23+
shape: ArrayLikeObject
24+
Desired shape.
25+
26+
dims: Array<integer> (optional)
27+
List of dimensions to exclude from broadcasting.
28+
29+
Returns
30+
-------
31+
out: ndarray
32+
Broadcasted array.
33+
34+
Examples
35+
--------
36+
> var x = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2, 3 ] ] )
37+
<ndarray>
38+
> var sh = x.shape
39+
[ 1, 3 ]
40+
> var y = {{alias}}( x, [ 2, 2, 3 ], [ -2 ] )
41+
<ndarray>
42+
> sh = y.shape
43+
[ 2, 1, 3 ]
44+
> var v = y.get( 0, 0, 0 )
45+
1
46+
> v = y.get( 0, 0, 1 )
47+
2
48+
> v = y.get( 0, 0, 2 )
49+
3
50+
> v = y.get( 1, 0, 0 )
51+
1
52+
> v = y.get( 1, 0, 1 )
53+
2
54+
> v = y.get( 1, 0, 2 )
55+
3
56+
57+
See Also
58+
--------

0 commit comments

Comments
 (0)