Skip to content

Commit a18a916

Browse files
committed
feat: add 2d accessors kernel
--- 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 ---
1 parent 18b91ff commit a18a916

File tree

1 file changed

+206
-0
lines changed

1 file changed

+206
-0
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
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 isRowMajor = require( '@stdlib/ndarray/base/assert/is-row-major-string' );
24+
25+
26+
// MAIN //
27+
28+
/**
29+
* Applies a binary callback to elements in two-dimensional input ndarrays and assigns results to elements in an equivalently shaped output ndarray.
30+
*
31+
* @private
32+
* @param {Object} x - object containing input ndarray meta data
33+
* @param {string} x.dtype - data type
34+
* @param {Collection} x.data - data buffer
35+
* @param {NonNegativeIntegerArray} x.shape - dimensions
36+
* @param {IntegerArray} x.strides - stride lengths
37+
* @param {NonNegativeInteger} x.offset - index offset
38+
* @param {string} x.order - specifies whether `x` is row-major (C-style) or column-major (Fortran-style)
39+
* @param {Array<Function>} x.accessors - data buffer accessors
40+
* @param {Object} y - object containing input ndarray meta data
41+
* @param {string} y.dtype - data type
42+
* @param {Collection} y.data - data buffer
43+
* @param {NonNegativeIntegerArray} y.shape - dimensions
44+
* @param {IntegerArray} y.strides - stride lengths
45+
* @param {NonNegativeInteger} y.offset - index offset
46+
* @param {string} y.order - specifies whether `y` is row-major (C-style) or column-major (Fortran-style)
47+
* @param {Array<Function>} y.accessors - data buffer accessors
48+
* @param {Object} z - object containing output ndarray meta data
49+
* @param {string} z.dtype - data type
50+
* @param {Collection} z.data - data buffer
51+
* @param {NonNegativeIntegerArray} z.shape - dimensions
52+
* @param {IntegerArray} z.strides - stride lengths
53+
* @param {NonNegativeInteger} z.offset - index offset
54+
* @param {string} z.order - specifies whether `z` is row-major (C-style) or column-major (Fortran-style)
55+
* @param {Array<Function>} z.accessors - data buffer accessors
56+
* @param {Callback} fcn - binary callback
57+
* @returns {void}
58+
*
59+
* @example
60+
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
61+
* var accessors = require( '@stdlib/array/base/accessors' );
62+
* var copy = require( '@stdlib/array/base/copy' );
63+
*
64+
* function fcn( x, y ) {
65+
* return x + y;
66+
* }
67+
*
68+
* // Create data buffers:
69+
* var xbuf = toAccessorArray( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0 ] );
70+
* var ybuf = toAccessorArray( [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ] );
71+
* var zbuf = toAccessorArray( [ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] );
72+
*
73+
* // Define the shape of the input and output arrays:
74+
* var shape = [ 6, 2 ];
75+
*
76+
* // Define the array strides:
77+
* var sx = [ 2, 1 ];
78+
* var sy = [ 2, 1 ];
79+
* var sz = [ 2, 1 ];
80+
*
81+
* // Define the index offsets:
82+
* var ox = 0;
83+
* var oy = 0;
84+
* var oz = 0;
85+
*
86+
* // Create the input and output ndarray-like objects:
87+
* var x = {
88+
* 'dtype': 'generic',
89+
* 'data': xbuf,
90+
* 'shape': shape,
91+
* 'strides': sx,
92+
* 'offset': ox,
93+
* 'order': 'row-major',
94+
* 'accessors': accessors( xbuf ).accessors
95+
* };
96+
* var y = {
97+
* 'dtype': 'generic',
98+
* 'data': ybuf,
99+
* 'shape': shape,
100+
* 'strides': sy,
101+
* 'offset': oy,
102+
* 'order': 'row-major',
103+
* 'accessors': accessors( ybuf ).accessors
104+
* };
105+
* var z = {
106+
* 'dtype': 'generic',
107+
* 'data': zbuf,
108+
* 'shape': shape,
109+
* 'strides': sz,
110+
* 'offset': oz,
111+
* 'order': 'row-major',
112+
* 'accessors': accessors( zbuf ).accessors
113+
* };
114+
*
115+
* // Apply the binary function:
116+
* binary2d( x, y, z, fcn );
117+
*
118+
* console.log( copy( z.data ) );
119+
* // => [ 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0 ]
120+
*/
121+
function binary2d( x, y, z, fcn ) {
122+
var xbuf;
123+
var ybuf;
124+
var zbuf;
125+
var xget;
126+
var yget;
127+
var zset;
128+
var dx0;
129+
var dx1;
130+
var dy0;
131+
var dy1;
132+
var dz0;
133+
var dz1;
134+
var sh;
135+
var S0;
136+
var S1;
137+
var sx;
138+
var sy;
139+
var sz;
140+
var ix;
141+
var iy;
142+
var iz;
143+
var i0;
144+
var i1;
145+
146+
// Note on variable naming convention: S#, dx#, dy#, dz#, i# where # corresponds to the loop number, with `0` being the innermost loop...
147+
148+
// Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments...
149+
sh = x.shape;
150+
sx = x.strides;
151+
sy = y.strides;
152+
sz = z.strides;
153+
if ( isRowMajor( x.order ) ) {
154+
// For row-major ndarrays, the last dimensions have the fastest changing indices...
155+
S0 = sh[ 1 ];
156+
S1 = sh[ 0 ];
157+
dx0 = sx[ 1 ]; // offset increment for innermost loop
158+
dx1 = sx[ 0 ] - ( S0*sx[1] ); // offset increment for outermost loop
159+
dy0 = sy[ 1 ];
160+
dy1 = sy[ 0 ] - ( S0*sy[1] );
161+
dz0 = sz[ 1 ];
162+
dz1 = sz[ 0 ] - ( S0*sz[1] );
163+
} else { // order === 'column-major'
164+
// For column-major ndarrays, the first dimensions have the fastest changing indices...
165+
S0 = sh[ 0 ];
166+
S1 = sh[ 1 ];
167+
dx0 = sx[ 0 ]; // offset increment for innermost loop
168+
dx1 = sx[ 1 ] - ( S0*sx[0] ); // offset increment for outermost loop
169+
dy0 = sy[ 0 ];
170+
dy1 = sy[ 1 ] - ( S0*sy[0] );
171+
dz0 = sz[ 0 ];
172+
dz1 = sz[ 1 ] - ( S0*sz[0] );
173+
}
174+
// Set the pointers to the first indexed elements in the respective ndarrays...
175+
ix = x.offset;
176+
iy = y.offset;
177+
iz = z.offset;
178+
179+
// Cache references to the input and output ndarray buffers...
180+
xbuf = x.data;
181+
ybuf = y.data;
182+
zbuf = z.data;
183+
184+
// Cache accessors:
185+
xget = x.accessors[ 0 ];
186+
yget = y.accessors[ 0 ];
187+
zset = z.accessors[ 1 ];
188+
189+
// Iterate over the ndarray dimensions...
190+
for ( i1 = 0; i1 < S1; i1++ ) {
191+
for ( i0 = 0; i0 < S0; i0++ ) {
192+
zset( zbuf, iz, fcn( xget( xbuf, ix ), yget( ybuf, iy ) ) );
193+
ix += dx0;
194+
iy += dy0;
195+
iz += dz0;
196+
}
197+
ix += dx1;
198+
iy += dy1;
199+
iz += dz1;
200+
}
201+
}
202+
203+
204+
// EXPORTS //
205+
206+
module.exports = binary2d;

0 commit comments

Comments
 (0)