Skip to content

Commit 3cb7288

Browse files
committed
Auto-generated commit
1 parent 055a5c2 commit 3cb7288

File tree

11 files changed

+1043
-0
lines changed

11 files changed

+1043
-0
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
### Features
1212

13+
- [`f40ccb7`](https://github.com/stdlib-js/stdlib/commit/f40ccb75929e92538b8c366145589addccdaafbe) - add `ndarray/base/ternary-loop-interchange-order` [(#9499)](https://github.com/stdlib-js/stdlib/pull/9499)
1314
- [`1f79854`](https://github.com/stdlib-js/stdlib/commit/1f798549409c47de0261c5396dccf64012e54a9c) - add `ndarray/base/ternary-tiling-block-size` [(#9495)](https://github.com/stdlib-js/stdlib/pull/9495)
1415
- [`327cda9`](https://github.com/stdlib-js/stdlib/commit/327cda9b2dda086b20da9ce256df388573486946) - update `ndarray` TypeScript declarations [(#9508)](https://github.com/stdlib-js/stdlib/pull/9508)
1516
- [`a7cbc8d`](https://github.com/stdlib-js/stdlib/commit/a7cbc8dbdbd69453891b1d5ffc1fcca9126910e2) - move optional argument to options object in `ndarray/concat` [(#9480)](https://github.com/stdlib-js/stdlib/pull/9480)
@@ -688,6 +689,7 @@ A total of 38 issues were closed in this release:
688689

689690
<details>
690691

692+
- [`f40ccb7`](https://github.com/stdlib-js/stdlib/commit/f40ccb75929e92538b8c366145589addccdaafbe) - **feat:** add `ndarray/base/ternary-loop-interchange-order` [(#9499)](https://github.com/stdlib-js/stdlib/pull/9499) _(by Muhammad Haris, Athan Reines)_
691693
- [`1f79854`](https://github.com/stdlib-js/stdlib/commit/1f798549409c47de0261c5396dccf64012e54a9c) - **feat:** add `ndarray/base/ternary-tiling-block-size` [(#9495)](https://github.com/stdlib-js/stdlib/pull/9495) _(by Muhammad Haris, Athan Reines)_
692694
- [`327cda9`](https://github.com/stdlib-js/stdlib/commit/327cda9b2dda086b20da9ce256df388573486946) - **feat:** update `ndarray` TypeScript declarations [(#9508)](https://github.com/stdlib-js/stdlib/pull/9508) _(by stdlib-bot)_
693695
- [`873beeb`](https://github.com/stdlib-js/stdlib/commit/873beeb4042c9ada02dff4c40ec0de82887faa17) - **chore:** remove square bracket and add private annotation _(by Philipp Burckhardt)_
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2026 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+
# ternaryLoopOrder
22+
23+
> Reorder ndarray dimensions and associated strides for loop interchange.
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+
```javascript
40+
var ternaryLoopOrder = require( '@stdlib/ndarray/base/binary-loop-interchange-order' );
41+
```
42+
43+
#### ternaryLoopOrder( shape, stridesW, stridesX, stridesY, stridesZ )
44+
45+
Reorders [ndarray][@stdlib/ndarray/ctor] dimensions and associated strides for [loop interchange][loop-interchange].
46+
47+
```javascript
48+
// Define an array shape:
49+
var shape = [ 2, 2 ];
50+
51+
// Define the strides for the input arrays:
52+
var stridesW = [ 2, 1 ]; // row-major
53+
var stridesX = [ 4, 2 ]; // row-major
54+
var stridesY = [ 1, 2 ]; // column-major
55+
56+
// Define the strides for the output array:
57+
var stridesZ = [ 1, 2 ]; // column-major
58+
59+
// Resolve the loop interchange order:
60+
var o = ternaryLoopOrder( shape, stridesW, stridesX, stridesY, stridesZ );
61+
// returns {...}
62+
```
63+
64+
The function returns an object having the following properties:
65+
66+
- **sh**: ordered dimensions.
67+
- **sw**: first input array strides sorted in loop order.
68+
- **sx**: second input array strides sorted in loop order.
69+
- **sy**: third input array strides sorted in loop order.
70+
- **sz**: output array strides sorted in loop order.
71+
72+
For all returned arrays, the first element corresponds to the innermost loop, and the last element corresponds to the outermost loop.
73+
74+
</section>
75+
76+
<!-- /.usage -->
77+
78+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
79+
80+
<section class="notes">
81+
82+
## Notes
83+
84+
- When iterating over the elements of a multi-dimensional array, accessing elements which are closer in memory can improve performance. To this end, [loop interchange][loop-interchange] is a technique used in [loop nest optimization][loop-nest-optimization] to improve locality of reference and take advantage of CPU cache.
85+
86+
The purpose of this function is to order [ndarray][@stdlib/ndarray/ctor] dimensions according to the magnitude of array strides. By using the ordered dimensions and associated strides, one can construct nested loops (one for each dimension) such that the innermost loop iterates over the dimension in which array elements are closest in memory and the outermost loop iterates over the dimension in which array elements are farthest apart in memory. As a consequence, element iteration is optimized to minimize cache misses and ensure locality of reference.
87+
88+
- Cache performance may be degraded if the layout order (i.e., row-major or column-major) differs for the input and output [ndarrays][@stdlib/ndarray/ctor]. This function is intended to optimize cache performance for the most common layout order. Accordingly, if the output [ndarray][@stdlib/ndarray/ctor] has a different layout order (e.g., if the input [ndarrays][@stdlib/ndarray/ctor] are row-major and the output [ndarray][@stdlib/ndarray/ctor] is column-major), cache misses are likely for the output [ndarray][@stdlib/ndarray/ctor]. In general, to ensure best performance, input and output [ndarrays][@stdlib/ndarray/ctor] should have the same layout order.
89+
90+
- The function assumes that the input and output [ndarrays][@stdlib/ndarray/ctor] have the same shape. Hence, loop interchange order should only be determined **after** broadcasting.
91+
92+
</section>
93+
94+
<!-- /.notes -->
95+
96+
<!-- Package usage examples. -->
97+
98+
<section class="examples">
99+
100+
## Examples
101+
102+
<!-- eslint-disable max-len -->
103+
104+
<!-- eslint no-undef: "error" -->
105+
106+
```javascript
107+
var array = require( '@stdlib/ndarray/array' );
108+
var getShape = require( '@stdlib/ndarray/shape' );
109+
var getStrides = require( '@stdlib/ndarray/strides' );
110+
var ternaryLoopOrder = require( '@stdlib/ndarray/base/binary-loop-interchange-order' );
111+
112+
// Create ndarrays:
113+
var w = array( [ [ 1, 2 ], [ 3, 4 ] ] );
114+
var x = array( [ [ 5, 6 ], [ 7, 8 ] ] );
115+
var y = array( [ [ 9, 10 ], [ 11, 12 ] ] );
116+
var z = array( [ [ 0, 0 ], [ 0, 0 ] ] );
117+
118+
// Resolve loop interchange data:
119+
var o = ternaryLoopOrder( getShape( w ), getStrides( w ), getStrides( x ), getStrides( y ), getStrides( z ) );
120+
// returns {...}
121+
122+
console.log( o );
123+
```
124+
125+
</section>
126+
127+
<!-- /.examples -->
128+
129+
<!-- 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. -->
130+
131+
<section class="references">
132+
133+
</section>
134+
135+
<!-- /.references -->
136+
137+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
138+
139+
<section class="related">
140+
141+
</section>
142+
143+
<!-- /.related -->
144+
145+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
146+
147+
<section class="links">
148+
149+
[loop-interchange]: https://en.wikipedia.org/wiki/Loop_interchange
150+
151+
[loop-nest-optimization]: https://en.wikipedia.org/wiki/Loop_nest_optimization
152+
153+
[@stdlib/ndarray/ctor]: https://github.com/stdlib-js/ndarray/tree/main/ctor
154+
155+
</section>
156+
157+
<!-- /.links -->
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2026 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 isArray = require( '@stdlib/assert/is-array' );
25+
var shape2strides = require( './../../../base/shape2strides' );
26+
var pkg = require( './../package.json' ).name;
27+
var ternaryLoopOrder = require( './../lib' );
28+
29+
30+
// MAIN //
31+
32+
bench( pkg+'::row-major', function benchmark( b ) {
33+
var strides;
34+
var factors;
35+
var shape;
36+
var out;
37+
var i;
38+
39+
shape = [ 10, 10, 10 ];
40+
strides = shape2strides( shape, 'row-major' );
41+
factors = [
42+
-1,
43+
1
44+
];
45+
46+
b.tic();
47+
for ( i = 0; i < b.iterations; i++ ) {
48+
strides[ i%shape.length ] *= factors[ i%factors.length ];
49+
out = ternaryLoopOrder( shape, strides, strides, strides, strides );
50+
if ( typeof out !== 'object' ) {
51+
b.fail( 'should return an object' );
52+
}
53+
}
54+
b.toc();
55+
if ( !isArray( out.sh ) || !isArray( out.sx ) || !isArray( out.sy ) || !isArray( out.sz ) ) { // eslint-disable-line max-len
56+
b.fail( 'should return an array' );
57+
}
58+
b.pass( 'benchmark finished' );
59+
b.end();
60+
});
61+
62+
bench( pkg+'::column-major', function benchmark( b ) {
63+
var strides;
64+
var factors;
65+
var shape;
66+
var out;
67+
var i;
68+
69+
shape = [ 10, 10, 10 ];
70+
strides = shape2strides( shape, 'column-major' );
71+
factors = [
72+
-1,
73+
1
74+
];
75+
76+
b.tic();
77+
for ( i = 0; i < b.iterations; i++ ) {
78+
strides[ i%shape.length ] *= factors[ i%factors.length ];
79+
out = ternaryLoopOrder( shape, strides, strides, strides, strides );
80+
if ( typeof out !== 'object' ) {
81+
b.fail( 'should return an object' );
82+
}
83+
}
84+
b.toc();
85+
if ( !isArray( out.sh ) || !isArray( out.sx ) || !isArray( out.sy ) || !isArray( out.sz ) ) { // eslint-disable-line max-len
86+
b.fail( 'should return an array' );
87+
}
88+
b.pass( 'benchmark finished' );
89+
b.end();
90+
});
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
{{alias}}( shape, stridesW, stridesX, stridesY, stridesZ )
3+
Reorders ndarray dimensions and associated strides for loop interchange.
4+
5+
The function returns an object having the following properties:
6+
7+
- sh: ordered dimensions.
8+
- sw: first input array strides sorted in loop order.
9+
- sx: second input array strides sorted in loop order.
10+
- sy: third input array strides sorted in loop order.
11+
- sz: output array strides sorted in loop order.
12+
13+
For all returned arrays, the first element corresponds to the innermost
14+
loop, and the last element corresponds to the outermost loop.
15+
16+
The function assumes that the input and output ndarrays have the same shape.
17+
Hence, loop interchange order should only be determined after broadcasting.
18+
19+
Parameters
20+
----------
21+
shape: ArrayLikeObject<integer>
22+
Array dimensions.
23+
24+
stridesW: ArrayLikeObject<integer>
25+
First input array strides.
26+
27+
stridesX: ArrayLikeObject<integer>
28+
Second input array strides.
29+
30+
stridesY: ArrayLikeObject<integer>
31+
Third input array strides.
32+
33+
stridesZ: ArrayLikeObject<integer>
34+
Output array strides.
35+
36+
Returns
37+
-------
38+
out: Object
39+
Loop interchange data.
40+
41+
out.sh: Array<integer>
42+
Ordered dimensions.
43+
44+
out.sw: Array<integer>
45+
First input array strides sorted in loop order.
46+
47+
out.sx: Array<integer>
48+
Second input array strides sorted in loop order.
49+
50+
out.sy: Array<integer>
51+
Third input array strides sorted in loop order.
52+
53+
out.sz: Array<integer>
54+
Output array strides sorted in loop order.
55+
56+
Examples
57+
--------
58+
> var w = {{alias:@stdlib/ndarray/array}}( [ [ 1, 2 ], [ 3, 4 ] ] );
59+
> var x = {{alias:@stdlib/ndarray/array}}( [ [ 5, 6 ], [ 7, 8 ] ] );
60+
> var y = {{alias:@stdlib/ndarray/array}}( [ [ 9, 10 ], [ 11, 12 ] ] );
61+
> var z = {{alias:@stdlib/ndarray/array}}( [ [ 0, 0 ], [ 0, 0 ] ] );
62+
> var o = {{alias}}( w.shape, w.strides, x.strides, y.strides, z.strides )
63+
{...}
64+
65+
See Also
66+
--------
67+

0 commit comments

Comments
 (0)