Skip to content

Commit f3d3f4f

Browse files
committed
feat: add a factory method to allow for partial application
1 parent ecb0cf1 commit f3d3f4f

11 files changed

Lines changed: 934 additions & 121 deletions

File tree

lib/node_modules/@stdlib/ndarray/base/ind/README.md

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,9 @@ idx = ind( -1, 9, 'throw' );
5555

5656
idx = ind( 10, 9, 'throw' );
5757
// throws <RangeError>
58-
```
59-
60-
The function supports the following modes:
61-
62-
- **throw**: specifies that the function should throw an error when an index is outside the interval `[0, max]`.
63-
- **normalize**: specifies that the function should normalize negative indices and throw an error when an index is outside the interval `[-max-1, max]`.
64-
- **wrap**: specifies that the function should wrap around an index using modulo arithmetic.
65-
- **clamp**: specifies that the function should set an index less than `0` to `0` (minimum index) and set an index greater than `max` to `max`.
6658

67-
```javascript
68-
var idx = ind( 2, 9, 'wrap' );
59+
// Wrapping indices around using modulo arithmetic:
60+
idx = ind( 2, 9, 'wrap' );
6961
// returns 2
7062

7163
idx = ind( 10, 9, 'wrap' );
@@ -74,6 +66,7 @@ idx = ind( 10, 9, 'wrap' );
7466
idx = ind( -1, 9, 'wrap' );
7567
// returns 9
7668

69+
// Clamping indices to first and last indices:
7770
idx = ind( 2, 9, 'clamp' );
7871
// returns 2
7972

@@ -83,13 +76,36 @@ idx = ind( 10, 9, 'clamp' );
8376
idx = ind( -1, 9, 'clamp' );
8477
// returns 0
8578

79+
// Normalizing negative indices:
8680
idx = ind( 2, 9, 'normalize' );
8781
// returns 2
8882

