Skip to content

Commit 8ca55e1

Browse files
committed
Add abstraction layer for performing multiple dispatch for unary mathematical functions
1 parent 4312323 commit 8ca55e1

27 files changed

+3379
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2021 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+
# Unary
22+
23+
> Multiple dispatch for unary mathematical functions.
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 dispatch = require( '@stdlib/math/tools/unary' );
41+
```
42+
43+
#### dispatch( table )
44+
45+
Returns a function which dispatches to specified functions based on input argument types.
46+
47+
<!-- eslint-disable array-element-newline -->
48+
49+
```javascript
50+
var nabs = require( '@stdlib/math/base/special/abs' );
51+
var dabs = require( '@stdlib/math/strided/special/dabs' );
52+
var sabs = require( '@stdlib/math/strided/special/sabs' );
53+
var gabs = require( '@stdlib/math/strided/special/abs' );
54+
55+
var table = {
56+
'scalar': [
57+
'number', nabs
58+
],
59+
'array': [
60+
'float64', dabs,
61+
'float32', sabs,
62+
'generic', gabs
63+
],
64+
'ndarray': [
65+
'float64', dabs.ndarray,
66+
'float32', sabs.ndarray,
67+
'generic', gabs.ndarray
68+
]
69+
};
70+
71+
var abs = dispatch( table );
72+
```
73+
74+
The function accepts the following arguments:
75+
76+
- **table**: resolution table object which maps input argument types to corresponding implementations.
77+
78+
A `table` resolution object may contain one or more of the following fields:
79+
80+
- **scalar**: strided look-up table for scalar arguments. Implementation functions must accept a single input argument: a scalar value. Supported data types: `'number'` and `'complex'`.
81+
82+
- **array**: strided look-up table for array-like object arguments. Implementation functions must follow strided array interface argument conventions:
83+
84+
```text
85+
fcn( N, x, strideX, y, strideY )
86+
```
87+
88+
where
89+
90+
- **N**: number of indexed elements.
91+
- **x**: input strided array.
92+
- **strideX**: index increment for `x`.
93+
- **y**: destination strided array.
94+
- **strideY**: index increment for `y`.
95+
96+
Supported array data types consist of all supported [ndarray][@stdlib/ndarray/dtypes] data types.
97+
98+
- **ndarray**: strided look-up table for [`ndarray`][@stdlib/ndarray/ctor] arguments. Implementation functions must follow strided array ndarray interface argument conventions:
99+
100+
```text
101+
fcn( N, x, strideX, offsetX, y, strideY, offsetY )
102+
```
103+
104+
where
105+
106+
- **N**: number of indexed elements.
107+
- **x**: input strided array (i.e., underlying input [`ndarray`][@stdlib/ndarray/ctor] buffer).
108+
- **strideX**: index increment for `x`.
109+
- **offsetX**: starting index for `x`.
110+
- **y**: destination strided array (i.e., underlying output [`ndarray`][@stdlib/ndarray/ctor] buffer).
111+
- **strideY**: index increment for `y`.
112+
- **offsetY**: starting index for `y`.
113+
114+
Supported data types consist of all supported [ndarray][@stdlib/ndarray/dtypes] data types.
115+
116+
Each strided look-up table should be comprised as follows:
117+
118+
```text
119+
[ <dtype>, <fcn>, <dtype>, <fcn>, ... ]
120+
```
121+
122+
If an argument's data type is **not** found in the argument's corresponding look-up table and if a `'generic'` data type is present in that same table, the returned dispatch function will resolve the "generic" implementation. In other words, an implementation associated with a `'generic'` data type will be treated as the default implementation.
123+
124+
If unable to resolve an implementation for a provided argument data type, the returned function throws an error.
125+
126+
* * *
127+
128+
#### dispatcher( x )
129+
130+
Dispatches to an underlying implementation based the data type of `x`.
131+
132+
<!-- eslint-disable array-element-newline -->
133+
134+
```javascript
135+
var nabs = require( '@stdlib/math/base/special/abs' );
136+
var dabs = require( '@stdlib/math/strided/special/dabs' );
137+
var sabs = require( '@stdlib/math/strided/special/sabs' );
138+
var gabs = require( '@stdlib/math/strided/special/abs' );
139+
140+
var table = {
141+
'scalar': [
142+
'number', nabs
143+
],
144+
'array': [
145+
'float64', dabs,
146+
'float32', sabs,
147+
'generic', gabs
148+
],
149+
'ndarray': [
150+
'float64', dabs.ndarray,
151+
'float32', sabs.ndarray,
152+
'generic', gabs.ndarray
153+
]
154+
};
155+
156+
var abs = dispatch( table );
157+
158+
var y = abs( -1.0 );
159+
// returns 1.0
160+
```
161+
162+
The returned dispatch function accepts the following arguments:
163+
164+
- **x**: input [`ndarray`][@stdlib/ndarray/ctor], array-like object, or number. If provided an [`ndarray`][@stdlib/ndarray/ctor] or array-like object, the function performs element-wise computation.
165+
166+
If provided an [`ndarray`][@stdlib/ndarray/ctor], the function returns an [`ndarray`][@stdlib/ndarray/ctor] having the same shape and data type as `x`.
167+
168+
<!-- eslint-disable array-element-newline -->
169+
170+
```javascript
171+
var dabs = require( '@stdlib/math/strided/special/dabs' );
172+
var sabs = require( '@stdlib/math/strided/special/sabs' );
173+
var gabs = require( '@stdlib/math/strided/special/abs' );
174+
var array = require( '@stdlib/ndarray/array' );
175+
176+
var table = {
177+
'ndarray': [
178+
'float64', dabs.ndarray,
179+
'float32', sabs.ndarray,
180+
'generic', gabs.ndarray
181+
]
182+
};
183+
184+
var abs = dispatch( table );
185+
186+
var x = array( [ [ -1.0, -2.0 ], [ -3.0, -4.0 ] ] ); // 2x2
187+
var y = abs( x );
188+
// returns <ndarray>
189+
190+
var v = y.get( 0, 1 );
191+
// returns 2.0
192+
```
193+
194+
If provided an array-like object, the function returns an array-like object having the same length and data type as `x`.
195+
196+
<!-- eslint-disable array-element-newline -->
197+
198+
```javascript
199+
var dabs = require( '@stdlib/math/strided/special/dabs' );
200+
var sabs = require( '@stdlib/math/strided/special/sabs' );
201+
var gabs = require( '@stdlib/math/strided/special/abs' );
202+
var Float64Array = require( '@stdlib/array/float64' );
203+
204+
var table = {
205+
'array': [
206+
'float64', dabs,
207+
'float32', sabs,
208+
'generic', gabs
209+
]
210+
};
211+
212+
var abs = dispatch( table );
213+
214+
var x = new Float64Array( [ -1.0, -2.0 ] );
215+
var y = abs( x );
216+
// returns <Float64Array>[ 1.0, 2.0 ]
217+
```
218+
219+
</section>
220+
221+
<!-- /.usage -->
222+
223+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
224+
225+
<section class="notes">
226+
227+
</section>
228+
229+
<!-- /.notes -->
230+
231+
<!-- Package usage examples. -->
232+
233+
* * *
234+
235+
<section class="examples">
236+
237+
## Examples
238+
239+
<!-- eslint-disable array-element-newline -->
240+
241+
<!-- eslint no-undef: "error" -->
242+
243+
```javascript
244+
var nabs = require( '@stdlib/math/base/special/abs' );
245+
var dabs = require( '@stdlib/math/strided/special/dabs' );
246+
var sabs = require( '@stdlib/math/strided/special/sabs' );
247+
var gabs = require( '@stdlib/math/strided/special/abs' );
248+
var Float64Array = require( '@stdlib/array/float64' );
249+
var array = require( '@stdlib/ndarray/array' );
250+
var ind2sub = require( '@stdlib/ndarray/ind2sub' );
251+
var dispatch = require( '@stdlib/math/tools/unary' );
252+
253+
var table;
254+
var sub;
255+
var abs;
256+
var sh;
257+
var x;
258+
var y;
259+
var i;
260+
261+
// Define a table for resolving unary functions based on argument data types:
262+
table = {
263+
'scalar': [
264+
'number', nabs
265+
],
266+
'array': [
267+
'float64', dabs,
268+
'float32', sabs,
269+
'generic', gabs
270+
],
271+
'ndarray': [
272+
'float64', dabs.ndarray,
273+
'float32', sabs.ndarray,
274+
'generic', gabs.ndarray
275+
]
276+
};
277+
278+
// Create a function which dispatches based on argument data types:
279+
abs = dispatch( table );
280+
281+
// Provide a number...
282+
y = abs( -1.0 );
283+
console.log( 'x = %d => abs(x) = %d', -1.0, y );
284+
285+
// Provide an array-like object...
286+
x = new Float64Array( [ -1.0, -2.0, -3.0 ] );
287+
y = abs( x );
288+
for ( i = 0; i < x.length; i++ ) {
289+
console.log( 'x_%d = %d => abs(x_%d) = %d', i, x[ i ], i, y[ i ] );
290+
}
291+
292+
// Provide an ndarray...
293+
x = array( [ [ -1.0, -2.0 ], [ -3.0, -4.0 ] ] );
294+
sh = x.shape;
295+
296+
y = abs( x );
297+
for ( i = 0; i < x.length; i++ ) {
298+
sub = ind2sub( sh, i );
299+
console.log( 'x_%d%d = %d => abs(x_%d%d) = %d', sub[ 0 ], sub[ 1 ], x.iget( i ), sub[ 0 ], sub[ 1 ], y.iget( i ) );
300+
}
301+
```
302+
303+
</section>
304+
305+
<!-- /.examples -->
306+
307+
<!-- 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. -->
308+
309+
<section class="references">
310+
311+
</section>
312+
313+
<!-- /.references -->
314+
315+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
316+
317+
<section class="links">
318+
319+
[@stdlib/ndarray/ctor]: https://github.com/stdlib-js/stdlib
320+
321+
[@stdlib/ndarray/dtypes]: https://github.com/stdlib-js/stdlib
322+
323+
</section>
324+
325+
<!-- /.links -->

0 commit comments

Comments
 (0)