Skip to content

Commit aad25b8

Browse files
committed
Add a utility to create a strided array function interface which accepts a callback function and performs multiple dispatch
1 parent a7df21a commit aad25b8

File tree

13 files changed

+5559
-0
lines changed

13 files changed

+5559
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2022 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+
# dispatchBy
22+
23+
> Create a strided array function interface which accepts a callback function and performs multiple dispatch.
24+
25+
<section class="intro">
26+
27+
</section>
28+
29+
<!-- /.intro -->
30+
31+
<section class="usage">
32+
33+
## Usage
34+
35+
```javascript
36+
var dispatchBy = require( '@stdlib/strided/dispatch-by' );
37+
```
38+
39+
#### dispatchBy( fcns, types, data, nargs, nin, nout )
40+
41+
Returns a strided array function interface which accepts a callback function and performs multiple dispatch.
42+
43+
<!-- eslint-disable array-element-newline -->
44+
45+
```javascript
46+
var unaryBy = require( '@stdlib/strided/base/unary-by' );
47+
var Float64Array = require( '@stdlib/array/float64' );
48+
var Float32Array = require( '@stdlib/array/float32' );
49+
50+
function foo( x ) {
51+
return x * 10.0;
52+
}
53+
54+
function bar( x ) {
55+
return x * 5.0;
56+
}
57+
58+
// Define a list of strided array functions for applying a unary callback:
59+
var fcns = [
60+
unaryBy,
61+
unaryBy
62+
];
63+
64+
// Define a one-dimensional list of input and output array types:
65+
var types = [
66+
'float64', 'float64', // input, output
67+
'float32', 'float32' // input, output
68+
];
69+
70+
// Define a list of callbacks which should be applied based on the provided array types:
71+
var data = [
72+
foo,
73+
bar
74+
];
75+
76+
// Define the total number of input arguments:
77+
var nargs = 8; // N + input_array_dtype + input_array + input_array_stride + output_array_dtype + output_array + output_array_stride + callback
78+
79+
// Define the number of input strided arrays:
80+
var nin = 1;
81+
82+
// Define the number of output strided arrays:
83+
var nout = 1;
84+
85+
// Create a strided array function interface:
86+
var strided = dispatchBy( fcns, types, data, nargs, nin, nout );
87+
88+
// ...
89+
90+
function accessor( v ) {
91+
return v * 2.0;
92+
}
93+
94+
var x = new Float64Array( [ 1.0, 2.0, 3.0 ] );
95+
var y = new Float64Array( x.length );
96+
97+
strided( x.length, 'float64', x, 1, 'float64', y, 1, accessor );
98+
// y => <Float64Array>[ 20.0, 40.0, 60.0 ]
99+
100+
x = new Float32Array( [ 1.0, 2.0, 3.0 ] );
101+
y = new Float32Array( x.length );
102+
103+
strided( x.length, 'float32', x, 1, 'float32', y, 1, accessor );
104+
// y => <Float32Array>[ 10.0, 20.0, 30.0 ]
105+
```
106+
107+
The function accepts the following arguments:
108+
109+
- **fcns**: list of strided array functions.
110+
- **types**: one-dimensional list of strided array argument [data types][@stdlib/strided/dtypes]. The length of `types` must be the number of strided array functions multiplied by `nin+nout`. If `fcns` is a function, rather than a list, the number of strided array functions is computed as `types.length / (nin+nout)`.
111+
- **data**: strided array function data (e.g., callbacks). If a list, the length of `data` must equal the number of strided array functions. If `null`, a returned strided array function interface does **not** provide a `data` argument to an invoked strided array function.
112+
- **nargs**: total number of strided array function interface arguments (including data types, strides, offsets, and the callback function).
113+
- **nin**: number of input strided arrays.
114+
- **nout**: number of output strided arrays.
115+
116+
</section>
117+
118+
<!-- /.usage -->
119+
120+
<section class="notes">
121+
122+
## Notes
123+
124+
- Without offsets, a returned strided array function interface has the following signature:
125+
126+
```text
127+
f( N, dtypeX, x, strideX, dtypeY, y, strideY, ..., clbk[, thisArg] )
128+
```
129+
130+
where
131+
132+
- **N**: number of indexed elements.
133+
- **dtypeX**: [data type][@stdlib/strided/dtypes] for `x`.
134+
- **x**: strided array.
135+
- **strideX**: index increment for `x`.
136+
- **dtypeY**: [data type][@stdlib/strided/dtypes] for `y`.
137+
- **y**: strided array.
138+
- **strideY**: index increment for `y`.
139+
- **...**: additional strided arrays and associated [data types][@stdlib/strided/dtypes] and strides.
140+
- **clbk**: callback function.
141+
- **thisArg**: callback function execution context.
142+
143+
- The number of strided array function interface parameters is derived from `nargs`, the number of input strided arrays is derived from `nin`, and the number of output strided arrays is derived from `nout`.
144+
145+
- Without offsets, the number of parameters must obey the following relation:
146+
147+
```text
148+
nargs = 3*(nout+nin) + 2
149+
```
150+
151+
- With offsets, the number of parameters must obey the following relation:
152+
153+
```text
154+
nargs = 4*(nout+nin) + 2
155+
```
156+
157+
- With offsets, a returned strided array function interface has the following signature:
158+
159+
```text
160+
f( N, dtypeX, x, strideX, offsetX, dtypeY, y, strideY, offsetY, ..., clbk[, thisArg] )
161+
```
162+
163+
where
164+
165+
- **N**: number of indexed elements.
166+
- **dtypeX**: [data type][@stdlib/strided/dtypes] for `x`.
167+
- **x**: strided array.
168+
- **strideX**: index increment for `x`.
169+
- **offsetX**: starting index for `x`.
170+
- **dtypeY**: [data type][@stdlib/strided/dtypes] for `y`.
171+
- **y**: strided array.
172+
- **strideY**: index increment for `y`.
173+
- **offsetY**: starting index for `y`.
174+
- **...**: additional strided arrays and associated [data types][@stdlib/strided/dtypes], strides, and offsets.
175+
- **clbk**: callback function.
176+
- **thisArg**: callback function execution context.
177+
178+
The choice of which strided array function interface to return depends on the use case. The former is suitable for typed array views; while the latter affords alternative indexing semantics more suitable for n-dimensional arrays (ndarrays).
179+
180+
- Without offsets, a strided array function (i.e., a value provided for the `fcns` argument) should have the following signature:
181+
182+
```text
183+
f( arrays, shape, strides, [data, ]clbk[, thisArg] )
184+
```
185+
186+
where
187+
188+
- **arrays**: array containing strided input and output arrays.
189+
- **shape**: array containing a single element, the number of indexed elements.
190+
- **strides**: array containing the stride lengths for the strided input and output arrays.
191+
- **data**: strided array function data (e.g., a callback).
192+
- **clbk**: callback function.
193+
- **thisArg**: callback function execution context.
194+
195+
- With offsets, a strided array function should have the following signature:
196+
197+
```text
198+
f( arrays, shape, strides, offsets, [data, ]clbk[, thisArg] )
199+
```
200+
201+
where
202+
203+
- **offsets**: array containing the starting indices (i.e., index offsets) for the strided input and output arrays.
204+
205+
- For convenience, a single strided array function may be provided which will be invoked whenever the strided array argument data types match a sequence of types in `types`. Providing a single strided array function is particularly convenient for the case where, regardless of array data types, traversing arrays remains the same, but the strided array function `data` differs (e.g., callbacks which differ based on the array data types). For example, the following
206+
207+
<!-- eslint-disable array-element-newline -->
208+
209+
```javascript
210+
var unaryBy = require( '@stdlib/strided/base/unary-by' );
211+
212+
function foo( x ) {
213+
return x * 10.0;
214+
}
215+
216+
function bar( x ) {
217+
return x * 5.0;
218+
}
219+
220+
function accessor( v ) {
221+
return v;
222+
}
223+
224+
var fcns = [
225+
unaryBy,
226+
unaryBy
227+
];
228+
var types = [
229+
'float64', 'float64',
230+
'float32', 'float32'
231+
];
232+
var data = [
233+
foo,
234+
bar
235+
];
236+
237+
var strided = dispatchBy( fcns, types, data, 8, 1, 1 );
238+
```
239+
240+
is equivalent to
241+
242+
<!-- eslint-disable array-element-newline -->
243+
244+
```javascript
245+
var unaryBy = require( '@stdlib/strided/base/unary-by' );
246+
247+
function foo( x ) {
248+
return x * 10.0;
249+
}
250+
251+
function bar( x ) {
252+
return x * 5.0;
253+
}
254+
255+
function accessor( v ) {
256+
return v;
257+
}
258+
259+
var types = [
260+
'float64', 'float64',
261+
'float32', 'float32'
262+
];
263+
var data = [
264+
foo,
265+
bar
266+
];
267+
268+
var strided = dispatchBy( unaryBy, types, data, 8, 1, 1 );
269+
```
270+
271+
</section>
272+
273+
<!-- /.notes -->
274+
275+
<section class="examples">
276+
277+
## Examples
278+
279+
<!-- eslint no-undef: "error" -->
280+
281+
```javascript
282+
var unaryBy = require( '@stdlib/strided/base/unary-by' ).ndarray;
283+
var abs = require( '@stdlib/math/base/special/abs' );
284+
var identity = require( '@stdlib/math/base/special/identity' );
285+
var Float64Array = require( '@stdlib/array/float64' );
286+
var dispatchBy = require( '@stdlib/strided/dispatch-by' );
287+
288+
var types = [ 'float64', 'float64' ];
289+
290+
var data = [
291+
abs
292+
];
293+
294+
var strided = dispatchBy( unaryBy, types, data, 10, 1, 1 );
295+
296+
var x = new Float64Array( [ -1.0, -2.0, -3.0, -4.0, -5.0 ] );
297+
var y = new Float64Array( [ 0.0, 0.0, 0.0, 0.0, 0.0 ] );
298+
299+
strided( 3, 'float64', x, 1, 2, 'float64', y, 1, 2, identity );
300+
console.log( y );
301+
// => <Float64Array>[ 0.0, 0.0, 3.0, 4.0, 5.0 ]
302+
```
303+
304+
</section>
305+
306+
<!-- /.examples -->
307+
308+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
309+
310+
<section class="related">
311+
312+
</section>
313+
314+
<!-- /.related -->
315+
316+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
317+
318+
<section class="links">
319+
320+
[@stdlib/strided/dtypes]: https://github.com/stdlib-js/stdlib
321+
322+
</section>
323+
324+
<!-- /.links -->

0 commit comments

Comments
 (0)