8983
idx = ind( -4, 9, 'normalize' );
9084
// returns 6
9185
```
9286

87+
#### ind.factory( mode )
88+
89+
Returns a function for returning an index according to a provided index `mode`.
90+
91+
```javascript
92+
var fcn = ind.factory( 'clamp' );
93+
94+
var idx = fcn( 2, 9 );
95+
// returns 2
96+
97+
idx = fcn( 10, 9 );
98+
// returns 9
99+
100+
idx = fcn( -1, 9 );
101+
// returns 0
102+
```
103+
104+
The function returns a function accepts the following arguments:
105+
106+
- **index**: input index.
107+
- **max**: maximum index value.
108+
93109
</section>
94110

95111
<!-- /.usage -->
@@ -98,6 +114,15 @@ idx = ind( -4, 9, 'normalize' );
98114

99115
<section class="notes">
100116

117+
## Notes
118+
119+
- Both functions support the following modes:
120+
121+
- **throw**: specifies that the function should throw an error when an index is outside the interval `[0, max]`.
122+
- **normalize**: specifies that the function should normalize negative indices and throw an error when an index is outside the interval `[-max-1, max]`.
123+
- **wrap**: specifies that the function should wrap around an index using modulo arithmetic.
124+
- **clamp**: specifies that the function should set an index less than `0` to `0` (minimum index) and set an index greater than `max` to `max`.
125+
101126
</section>
102127

103128
<!-- /.notes -->
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2023 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 isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
25+
var isFunction = require( '@stdlib/assert/is-function' );
26+
var pkg = require( './../package.json' ).name;
27+
var factory = require( './../lib' ).factory;
28+
29+
30+
// MAIN //
31+
32+
bench( pkg+':factory', function benchmark( b ) {
33+
var modes;
34+
var out;
35+
var i;
36+
37+
modes = [
38+
'throw',
39+
'clamp',
40+
'wrap',
41+
'normalize'
42+
];
43+
44+
b.tic();
45+
for ( i = 0; i < b.iterations; i++ ) {
46+
out = factory( modes[ i%modes.length ] );
47+
if ( typeof out !== 'function' ) {
48+
b.fail( 'should return a function' );
49+
}
50+
}
51+
b.toc();
52+
if ( !isFunction( out ) ) {
53+
b.fail( 'should return a function' );
54+
}
55+
b.pass( 'benchmark finished' );
56+
b.end();
57+
});
58+
59+
bench( pkg+':factory:mode=clamp', function benchmark( b ) {
60+
var ind;
61+
var out;
62+
var idx;
63+
var i;
64+
65+
ind = factory( 'clamp' );
66+
67+
b.tic();
68+
for ( i = 0; i < b.iterations; i++ ) {
69+
idx = (i%100) - 50;
70+
out = ind( idx, 10 );
71+
if ( out !== out ) {
72+
b.fail( 'should not return NaN' );
73+
}
74+
}
75+
b.toc();
76+
if ( !isNonNegativeInteger( out ) ) {
77+
b.fail( 'should return a nonnegative integer' );
78+
}
79+
b.pass( 'benchmark finished' );
80+
b.end();
81+
});
82+
83+
bench( pkg+':factory:mode=wrap', function benchmark( b ) {
84+
var ind;
85+
var out;
86+
var idx;
87+
var i;
88+
89+
ind = factory( 'wrap' );
90+
91+
b.tic();
92+
for ( i = 0; i < b.iterations; i++ ) {
93+
idx = (i%100) - 50;
94+
out = ind( idx, 10 );
95+
if ( out !== out ) {
96+
b.fail( 'should not return NaN' );
97+
}
98+
}
99+
b.toc();
100+
if ( !isNonNegativeInteger( out ) ) {
101+
b.fail( 'should return a nonnegative integer' );
102+
}
103+
b.pass( 'benchmark finished' );
104+
b.end();
105+
});
106+
107+
bench( pkg+':factory:mode=throw', function benchmark( b ) {
108+
var ind;
109+
var out;
110+
var idx;
111+
var i;
112+
113+
ind = factory( 'throw' );
114+
115+
b.tic();
116+
for ( i = 0; i < b.iterations; i++ ) {
117+
idx = i % 11;
118+
out = ind( idx, 10 );
119+
if ( out !== out ) {
120+
b.fail( 'should not return NaN' );
121+
}
122+
}
123+
b.toc();
124+
if ( !isNonNegativeInteger( out ) ) {
125+
b.fail( 'should return a nonnegative integer' );
126+
}
127+
b.pass( 'benchmark finished' );
128+
b.end();
129+
});
130+
131+
bench( pkg+':factory:mode=normalize', function benchmark( b ) {
132+
var ind;
133+
var out;
134+
var idx;
135+
var i;
136+
137+
ind = factory( 'normalize' );
138+
139+
b.tic();
140+
for ( i = 0; i < b.iterations; i++ ) {
141+
idx = (i%21) - 10;
142+
out = ind( idx, 10 );
143+
if ( out !== out ) {
144+
b.fail( 'should not return NaN' );
145+
}
146+
}
147+
b.toc();
148+
if ( !isNonNegativeInteger( out ) ) {
149+
b.fail( 'should return a nonnegative integer' );
150+
}
151+
b.pass( 'benchmark finished' );
152+
b.end();
153+
});

lib/node_modules/@stdlib/ndarray/base/ind/benchmark/benchmark.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
// MODULES //
2222

2323
var bench = require( '@stdlib/bench' );
24-
var randu = require( '@stdlib/random/base/randu' );
25-
var floor = require( '@stdlib/math/base/special/floor' );
2624
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
2725
var pkg = require( './../package.json' ).name;
2826
var ind = require( './../lib' );
@@ -37,7 +35,7 @@ bench( pkg+':mode=clamp', function benchmark( b ) {
3735

3836
b.tic();
3937
for ( i = 0; i < b.iterations; i++ ) {
40-
idx = floor( randu()*100.0 ) - 50.0;
38+
idx = (i%100) - 50;
4139
out = ind( idx, 10, 'clamp' );
4240
if ( out !== out ) {
4341
b.fail( 'should not return NaN' );
@@ -58,7 +56,7 @@ bench( pkg+':mode=wrap', function benchmark( b ) {
5856

5957
b.tic();
6058
for ( i = 0; i < b.iterations; i++ ) {
61-
idx = floor( randu()*100.0 ) - 50.0;
59+
idx = (i%100) - 50;
6260
out = ind( idx, 10, 'wrap' );
6361
if ( out !== out ) {
6462
b.fail( 'should not return NaN' );
@@ -79,7 +77,7 @@ bench( pkg+':mode=throw', function benchmark( b ) {
7977

8078
b.tic();
8179
for ( i = 0; i < b.iterations; i++ ) {
82-
idx = floor( randu()*11.0 );
80+
idx = i % 11;
8381
out = ind( idx, 10, 'throw' );
8482
if ( out !== out ) {
8583
b.fail( 'should not return NaN' );
@@ -100,7 +98,7 @@ bench( pkg+':mode=normalize', function benchmark( b ) {
10098

10199
b.tic();
102100
for ( i = 0; i < b.iterations; i++ ) {
103-
idx = floor( randu()*20.0 ) - 10.0;
101+
idx = (i%21) - 10;
104102
out = ind( idx, 10, 'normalize' );
105103
if ( out !== out ) {
106104
b.fail( 'should not return NaN' );

lib/node_modules/@stdlib/ndarray/base/ind/docs/repl.txt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,41 @@
4444
> idx = {{alias}}( -4, 10, 'normalize' )
4545
7
4646

47+
48+
{{alias}}.factory( mode )
49+
Returns a function for returning an index according to a provided index
50+
mode.
51+
52+
The function returns a function which accepts the following arguments:
53+
54+
- idx: index
55+
- max: maximum index value
56+
57+
Parameters
58+
----------
59+
mode: string
60+
Specifies how to handle an index outside the interval [0, max]. If equal
61+
to 'throw', the function throws an error. If equal to 'normalize', the
62+
function throws an error if provided an out-of-bounds normalized index.
63+
If equal to 'wrap', the function wraps around an index using modulo
64+
arithmetic. If equal to 'clamp', the function sets an index to either 0
65+
(minimum index) or the maximum index.
66+
67+
Returns
68+
-------
69+
fcn: Function
70+
Function for returning an index.
71+
72+
Examples
73+
--------
74+
> var f = {{alias}}.factory( 'clamp' );
75+
> var idx = f( 2, 10 )
76+
2
77+
> idx = f( -4, 10 )
78+
0
79+
> idx = f( 13, 10 )
80+
10
81+
4782
See Also
4883
--------
4984

0 commit comments

Comments
 (0)